Как отображать обертывание гибких элементов как пробел между последней левой строкой?
У меня есть контейнер с фиксированной шириной, в который должны появляться несколько элементов переменной ширины в строке, которые при необходимости могут перетекать в дополнительные строки.
Однако начало каждого элемента должно быть выровнено с одним над ним, поэтому в ASCII-стиле оно будет выглядеть так (например, добавление 1):
/----------------------------------\
| |
| # One # Two # Three # Four |
| # Five # Six |
| |
\----------------------------------/
Другими словами:
- Первый элемент каждой строки должен быть выровнен по левому краю
- Последний элемент каждой строки (кроме последней строки) должен быть выровнен по правому краю.
- Каждый элемент должен быть выровнен по левому краю над элементом над ним
Я пытаюсь использовать flexbox для этого без успеха.
Это - лучшее, что я до сих пор использовал, используя flex-wrap: wrap
для контейнера и flex-grow: 1
для элементов.
Проблема в том, что последняя строка заполняется до края.
justify-content: flex-start; // this does nothing
Если я уберу flow-grow: 1
, тогда элементы не будут распределены одинаково. Я также пробовал возиться с last-of-type
по элементам, но этого также недостаточно.
Возможно ли это с помощью flexbox
, или я не ошибаюсь?
Спасибо...
Ответы
Ответ 1
После прочтения предложений здесь (спасибо!) и поиска в Интернете долго и широко, я пришел к выводу, что это просто невозможно с помощью flexbox. Любое тем, что я имею в виду, что другие пришли к этому выводу, когда я упорно пытался сделать это не работать в любом случае, пока, наконец, отказаться от принятия и мудрости мудрых людей.
Есть несколько ссылок, с которыми я столкнулся, которые могут объяснить это лучше или разные аспекты требований, поэтому я отправляю их здесь для... потомства.
Как сохранить обернутые гибкие элементы той же ширины, что и элементы предыдущей строки?
http://fourkitchens.com/blog/article/responsive-multi-column-lists-flexbox
Ответ 2
Я знаю, что я немного опаздываю, но я искал решения для этого в прошлый час или около того, и я думаю, что я как-то понял это. Поместите пустой div
в конец вашего контейнера и установите для него flex-grow: 1
и ничего больше. Также установите justify-content: space-between
на контейнер и не используйте flex-grow
для других элементов. Это всегда приведет к выравниванию последней строки, потому что этот div будет растягиваться по всему оставшемуся пространству.
Однако проблема заключается в том, что она ВСЕГДА делает последнюю линию выравниваемой влево - даже если это единственная строка, которая делает это решение непригодным для меня, но оно может быть полезно для тех, кто может ожидать более одной строки позиций.
Ответ 3
Если ширина ваших позиций исправлена, вы можете добавить несколько пустых div в конец списка элементов:
<div class="item">meaningful content</div>
<div class="item">meaningful content</div>
<div class="item">meaningful content</div>
<div class="empty-div"></div>
<div class="empty-div"></div>
<div class="empty-div"></div>
а затем:
.item, .empty-div{ width: 150px; } // make them the same width
Хорошо работает.
Ответ 4
Я просто наткнулся на ту же проблему и придумал другое решение. Я не могу решить, чувствует ли он себя грязным или изящным, но решите для себя.
Добавьте в контейнер столько пустых div
сколько максимальное количество элементов в строке, присвойте им тот же класс, что и элементы строки, но удалите из них все поля или отступы (в основном все, что дает им высоту). Это приведет к тому, что строка будет вести себя так, как ожидалось, потому что после последнего элемента строки всегда будет достаточно невидимых "прокладок" для прокладки строки. Те, которые завернуты в следующую строку, не имеют высоты, поэтому они не должны влиять на остальную часть вашей страницы.
Пример здесь: https://jsfiddle.net/amknwjmj/
.products {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.product {
/* set top and bottom margin only, as left and right
will be handled by space-between */
margin: 0.25rem 0;
/* account your desired margin two times and substract
it from the base width of the row item */
flex-basis: calc(25% - (0.25rem * 2));
}
.product.spacer {
/* remove all properties increasing the element height
from the spacers to avoid them being visible */
margin: 0;
padding: 0;
height: initial;
}
/* start demo styles (purely eye-candy not required for this to work) */
* {
box-sizing: border-box;
font-family: sans-serif;
}
.products {
padding: .25rem .5rem;
background: powderblue;
}
.product {
height: 75px;
line-height: 75px;
padding: .25rem;
text-align: center;
background: steelblue;
color: #fff;
}
.product.spacer {
background: none;
/* of course, spacers should NOT have a border
but they are helpful to illstrate what going on. */
border: 1px dashed gray;
}
/* end demo styles */
<div class="products">
<article id="product-1" class="product">P1</article>
<article id="product-2" class="product">P2</article>
<article id="product-3" class="product">P3</article>
<article id="product-4" class="product">P4</article>
<article id="product-5" class="product">P5</article>
<div class="product spacer"></div>
<div class="product spacer"></div>
<div class="product spacer"></div>
<div class="product spacer"></div>
</div>
Ответ 5
Итак, у вас есть контейнер и некоторые вещи внутри?
<div class="container">
<span>msg1</span>
<span>msg1</span>
<span>msg1</span>
<span>msg1</span>
<span>msg1</span>
</div>
Вот как это работает, когда вы объявляете display: flex
для своего контейнера, все его прямые дочерние элементы тоже будут гибкими, с некоторой конфигурацией по умолчанию (align-items:strech
).
Я предполагаю, что у вас это уже есть, поэтому, возможно, вы можете попробовать использовать justify-content: space-between
, который выровнят ваши элементы в строке, оставив их равномерными плюс flex-basis: 25%
(чтобы удостовериться, что всегда будет 4 элемента в строке, измените de%, как вы хотите), который должен работать для всех ваших линий, кроме последнего. Для последнего вы можете использовать селектор css (например, last-child
) и установить его свойство flex-grow: 0
/flex-shrink:0
(решение одной из ваших проблем, если вы использовали flex: 1 1 25%
вместо flex-basis
), а также align-self: flex-start
или что вам нравится
Ответ 6
Вы можете попробовать его с помощью фиксированного-псевдо-элемента:
.container {
display:flex;
justify-content:space-between;
}
.container:after {
content: '';
flex-grow: 0;
width: 25%;
}
.container .element {
width: 25%;
}
Ответ 7
Нет простого способа сделать это с помощью flexbox. Но если вы готовы пожертвовать IE, тогда вы можете сделать это с помощью grid
css, добавьте это в контейнер:
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
И если вы хотите иметь некоторое пространство между элементами, тогда добавьте
grid-gap: 10px;
Ответ 8
Я смог достичь желаемого результата с комбинацией положительных и отрицательных полей.
Если каждый элемент в контейнере определяет границу для создания пробела между ними:
.container .element {
flex: 1;
margin: 0px 5px;
}
восстанавливать пиксели с краев каждой строки в контейнере с отрицательным запасом той же суммы:
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0px -5px;
}
Это должно привести к 10px между каждым элементом в строке с первой и последней из каждой строки на краю контейнера.