Flexbox можна назвати вдалою спробою вирішення величезного спектра проблем при побудові лейаутів в CSS. Але перш ніж перейти до його опису, давайте з'ясуємо, що не так зі способами верстки, якими ми користуємося зараз?
Будь-який верстальник знає кілька шляхів вирівняти щось по вертикалі або зробити 3-х колонковий макет із гумовою середньою колонкою. Але давайте визнаємо, що всі ці способи досить дивні, схожі на хак, підходять не завжди, складні для сприйняття і не працюють при недотриманні певних магічних умов, які склалися історично.
Сталося так тому, що HTML та CSS розвивалися еволюційно. На початку веб-сторінки були схожі на однопотокові текстові документи, згодом розбиття сторінки на блоки робили таблицями, потім стало модним верстати float-ами, а після офіційної смерті IE6 додалися ще й прийоми з inline-block. У результаті ми отримали у спадок гримучу суміш усіх цих прийомів, використовувану для побудови лейаутів 99,9% всіх існуючих веб-сторінок.
Специфікація CSS Flexible Box Layout Module (у народі — Flexbox) покликана кардинально змінити ситуацію на краще при вирішенні величезної кількості завдань. Flexbox дозволяє контролювати розмір, порядок та вирівнювання елементів по кількох осях, розподіл вільного місця між елементами та багато іншого.
Основні переваги Flexbox
- Всі блоки дуже легко робляться «гумовими», що вже випливає з назви «flex». Елементи можуть стискатися та розтягуватися за заданими правилами, займаючи потрібний простір.
- Вирівнювання по вертикалі та горизонталі, базової лінії тексту працює шикарно.
- Розташування елементів HTML не має вирішального значення. Його можна змінити в CSS. Це особливо важливо для деяких аспектів Responsive верстки.
- Елементи можуть автоматично вишиковуватися в кілька рядків/стовпців, займаючи все надане місце.
- Безліч мов у світі використовують написання праворуч ліворуч rtl (right-to-left), на відміну від звичного нам ltr (left-to-right). Flexbox пристосований для цього. У ньому є поняття початку та кінця, а не права та лева. Тобто. у браузерах з локаллю rtl всі елементи будуть автоматично розміщені у реверсному порядку.
- Синтаксис CSS правил дуже простий та освоюється досить швидко.
Поддержка браузерами
Поддержка браузерами пока неполная (2014). Виноват в этом в основном Internet Explorer, который поддерживает спецификацию 2011 года только начиная с 10 версии.
Не смотря на это, обратите внимание на обширность поддержки всеми остальными мобильными и десктопными браузерами! Тут все прекрасно. Если вам нужна мобильная версия сайта или web-based приложение, то его уже можно (а, возможно, и нужно) делать, используя все преимущества Flexbox!
Начинаем погружение
Flexbox определяет набор CSS свойств для контейнера (flex-контейнер) и его дочерних элементов (flex-блоков).
Первое, что нужно сделать — это указать контейнеру display:flex
или display:inline-flex
.
<div class="my-flex-container">
<div class="my-flex-block">item1</div>
<div class="my-flex-block">item2</div>
<div class="my-flex-block">item3</div>
</div>
.my-flex-container{
display: flex;
}
Основные свойства Flex-контейнера. Главная и поперечная ось
Одним из основных понятий в Fleхbox являются оси.
- Главной осью Flex-контейнера является направление, в соответствии с которым располагаются все его дочерние элементы.
- Поперечной осью называется направление, перпендикулярное главной оси.
Главная ось в ltr локали по умолчанию располагается слева направо. Поперечная — сверху вниз. Направление главной оси Flex-контейнера можно задавать, используя базовое CSS свойство flex-direction
.
flex-direction
— направление главной оси
Доступные значения flex-direction:
row
(значение по умолчанию): слева направо (в rtl справа налево)row-reverse
: справа налево (в rtl слева направо)column
: сверху внизcolumn-reverse
: снизу вверх
justify-content
— выравнивание по главной оси
CSS свойство justify-content
определяет то, как будут выровнены элементы вдоль главной оси.
Доступные значения justify-content:
flex-start
(значение по умолчанию): блоки прижаты к началу главной осиflex-end
: блоки прижаты к концу главной осиcenter
: блоки располагаются в центре главной осиspace-between
: первый блок располагается в начале главной оси, последний блок — в конце, все остальные блоки равномерно распределены в оставшемся пространстве.space-around
: все блоки равномерно распределены вдоль главной оси, разделяя все свободное пространство поровну.
align-items
— выравнивание по поперечной оси
CSS свойство align-items
определяет то, как будут выровнены элементы вдоль поперечной оси.
Доступные значения align-items:
flex-start
: блоки прижаты к началу поперечной осиflex-end
: блоки прижаты к концу поперечной осиcenter
: блоки располагаются в центре поперечной осиbaseline
: блоки выровнены по их baselinestretch
(значение по умолчанию): блоки растянуты, занимая все доступное место по поперечной оси, при этом все же учитываютсяmin-width
/max-width
, если таковые заданы.
СSS свойства flex-direction
, justify-content
, align-items
должны применяться непосредственно к flex-контейнеру, а не к его дочерним элементам.
Многострочная организация блоков внутри Flex-контейнера
flex-wrap
Все примеры, которые мы приводили выше, были построены с учетом однострочного (одностолбцового) расположения блоков. Надо сказать, что по умолчанию Flex-контейнер всегда будет располагать блоки внутри себя в одну линию. Однако спецификацией также поддерживается многострочный режим. За многострочность внутри flex-контейнера отвечает CSS свойство flex-wrap
.
Доступные значения flex-wrap:
nowrap
(значение по умолчанию): блоки расположены в одну линию слева направо (в rtl справа налево)wrap
: блоки расположены в несколько горизонтальных рядов (если не помещаются в один ряд). Они следуют друг за другом слева направо (в rtl справа налево)wrap-reverse
: то же, что и wrap, но блоки располагаются в обратном порядке.
flex-flow
— удобное сокращение для flex-direction + flex-wrap
По сути,flex-flow
предоставляет возможность в одном свойстве описать направление главной и многострочность поперечной оси. По умолчанию flex-flow: row nowrap
.
flex-flow: <‘flex-direction’> || <‘flex-wrap’>
/* тобто ... */
.my-flex-block{
flex-direcrion:column;
flex-wrap: wrap;
}
/* це те ж саме, що ... */
.my-flex-block{
flex-flow: column wrap;
}
align-content
Существует также свойство align-content
, которое определяет то, каким образом образовавшиеся ряды блоков будут выровнены по вертикали и как они поделят между собой все пространство Flex-контейнера.
Важно: align-content
работает только в многострочном режиме (т.е. в случае flex-wrap:wrap;
или flex-wrap:wrap-reverse;
)
Доступные значения align-content:
flex-start
: ряды блоков прижаты к началу flex-контейнера.flex-end
: ряды блоков прижаты к концу flex-контейнераcenter
: ряды блоков находятся в центре flex-контейнераspace-between
: первый ряд блоков располагается в начале flex-контейнера, последний ряд блоков блок — в конце, все остальные ряды равномерно распределены в оставшемся пространстве.space-around
: ряды блоков равномерно распределены в от начала до конца flex-контейнера, разделяя все свободное пространство поровну.stretch
(значение по умолчанию):ряды блоков растянуты, чтобы занять все имеющееся пространство.
СSS свойства flex-wrap
и align-content
должны применяться непосредственно к flex-контейнеру, а не к его дочерним элементам.
CSS правила для дочерних элементов flex-контейнера (flex-блоков)
flex-basis
— базовый размер отдельно взятого flex-блока
Задает изначальный размер по главной оси для flex-блока до того, как к нему будут применены преобразования, основанные на других flex-факторах. Может быть задан в любых единицах измерения длинны (px
, em
, %
, …) или auto
(по умолчанию). Если задан как auto
— за основу берутся размеры блока (width, height), которые, в свою очередь, могут зависеть от размера контента, если не указаны явно.
flex-grow
— «жадность» отдельно взятого flex-блока
Определяет то, насколько отдельный flex-блок может быть больше соседних элементов, если это необходимо.
flex-grow
принимает безразмерное значение ( по умолчанию 0
)
Пример 1:
- Если все flex-блоки внутри flex-контейнера имеют
flex-grow:1
, то они будут одинакового размера - Если один из них имеет
flex-grow:2
, то он будет в 2 раза больше, чем все остальные
Пример 2:
- Если все flex-блоки внутри flex-контейнера имеют
flex-grow:3
, то они будут одинакового размера - Если один из них имеет
flex-grow:12
, то он будет в 4 раза больше, чем все остальные
Т.е абсолютное значение flex-grow
не определяет точную ширину. Оно определяет его степень «жадности» по отношению к другим flex-блокам того же уровня.
flex-shrink
— фактор «сжимаемости» отдельно взятого flex-блока
Определяет, насколько flex-блок будет уменьшаться относительно соседних эдементов внутри flex-контейнера в случае недостатка свободного места. По умолчанию равен 1
.
flex
— короткая запись для свойств flex-grow, flex-shrink и flex-basis
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
/* тобто ... */
.my-flex-block{
flex-grow:12;
flex-shrink:3;
flex basis: 30em;
}
/* це те ж саме, що ... */
.my-flex-block{
flex: 12 3 30em;
}
align-self
— выравнивание отдельно взятого flex-блока по поперечной оси
Делает возможным переопределять свойство flex-контейнера align-items
для отдельного flex-блока.
Доступные значения align-self (те же 5 вариантов, что и для align-items
)
flex-start
: flex-блок прижат к началу поперечной осиflex-end
: flex-блок прижат к концу поперечной осиcenter
: flex-блок располагаются в центре поперечной осиbaseline
: flex-блок выравнен по baselinestretch
(значение по умолчанию): flex-блок растянут, чтобы занять все доступное место по поперечной оси, при этом учитываютсяmin-width
/max-width
, если таковые заданы.
order
— порядок следования отдельно взятого flex-блока внутри flex-контейнера
По умолчанию все блоки будут следовать друг за другом в порядке, заданном в HTML. Однако этот порядок можно изменить с помощью свойства order
. Оно задается целым числом и по умолчанию равно 0
.
Значение order
не задает абсолютную позицию элемента в последовательности. Оно определяет вес позиции элемента.
<div class="my-flex-container">
<div class="my-flex-block" style="order: 5" >item1</div>
<div class="my-flex-block" style="order: 10">item2</div>
<div class="my-flex-block" style="order: 5" >item3</div>
<div class="my-flex-block" style="order: 5" >item4</div>
<div class="my-flex-block" style="order: 0" >item5</div>
</div>
В данном случае, блоки будут следовать один за другим вдоль главной оси в следующем порядке: item5, item1, item3, item4, item2.
margin: auto
— по вертикали. Мечты сбываются!
Flexbox можно любить хотя бы за то, что привычное всем выравнивание по горизонтали через margin:auto
здесь работает и для вертикали!
.my-flex-container {
display: flex;
height: 300px; /* Або що завгодно */
}
.my-flex-block {
width: 100px; /* Або що завгодно */
height: 100px; /* Або що завгодно */
margin: auto; /* Магія! Блок відцентрований по вертикалі та горизонталі! */
}
Вещи, которые следует помнить
- Не следует использовать flexbox там, где в этом нет необходимости.
- Определение регионов и изменение порядка контента во многих случаях все-таки полезно делать зависимым от структуры страницы. Продумывайте это.
- Разберитесь в flexbox и знайте его основы. Так намного легче достичь ожидаемого результата.
- Не забывайте про margin-ы. Они учитываются при установке выравнивания по осям. Также важно помнить, что margin-ы в flexbox не “коллапсятся”, как это происходит в обычном потоке.
- Значение float у flex-блоков не учитывается и не имеет значения. Это, наверно, как-то можно использовать для graceful degradation при переходе на flexbox.
- flexbox очень хорошо подходит для верстки веб-компонентов и отдельных частей веб-страниц, но показал себя не с лучшей стороны при верстке базовых макетов (расположение article, header, footer, navbar и т.п.).