it-swarm.com.ru

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

enter image description here

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

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

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

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

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

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

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

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

Все вышесказанное - моя идеальная ситуация, но я не знаю, как этого добиться. Потому что, когда я создаю гибкую структуру, вот так:

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

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

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

Update

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

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

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

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

Вот метод, использующий 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 для равномерного распределения пространства контейнера ( подробнее ).
  • Теперь элементы занимают все пространство в строке и имеют одинаковую ширину.
  • Сделайте каждый элемент гибким контейнером (вложенным) и добавьте justify-content: center.
  • Теперь каждый элемент span представляет собой центрированный гибкий элемент.
  • Используйте гибкие поля auto для смещения внешних spans влево и вправо.

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

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

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

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

79
Michael_B
  1. Используйте три гибких предмета в контейнере
  2. Установите flex: 1 на первый и последний. Это заставляет их расти одинаково, чтобы заполнить доступное пространство, оставленное средним.
  3. Таким образом, средний будет стремиться к центру.
  4. Однако, если первый или последний элемент имеет широкое содержимое, этот гибкий элемент также будет расти из-за нового начального значения 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>
21
Oriol

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

.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

Вместо использования по умолчанию flexbox, использование grid решает его в 2 строки CSS без дополнительной разметки внутри дочерних элементов верхнего уровня.

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;
}

Flexbox качается, но не должен быть ответом за все. В этом случае сетка явно самый чистый вариант.

Даже сделал кодовую ручку для вашего удовольствия от тестирования: https://codepen.io/anon/pen/mooQOV

1
Johan