web-dev-qa-db-fra.com

Comment puis-je avoir une position: fixe; comportement pour un élément de taille flexbox?

J'ai une div appelée .side-el que j'aimerais avoir dans une position: fixe; comportement, mais dès que j'applique position fixe la largeur alterne de la droite. La bonne largeur serait celle définie par flexbox. Comment puis-je atteindre cet objectif?

.container {
  -webkit-align-content: flex-start;
  align-content: flex-start;
  -webkit-align-items: flex-start;
  align-items: flex-start;
  display: -webkit-flex;
  display: flex;
  -webkit-flex-direction: row;
  flex-direction: row;
  -webkit-flex-wrap: wrap;
  flex-wrap: wrap;
  -webkit-justify-content: flex-start;
  justify-content: flex-start;
  
  * {
    box-sizing: border-box;
    -webkit-flex-grow: 1;
    flex-grow: 1;
    -webkit-flex-shrink: 0;
    flex-shrink: 0;
  }
}


.main-el {
  box-sizing: border-box;
  padding:0 2em;
  width: 70%;
}

.side-el {
  box-sizing: border-box;
  width: 30%;
}
<div class="container" style="background-color: blue; height: 100px;">
  <div class="main-el">
    <div  style="background-color: red; height: 1000px;">content</div>
  </div>
  <div class="side-el" >
    <div style="background-color: red; height: 100px;">content</div>
  </div>
</div>
51
Daniel Schmidt

Tu ne peux pas.

Comme expliqué par le spécification CSS2.1 :

Les boîtes positionnées de manière absolue sont extraites du flux normal .

Et la spécification Flexible Box Layout confirme que:

Un enfant absolument positionné d'un conteneur flexible ne participe pas à la présentation flexible . Cependant, il participe à la étape de réorganisation (voir ordre ), ce qui a un effet sur leur ordre de peinture.

(Souligné par moi)

33
Oriol

@ Daniel, je sais que c'est très tard, mais ... bien que la réponse acceptée soit correcte, je ne pense pas que cela soit très utile. J'avais la même question (comment je suis tombé sur ce message), et la solution que je vais utiliser consiste à envelopper l'élément de position fixe dans l'élément flex. Voici un (très moche) exemple

Balisage pertinent

  <aside class="Layout-aside" ng-class="{'isCollapsed': collapsed}" ng-controller="AsideCtrl">
    <div class="Layout-aside-inner">
      <button ng-click="collapsed = !collapsed">
        <span ng-show="collapsed">&gt;</span>
        <span ng-hide="collapsed">&lt;</span>
      </button>
      <ul class="Layout-aside-content">
        <li ng-repeat="i in items">{{i}}</li>
      </ul>
    </div>
  </aside>

CSS pertinentes

.Layout-aside {
  order: 0;
  min-width: 140px;
  width: 140px;
  background-color: rgba(0, 255, 0, .4);
  transition: width .4s, min-width .4s; 
}
.Layout-aside.isCollapsed {
  min-width: 25px;
  width: 25px;
}

.Layout-aside-inner {
  position: fixed;
}

.Layout-aside.isCollapsed .Layout-aside-inner {
  width: 25px;
}

.Layout-aside.isCollapsed .Layout-aside-content {
  opacity: 0;
}
38
o4ohel

Voici un moyen de faire cela inspiré par bootstrap:

.fixed-top {
  display: flex;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
}

Cela donne à votre flex-box un espace pour respirer et faire son truc. Si votre direction de flex est colonne, vous pouvez utiliser top, left, bottom au lieu.

Cela fonctionne car lorsque vous attribuez à un élément une position fixe et un left et right de 0 ou un top et bottom de 0, l'élément est étiré. pour remplir l’espace de gauche à droite ou de haut en bas. Cela permet à un flex-box d’utiliser la quantité d’espace attendue sans position fixe.

36
Wylliam Judd

Vous pouvez y parvenir avec une alternative css position: sticky

Cela fonctionne bien, mais le seul problème est le support du navigateur (juin 2018): https://caniuse.com/#feat=css-sticky

J'espère que ça ira mieux bientôt.

7
Juozas Rastenis

Une solution beaucoup plus simple serait d'utiliser overflow-y:scroll et height: 100vh sur le main-el récipient. Cela donnera l'apparence d'une position fixe au side-el conteneur sans recourir à la position: fixe.

5
Greg Beaver