Выровняйте элементы Flexbox по горизонтали с помощью разворачиваемого элемента переменной ширины

Я хочу выровнять три элемента во флекс-боксе вот так. Контекст состоит в том, что это метки неизвестной длины (но переносимые) для ползунка / ряда кнопок неизвестной ширины (без оболочки) в опросе.

[L] [R] [variable width]

Как мне выровнять два верхних элемента по ширине нижнего элемента / середина, не фиксируя ширину контейнера (на самом деле неизвестная ширина элемента середина)?

Я подумал о том, чтобы поместить оставил и верно в другой гибкий бокс и использовать макет столбцов для верхнего контейнера. Мне не нравится такой способ, потому что мне пришлось бы нарушить истинный порядок содержимого (слева-посередине-справа), но я даже не мог заставить его работать таким образом.

div {
  border: 1px dotted;
}

.container {
  display: flex;
  flex-wrap: wrap;
  width: 300px; /* I want to get rid of this */
}

.left {
  order: 1;
  flex: 1 0;
}

.right {
  order: 2;
  flex: 1 0;
  text-align: right;
}

.middle {
  order: 3;
  flex: 2 0 auto;
}
<div class = "container">
  <div class = "left">
    left
  </div>
  <div class = "middle">
    Some unknown-width unwrappable thing here.
  </div>
  <div class = "right">
    right label may wrap if it's wider than 50%
  </div>
</div>

Вы против использования position:absolute для левого / правого контента?

Richard Parnaby-King 22.03.2018 11:22
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
2
1
765
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Не думаю, что flex можно так настроить. Желаемого эффекта можно достичь, используя position:absolute на левом / правом элементах:

.container {
  position: relative;
  padding-top: 1em;
  display: inline-block;
}

.left,
.right {
  position: absolute;
  top: 0;
}

.left {
  left: 0;
}

.right {
  right: 0;
}

.middle {}
<div class = "container">
  <div class = "left">
    left
  </div>
  <div class = "middle">
    So in my real example, there is some unknown-width unwrappable thing here.
  </div>
  <div class = "right">
    right
  </div>
</div>

Неплохо, но из-за этого метки left и right могут столкнуться друг с другом, если они длиннее, не так ли? У них тоже неизвестное содержимое. Я исправлю свой пример, чтобы показать это, потому что я думаю, что это одна из причин, по которой я предпочитаю flebox.

Ruben 22.03.2018 11:29

Вот идея решения без добавления дополнительной разметки:

.container {
  display: inline-flex;
  flex-wrap: wrap;
  max-width: 100%;
  border: 1px solid;
  margin: 20px;
}

.left {
  order: 1;
  min-width: 0;
  width: 0.5px;
  white-space: nowrap;
}

.right {
  order: 2;
  min-width: 0;
  width: 0.5px;
  margin-left: auto;
  display: flex;
  justify-content: flex-end;
  white-space: nowrap;
}

.middle {
  order: 3;
  flex-basis: 100%
}
<div class = "container">
  <div class = "left">
    some left content
  </div>
  <div class = "middle">
    So in my real example, there is some unknown-width unwrappable thing here. there is some unknown-width unwrappable thing here.
  </div>
  <div class = "right">
    some right content
  </div>
</div>
<div class = "container">
  <div class = "left">
    some left content
  </div>
  <div class = "middle">
    So in my real example, there is some unknown-width unwrappable thing here.
  </div>
  <div class = "right">
    right
  </div>
</div>
<div class = "container">
  <div class = "left">
    left
  </div>
  <div class = "middle">
    So in my real example, there is.
  </div>
  <div class = "right">
    right
  </div>
</div>
<div class = "container">
  <div class = "left">
    left
  </div>
  <div class = "middle">
    So in my
  </div>
  <div class = "right">
    right
  </div>
</div>

Но если вы можете немного изменить HTML, вы можете попробовать что-то вроде этого:

.container {
  display: inline-flex;
  flex-direction: column;
  max-width: 100%;
  border: 1px solid;
  margin: 20px;
}

.sub {
  display: flex;
  justify-content: space-between;
}
<div class = "container">
  <div class = "sub">
    <div class = "left">
      some left content
    </div>
    <div class = "right">
      some right content
    </div>
  </div>
  <div class = "middle">
    So in my real example, there is some unknown-width unwrappable thing here. there is some unknown-width unwrappable thing here.
  </div>
</div>
<div class = "container">
  <div class = "sub">
    <div class = "left">
      some left content
    </div>
    <div class = "right">
      some right content
    </div>
  </div>
  <div class = "middle">
    So in my real example, there is some unk
  </div>
</div>
<div class = "container">
  <div class = "sub">
    <div class = "left">
      left
    </div>
    <div class = "right">
      right
    </div>
  </div>
  <div class = "middle">
    So in my real example,
  </div>
</div>

Это здорово и решает мою проблему, спасибо. Теперь, чтобы понять, почему это работает, и попытаемся применить это к моей реальной проблеме (пока не совсем работает).

Ruben 22.03.2018 11:42

Я наткнулся на одну загвоздку: когда левый / правый может оборачиваться, но в этом нет необходимости, теперь они делают это преждевременно из-за взлома. jsfiddle.net/y7mcmxtf/14

Ruben 22.03.2018 11:45

