Сохранить средний элемент по центру, когда боковые элементы имеют разную ширину


представьте себе следующий макет, где точки представляют собой пространство между коробками:

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

когда я удаляю правую коробку, мне нравится, чтобы центральная коробка все еще была в центре, например:

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

то же самое касается, если бы я удалил левую коробку.

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

теперь, когда содержимое в центральной коробке становится длиннее, оно будет занимать столько свободного места, сколько необходимо, оставаясь центрированным. Левый и правая коробка никогда не будет сжиматься и, таким образом, когда где нет места осталось overflow:hidden и text-overflow: ellipsis вступит в силу, чтобы разбить контент;

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

все вышесказанное является моим идеалом, но я понятия не имею, как достичь этого эффекта. Потому что когда я создаю структуру flex вот так:

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

если левая и правая коробки будут точно такого же размера, я получаю желаемый эффект. Однако, когда один из них из другого размера, центрированная коробка не является действительно больше по центру.

кто-нибудь, кто может мне помочь?

обновление

A justify-self было бы неплохо, это было бы идеально:

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

.rightBox {
    justify-self : flex-end;
}
3 63

3 ответа:

если слева и справа будут точно такого же размера, я получаю желаемый эффект. Однако, когда один из них имеет другой размер, центрированная коробка больше не центрирована. Кто-нибудь может мне помочь?

вот метод, использующий flexbox для центрирования среднего элемента, независимо от ширины братьев и сестер.

основные характеристики:

  • чистый CSS
  • нет абсолютного позиционирования
  • нет JS / jQuery

используйте вложенные контейнеры flex и auto поля:

.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>

вот как это работает:

  • div верхнего уровня (.container) - Это гибкий контейнер.
  • каждый ребенок div (.box) теперь является гибким элементом.
  • каждого .box пункт дается flex: 1 для равномерного распределения пространства контейнера (более подробная информация).
  • элементы занимают все места в ряду и имеют одинаковую ширину.
  • сделать каждый элемент (вложенный) flex контейнер и добавить justify-content: center.
  • теперь каждый span элемент-это центрированный гибкий элемент.
  • использовать flex auto поля для смены внешнего spans слева и справа.

вы также можете отказаться justify-content и использовать auto поля исключительно.

но justify-content можете работать здесь, потому что auto поля всегда имеют приоритет.

8.1. Выравнивание с auto поля

до выравнивания с помощью justify-content и align-self любой положительное свободное пространство распределяется на автоматические поля в этом измерении.

  1. используйте три гибких элемента в контейнере
  2. Set flex: 1 к первому и последнему. Это заставляет их расти одинаково, чтобы заполнить доступное пространство, оставленное средним.
  3. таким образом, средний будет иметь тенденцию быть центрированным.
  4. однако, если первый или последний элемент имеет широкий контент, этот элемент flex также будет расти из-за нового min-width: auto начальное значение.

    Примечание Chrome, похоже, не реализует это должным образом. Тем не менее, вы можете набор min-width до -webkit-max-content или -webkit-min-content и это тоже будет работать.

  5. только в этом случае средний элемент будет выталкиваться из центра.

.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>

вы можете сделать это так:

.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>