Сайт вебмастера

Нормальное описание Flexbox-модели

10-02-2016Reading time ~ 8 min.CSS, HTML, LESS, SASS 17596

Почти все руководства по Flexbox стараются вместить в себя описание всех его свойств и возможностей. Это приводит к тому, что вебмастеру довольно сложно соориентироваться какие свойства правильно использовать.

Flexbox — мощная штука, которая охватывает достаточно большой пласт задач, но на практике требуется буквально несколько основных его возможностей. В 90% случаев Flexbox используется как замена float-модели блоков, то есть там, где требуется расположить несколько блоков рядом. Плюсом Flexbox будет и то, что его возможности позволяют легко строить адаптивные сетки, вертикальное выравнивание, произвольный порядок и т.п.

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

HTML-разметка Flexbox

Flexbox оперирует двумя понятиями: контейнер (flex container) и элементы (flex items). То есть всегда, где используется flex, создается основной контейнер.

Особенностью Flexbox-модели является то, что элементы не требуется специальным образом задавать. Например во float-модели (понятно, что это условное именование), было как раз наоборот — требовалось задавать float-свойства именно элементов. Во Flexbox - задается только контейнер, а элементы будут заданы автоматически — все непосредственные потомки.

Типовой вариант html-разметки:

<div style="display: flex;">
	<div>1</div>
	<div>2</div>
	<div>3</div>
</div>

Результат (я немного раскрасил для наглядности):

1
2
3

Блоки элементов (flex items) во Flexbox приобретут специальное свойство, делающее их похожими на inline-block. Именно поэтому хоть у нас и DIV, который в обычном состоянии занял бы 100% ширины, в данном примере занял ширину, соответствующему своему содержимому.

У flex-контейнера может быть свойство justify-content, которое позволяет задать способ размещения элементов. Значение flex-start — это значение по умолчанию (как в примере выше). Значение flex-end — обратное. То есть выравнивание будет с конца.

<div style="display: flex; justify-content: flex-end;">
1
2
3

Значение center размещает элементы по центру:

<div style="display: flex; justify-content: center;">
1
2
3

Более интересные значения у space-around и space-between. Они распределяют свободное место между блоками. Первое учитывает отступы с краёв, а второе прижимает блоки к краю контейнера.

<div style="display: flex; justify-content: space-around;">
1
2
3
<div style="display: flex; justify-content: space-between;">
1
2
3

У контейнера может быть еще одно свойство flex-direction, которое задает направление элементов. Значение п умолчанию row, то есть построчно. Есть значение column — в колонку.

<div style="display: flex; flex-direction: column;">
1
2
3

Значения row-reverse и column-reverse делают реверс, то есть меняют порядок элементов.

<div style="display: flex; flex-direction: row-reverse;">
1
2
3

На практике column практически не используются. Во всяком случае мне ни разу не пришлось им воспользоваться.

Вариант

<div style="display: flex; justify-content: space-between;">

по сути является привычной «резиновой» раскладкой, которая может применяться как для отдельных блоков страницы, так и модульной сетки в целом.

Управлять шириной элементов можно через привычное свойство width.

<div style="display: flex; justify-content: space-between;">
	<div style="width: 30%;">1</div>
	<div style="width: 30%;">2</div>
	<div style="width: 30%;">3</div>
</div>
1
2
3

Теперь об очень важном моменте. Ширина элемента (width) во Flexbox носит лишь «рекомендательный» характер, а не обязательный. Задавая ширину вебмастер лишь указывает желаемую ширину, а Flexbox уже сам решит что делать, если она окажется некорректной. Например, если суммарная ширина элементов превысит 100% (страшный сон вебмастера, использующего float-вёрстку!), во Flexbox ничего страшного не произойдет — блоки останутся на местах, автоматически заняв оптимальное расположение.

На этом основано одно из свойств элементов flex-grow — т.н. жадность элемента, которая указывается числом — чем оно больше, тем больше и «жадность». По умолчанию для всех элементов это 0. Свойство flex-grow крайне удобная штука, поскольку позволяет задавать ширину элементов относительно других без указания точных значений. Например при верстке блока, где ширина «абстрактная» и мы знаем только, что один элемент должен быть больше других. Такие задачи — довольно частые в вебмастерской практике.

<div style="display: flex; justify-content: space-between;">
	<div style="flex-grow: 3;">1</div>
	<div style="flex-grow: 1;">2</div>
	<div style="flex-grow: 1;">3</div>
</div>
1
2
3

Этот же способ применяется там, где ширину задавать невозможно. Простой пример — иконки или пункты меню. Мы не можем рассчитать ширину каждого элемента, поскольку просто не знаем их количество. В этом случае будет достаточно указать свойство flex-grow.

