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





Не думаю, что 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.
Вот идея решения без добавления дополнительной разметки:
.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>Это здорово и решает мою проблему, спасибо. Теперь, чтобы понять, почему это работает, и попытаемся применить это к моей реальной проблеме (пока не совсем работает).
Я наткнулся на одну загвоздку: когда левый / правый может оборачиваться, но в этом нет необходимости, теперь они делают это преждевременно из-за взлома. jsfiddle.net/y7mcmxtf/14
@Ruben, хорошо, я вижу, в этом случае мы можем использовать white-space: nowrap
@Ruben но они переполнятся, тогда jsfiddle.net/y7mcmxtf/24 .. ок, подумаем об альтернативе;)
@Ruben Я добавил другой способ, но был вынужден разделить контент на два разных контейнера
Благодаря этому новому способу левый / правый элементы никогда не оборачиваются, но мне нужно, чтобы ширина определялась средним элементом. Если правый + левый шире (развернут), чем средний, они не совпадают.
@Ruben ну, у меня нет хаков для этого :) кстати, я не думаю, что возможно удовлетворить все потребности, потому что некоторые из них противоречивы
Действительно? Как что? Все мои потребности были бы удовлетворены, если бы я знал ширину среднего элемента (например, я мог бы легко взломать это с помощью JS, и это легко с таблицами jsfiddle.net/4z7qxfx6/2). Но да, я также понятия не имею, как это сделать с помощью CSS.
@Ruben, конечно, с JS легко :) тоже с таблицей, но непросто с гибким и актуальным макетом ... очень сложно указать, что оба элемента должны соответствовать ширине третьего элемента, а также нормально вести себя в пределах этой ширины [ при необходимости оберните]
Может, позже попробую какую-нибудь отвратительную комбинацию display table и flexbox. Но это, вероятно, потребует от меня возиться с порядком и вложенностью div.
Вы можете изменить 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>Но это не тот макет, который мне нужен.
Единственная возможность на чистом 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 ;-) Это проверяет все поля. В моей реальной проблеме вычисление ширины среднего элемента по какой-то причине изменилось с помощью этого решения, но я смогу выяснить это самостоятельно.
Я не замечал этого раньше, но здесь снова нижний / средний элемент не определяет ширину всего: jsfiddle.net/8nofar40 Я не уверен, что это за правило. Могу ли я сделать так, чтобы средний элемент всегда был решающим фактором?
Используйте 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>Ваш собственный пример кода показывает, что это не воспроизводит мой желаемый результат. Теперь правый элемент не оборачивается, и общая ширина определяется умножением правой ширины на два, а не шириной среднего элемента.
Вы против использования
position:absoluteдля левого / правого контента?