web-dev-qa-db-fra.com

Gardez l'élément du milieu centré lorsque les éléments latéraux ont des largeurs différentes

enter image description here

Imaginez la disposition suivante, où les points représentent l'espace entre les cases:

[Left box]......[Center box]......[Right box]

Lorsque je supprime la case de droite, j'aime bien que la case du centre soit toujours au centre, comme ceci:

[Left box]......[Center box].................

La même chose vaut pour si je supprimerais la case de gauche.

................[Center box].................

Désormais, lorsque le contenu de la zone centrale s’allonge, il occupe tout l’espace disponible nécessaire tout en restant centré. Les cases gauche et droite ne seront jamais réduites et donc quand il n'y a plus d'espace, le overflow:hidden et text-overflow: Ellipsis viendra en effet pour casser le contenu;

[Left box][Center boxxxxxxxxxxxxx][Right box]

Tout ce qui précède est ma situation idéale, mais je ne sais pas comment obtenir cet effet. Parce que quand je crée une structure flex comme ceci:

.parent {
    display : flex; // flex box
    justify-content : space-between; // horizontal alignment
    align-content   : center; // vertical alignment
}

Si les cases gauche et droite ont exactement la même taille, j'obtiens l'effet souhaité. Cependant, lorsque l'un des deux est d'une taille différente, la case centrée n'est plus vraiment centrée.

Y a-t-il quelqu'un qui peut m'aider?

Mettre à jour

UNE justify-self serait bien, ce serait l’idéal:

.leftBox {
     justify-self : flex-start;
}

.rightBox {
    justify-self : flex-end;
}
119
Mark

Si les cases gauche et droite ont exactement la même taille, j'obtiens l'effet désiré. Cependant, lorsque l’une des deux est de taille différente, la case centrée n’est plus vraiment centrée. Y a-t-il quelqu'un qui peut m'aider?

Voici une méthode utilisant flexbox pour centrer l'élément du milieu, quelle que soit la largeur de la fratrie.

Principales caractéristiques:

  • cSS pur
  • pas de positionnement absolu
  • non JS/jQuery

Utilisez des conteneurs flexibles et des marges auto imbriquées:

.container {
  display: flex;
}
.box {
  flex: 1;
  display: flex;
  justify-content: center;
}

.box:first-child > span { margin-right: auto; }

.box:last-child  > span { margin-left: auto;  }

/* non-essential */
.box {
  align-items: center;
  border: 1px solid #ccc;
  background-color: lightgreen;
  height: 40px;
}
p {
  text-align: center;
  margin: 5px 0 0 0;
}
<div class="container">
  <div class="box"><span>short text</span></div>
  <div class="box"><span>centered text</span></div>
  <div class="box"><span>loooooooooooooooong text</span></div>
</div>
<p>&#8593;<br>true center</p>

Voilà comment cela fonctionne:

  • La div de niveau supérieur (.container) est un conteneur flexible.
  • Chaque enfant div (.box) est maintenant un élément flexible.
  • Chaque .box l'article est donné flex: 1 afin de répartir équitablement l’espace conteneur ( plus de détails ).
  • Désormais, les éléments occupent tout l’espace de la ligne et ont la même largeur.
  • Faites de chaque article un conteneur flex (imbriqué) et ajoutez justify-content: center.
  • Maintenant, chaque élément span est un élément flex centré.
  • Utilisez les marges flex auto pour décaler les spans externes à gauche et à droite.

Vous pouvez aussi oublier justify-content et utilisez auto marges exclusivement.

Mais justify-content peut fonctionner ici car auto les marges ont toujours la priorité.

8.1. Alignement sur auto marges

Avant l'alignement via justify-content et align-self, tout espace libre positif est distribué aux marges automatiques dans cette dimension.

90
Michael_B
  1. Utilisez trois articles flexibles dans le conteneur
  2. Ensemble flex: 1 aux premier et dernier. Cela les fait grandir également pour occuper l’espace disponible laissé par le milieu.
  3. Ainsi, le milieu aura tendance à être centré.
  4. Toutefois, si le premier ou le dernier élément a un contenu large, cet élément flexible augmentera également en raison du nouveau min-width: auto valeur initiale.

    Remarque Chrome ne semble pas implémenter cela correctement. Cependant, vous pouvez définir min-width à -webkit-max-content ou -webkit-min-content et cela fonctionnera aussi.

  5. Ce n'est que dans ce cas que l'élément du milieu sera poussé hors du centre.

.outer-wrapper {
  display: flex;
}
.item {
  background: Lime;
  margin: 5px;
}
.left.inner-wrapper, .right.inner-wrapper {
  flex: 1;
  display: flex;
  min-width: -webkit-min-content; /* Workaround to Chrome bug */
}
.right.inner-wrapper {
  justify-content: flex-end;
}
.animate {
  animation: anim 5s infinite alternate;
}
@keyframes anim {
  from { min-width: 0 }
  to { min-width: 100vw; }
}
<div class="outer-wrapper">
  <div class="left inner-wrapper">
    <div class="item animate">Left</div>
  </div>
  <div class="center inner-wrapper">
    <div class="item">Center</div>
  </div>
  <div class="right inner-wrapper">
    <div class="item">Right</div>
  </div>
</div>
<!-- Analogous to above --> <div class="outer-wrapper"><div class="left inner-wrapper"><div class="item">Left</div></div><div class="center inner-wrapper"><div class="item animate">Center</div></div><div class="right inner-wrapper"><div class="item">Right</div></div></div><div class="outer-wrapper"><div class="left inner-wrapper"><div class="item">Left</div></div><div class="center inner-wrapper"><div class="item">Center</div></div><div class="right inner-wrapper"><div class="item animate">Right</div></div></div>
24
Oriol

Vous pouvez faire ça comme ça:

.bar {
    display: flex;    
    background: #B0BEC5;
}
.l {
    width: 50%;
    flex-shrink: 1;
    display: flex;
}
.l-content {
    background: #9C27B0;
}
.m { 
    flex-shrink: 0;
}
.m-content {    
    text-align: center;
    background: #2196F3;
}
.r {
    width: 50%;
    flex-shrink: 1;
    display: flex;
    flex-direction: row-reverse;
}
.r-content { 
    background: #E91E63;
}
<div class="bar">
    <div class="l">
        <div class="l-content">This is really long content.  More content.  So much content.</div>
    </div>
    <div class="m">
        <div class="m-content">This will always be in the center.</div>
    </div>
    <div class="r">
        <div class="r-content">This is short.</div>
    </div>
</div>
6
Michael Morton

Au lieu d'utiliser par défaut flexbox, l'utilisation de grid le résout en 2 lignes de CSS sans annotation supplémentaire à l'intérieur des enfants de niveau supérieur.

HTML:

<header class="header">
  <div class="left">variable content</div>
  <div class="middle">variable content</div>
  <div class="right">variable content which happens to be very long</div>
</header>

CSS:

.header {
  display: grid;
  grid-template-columns: [first] 20% auto [last] 20%;
}
.middle {
  /* use either */
  margin: 0 auto;
  /* or */
  text-align: center;
}

La Flexbox est géniale mais ne devrait pas être la solution à tout. Dans ce cas, la grille est clairement l'option la plus propre.

Même fait un codepen pour votre plaisir de tester: https://codepen.io/anon/pen/mooQOV

4
Johan