Flexbox обладает ещё одним интересным свойством order, которое указывает порядок элемента. С его помощью можно перетусовать элементы как угодно.

<div style="display: flex; justify-content: space-between;">
	<div style="order: 2;">1</div>
	<div style="order: 3;">2</div>
	<div style="order: 1;">3</div>
</div>
1
2
3

Через order можно менять расположение блоков модульной сетки, например поменять расположение сайдбара слева или справа.

Теперь рассмотрим свойство контейнера flex-wrap. Через него можно управлять поведением элементов в случае заполнения всей ширины. По простому — flex-wrap разрешает делать перенос элементов на новую строку. По умолчанию это значение nowrap, то есть перенос запрещен. Перенос разрешен для wrap и wrap-reverse (тоже самое, только делает реверс элементов).

Перенос часто используется для создания адаптивной сетки. Например есть три блока по 30%. На широких экранах они будут занимать, скажем по 300px. На планшетах, чья ширина меньше — пусть по 200px, а на телефонах еще меньше, скажем 80px. Всё потому, что ширина рассчитывается именно в процентах от ширины экрана.

Оптимальным же будет поведение, когда для десктопов перенос запрещен и блоки в одну строку, как и задумано. Для планшетов и телефонов, перенос уже разрешен и ширину элементов нужно сделать больше, например по 50%. А вот для телефонов ширину сделать уже 100%, поскольку места и так мало. Таким образом на любом экране блоки будут смотреться уже нормально.

Данный CSS-код основан на @media, когда css-классы определяются только для определенных экранов. Вот примерно так (код на LESS):

@media @SCREEN_TABLET {
	.wXX-tablet { ... } 
}
 
@media @SCREEN_PHONE {
	.wXX-phone { ... }
}
 
<div class="w30 w50-tablet w100-phone">...</div>
<div class="w30 w50-tablet w100-phone">...</div>

Свойство flex-wrap здесь как раз и будет играть ключевую роль. Приведу пример на классах Berry CSS (см. описание flex):

<div class="flex flex-wrap-tablet">
	<div class="w30 w50-tablet w100-phone">1</div>
	<div class="w30 w50-tablet w100-phone">2</div>
	<div class="w30 w100-tablet w100-phone">3</div>
</div>

Другим примером использования flex-wrap будет равномерное заполнение блока фиксированными элементами. Например вывод миниатюр в галерее.

<div style="display: flex; flex-wrap: wrap;">
	<div style="width: 100px;">1</div>
	<div style="width: 100px;">2</div>
	<div style="width: 100px;">3</div>
	<div style="width: 100px;">4</div>
	<div style="width: 100px;">5</div>
	<div style="width: 100px;">6</div>
	<div style="width: 100px;">7</div>
	<div style="width: 100px;">8</div>
	<div style="width: 100px;">9</div>
	<div style="width: 100px;">10</div>
</div>
1
2
3
4
5
6
7
8
9
10

Flexbox позволяет управлять и высотой элементов (или расположением по вертикали). Такие задачи встречаются гораздо реже. По-умолчанию высоты элементов индивидуальны.

1
2
3

Если нужно выровнять блоки по высоте, то у контейнера выставляется свойство align-items. Оно имеет значения: flex-start, flex-end, center, baseline и stretch и похожи на те, что описаны выше, только работающие по вертикали. Для выравнивания используется stretch.

<div style="display: flex; justify-content: space-between; align-items: stretch;">
	<div>1</div>
	<div>2</div>
	<div style="height: 200px;">3</div>
</div>
1
2
3

Данное поведение очень похоже на выравнивание ячеек в таблицах (table), поэтому используется примерно в этом же контексте, например при выравнивании прайсовых блоков.

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

<div style="display: flex; justify-content: space-between; align-items: center;">
	<div style="width: 25%; height: 40px;">1</div>
	<div style="width: 25%; height: 60px;">2</div>
	<div style="width: 25%; height: 80px;">3</div>
</div>
1
2
3

И последнее, что может пригодится вебмастеру — выравнивание блока по вертикали по центру. Вертикльное выравнивание, всегда было головной болью, но с Flexbox всё решается очень просто. Стандартно центрирование по горизонтали выполнялось с помощью margin: 0 auto; Собственно auto и работало только по-горизонтали. Но в Flexbox теперь работает в любом направлении.

<div style="display: flex; height: 150px; border: 1px solid gray;">
	<div style="width: 50px; height: 50px; margin: auto;"></div>
</div>

В заключении приведу ссылку на официальную документацию CSS Flexible Box Layout Module, где можно посмотреть все возможности Flexbox.

Related Posts
Comments (1) RSS
1 Санек 2016-02-11 19:19:22

Спасибо MAX, и в правду супер!