@Ruben, хорошо, я вижу, в этом случае мы можем использовать white-space: nowrap

Temani Afif 22.03.2018 12:00

@Ruben но они переполнятся, тогда jsfiddle.net/y7mcmxtf/24 .. ок, подумаем об альтернативе;)

Temani Afif 22.03.2018 12:01

@Ruben Я добавил другой способ, но был вынужден разделить контент на два разных контейнера

Temani Afif 25.03.2018 13:57

Благодаря этому новому способу левый / правый элементы никогда не оборачиваются, но мне нужно, чтобы ширина определялась средним элементом. Если правый + левый шире (развернут), чем средний, они не совпадают.

Ruben 25.03.2018 18:34

@Ruben ну, у меня нет хаков для этого :) кстати, я не думаю, что возможно удовлетворить все потребности, потому что некоторые из них противоречивы

Temani Afif 26.03.2018 10:33

Действительно? Как что? Все мои потребности были бы удовлетворены, если бы я знал ширину среднего элемента (например, я мог бы легко взломать это с помощью JS, и это легко с таблицами jsfiddle.net/4z7qxfx6/2). Но да, я также понятия не имею, как это сделать с помощью CSS.

Ruben 26.03.2018 13:51

@Ruben, конечно, с JS легко :) тоже с таблицей, но непросто с гибким и актуальным макетом ... очень сложно указать, что оба элемента должны соответствовать ширине третьего элемента, а также нормально вести себя в пределах этой ширины [ при необходимости оберните]

Temani Afif 26.03.2018 13:59

Может, позже попробую какую-нибудь отвратительную комбинацию display table и flexbox. Но это, вероятно, потребует от меня возиться с порядком и вложенностью div.

Ruben 26.03.2018 15:51

Вы можете изменить flex с auto на 100% и добавить text-align: center в .middle, например:

.container {
  display: flex;
  flex-wrap: wrap;
}

.left {
  order: 1;
  flex: 1 0;
}

.right {
  order: 2;
  flex: 1 0;
  text-align: right;
}

.middle {
  order: 3;
  flex: 2 0 100%; /* change this to 100% instead of auto */
  text-align: center; /* To center the text */
}
<div class = "container">
  <div class = "left">
    left
  </div>
  <div class = "middle">
    So in my real example, there is some unknown-width unwrappable thing here.
  </div>
  <div class = "right">
    right
  </div>
</div>

Но это не тот макет, который мне нужен.

Ruben 22.03.2018 11:46
Ответ принят как подходящий

Единственная возможность на чистом CSS выровнять элементы по своему усмотрению - это CSS Grid.

div {
  border: 1px dotted;
}

.container {
  display: inline-grid;
  grid-template-columns: min-content min-content;
}

.right {
  grid-column: 2;
  grid-row: 1;
}

.middle {
  grid-column: 1 / span 2;
  white-space: nowrap;
}
<div class = "container">
  <div class = "left">
    left
  </div>
  <div class = "middle">
    Some unknown-width unwrappable thing here.
  </div>
  <div class = "right">
    right label may wrap if it's wider than 50%
  </div>
</div>

Также, если вам нужна поддержка IE10 +, этого легко добиться:

div {
  border: 1px dotted;
}

.container {
  display: -ms-inline-grid;
  display: inline-grid;
  -ms-grid-columns: min-content min-content;
  grid-template-columns: min-content min-content;
}

.right {
  -ms-grid-column: 2;
  grid-column: 2;
  grid-row: 1;
}

.middle {
  -ms-grid-row: 2;
  -ms-grid-column-span: 2;
  grid-column: 1 / span 2;
  white-space: nowrap;
}
<div class = "container">
  <div class = "left">
    left
  </div>
  <div class = "middle">
    Some unknown-width unwrappable thing here.
  </div>
  <div class = "right">
    right label may wrap if it's wider than 50%
  </div>
</div>

Спасибо! Я не знал о сетке CSS, поэтому спасибо, особенно за то, что проигнорировал заголовок моего вопроса с просьбой о решении flexbox ;-) Это проверяет все поля. В моей реальной проблеме вычисление ширины среднего элемента по какой-то причине изменилось с помощью этого решения, но я смогу выяснить это самостоятельно.

Ruben 27.03.2018 10:49

Я не замечал этого раньше, но здесь снова нижний / средний элемент не определяет ширину всего: jsfiddle.net/8nofar40 Я не уверен, что это за правило. Могу ли я сделать так, чтобы средний элемент всегда был решающим фактором?

Ruben 27.03.2018 14:05

Используйте flex-basis: number%, он работает очень хорошо и поддерживается IE 10+, и вы можете выбрать точку останова в селекторах медиа-запросов, если хотите.

проверьте мой код:

div {
  border: 1px dotted;
}

.container {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.left {
  flex-basis: 49.55%; /* change this to whatever you want */
}

.right {
  flex-basis: 49.55%; /* change this to whatever you want */
}

.middle {
  order: 3;
  flex-basis: 100%;
}
<div class = "container">
  <div class = "left">
    left
  </div>
  <div class = "middle">
    Some unknown-width unwrappable thing here.
  </div>
  <div class = "right">
    right label may wrap if it's wider than 50%
  </div>
</div>

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

Ruben 27.03.2018 10:28

Другие вопросы по теме