О модели Flexbox сказано и написано уже немало. Это и понятно, т.к. эта модель значительно более современна, чем использование, например, плавающих блоков с float: left
или right
. Именно, поэтому ее взяли за основу разработчики Bootstrap 4.
Flexbox (с англ. дословно "гибкая коробка") представляет собой набор свойств, которые назначаются отдельно для родительских и дочерних элементов, позволяя их действительно гибко распределять в соответствии с популярным сейчас подходом верстки по сетке.
Модель CSS FlexBox (CSS Flexible Box Layout Module) была задумана еще в 2008 году и имеет несколько редакций, выпущенных в такое время:
- 2009 – был опубликован черновик “Flexible Box Layout Module”. В то время Chrome и Safari добавляет частичную поддержку этой технологии, а Mozilla начинает поддерживает синтаксис, известный как “Flexbox 2009″.
- 2011 – были созданы черновики Flexbox-модели, в которых Tab Atkins очень сильно изменил синтаксис по сравнению с 2009 годом. Поддержка нового синтаксиса внедряется браузерами Chrome, Opera и IE10. Этот синтаксис становится известен под названием “flexbox 2011”
- 2012 – Синтаксис опять несколько изменен и уточнен. Спецификация переходит в статус Candidate Recommendation и известна под названием “flexbox 2012”. Opera внедряет поддержку без префиксов, Chrome поддерживает текущую спецификацию с префиксами, а Mozilla без них, IE10 добавляет поддержку устаревающего “flexbox 2011” синтаксиса.
- 2014 – все новые браузеры поддерживают последнюю спецификацию (включая IE 11)
Т.е. с 2014 года "рулят" те правила модели Flexbox, которые мы будем рассматривать ниже. Для Safari 6.1+ до v.8 и iOS 7.1+ до v.8.4, Android до v.4.3 нужно указывать префикс -webkit-
. Более детальную поддержку и совместимость с браузерами можно посмотреть на сайте caniuse.com. Для Internet Explorer 10 и IE Mobile нужно указывать префикс -ms-
.
В этой статье мы рассмотрим такие свойства:
Основные свойства Flexbox
Итак, свойства Flexbox разделяются на свойства для родительского элемента (будем называть его контейнером) и для его дочерних элементов.
Свойства Flexbox-контейнера
Свойство display
Во-первых , обязательным является указание для контейнера свойства display: flex
или inline-flex
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <head> <style> .container { display: flex; border: 1px solid #ccc; } .inline-container { display: inline-flex; border: 1px solid #ccc; } .item { width: 100px; padding: 10px; text-align: center; } </style> <head> <body> <div class="container"> <div class="item"> 1 </div> <div class="item"> 2 </div> <div class="item"> 3 </div> <div class="item"> 4 </div> </div> </body> |
Обратите внимание, что в первом случае (display: flex
) размер контейнера доходит до пределов родительского блока, а дочерние элементы занимают по 100px, а во втором (display: inline-flex
) размер родительского контейнера совпадает с размером содержимого, т.е. размером дочерних элементов.
С префиксами css-код будет выглядеть несколько иначе:
1 2 3 4 5 6 7 8 9 10 11 12 | .container { display: -webkit-box; display: -ms-flexbox; display: flex; border: 1px solid #ccc; } .inline-container { display: -webkit-inline-box; display: -ms-inline-flexbox; display: inline-flex; border: 1px solid #ccc; } |
Далее префиксы мы будем опускать для читабельности кода. Но в реальных проектах их стоит добавлять с помощью autoprefixer, который автоматически добавит css-правила и вендорные префиксы для тех браузеров, которым они нужны.
Важное примечание: flex-контейнер сам не является блочным контейнером, поэтому для внутренних блоков не работают такие css-свойства, как float
, clear
, vertical-align
. Также, на flex-контейнер не оказывают влияние свойства column-
, создающие колонки в тексте и псевдоэлементы ::first-line
и ::first-letter
.
Свойство flex-direction
Вернемся к примеру: все блоки с классом item внутри flex-контейнера выстроились по горизонтали слева направо. В спецификации Flexbox это определяется свойством flex-direction: row
, которое задано для flex-контейнеров по умолчанию. Также оно может иметь следующие значения:
1 | flex-direction: row | row-reverse | column | column-reverse |
Как только значение row
или row-reverse
(строка) меняется на column
или column-reverse
(столбец), внутренние элементы выстраиваются по вертикали. Это происходит потому, что в модели Flexbox есть 2 направления, или 2 оси - главная (main axis) и поперечная (cross axis). По умолчанию оси направлены слева направо и сверху вниз, но используя значения с суффиксом -reverse
можно поменять направление на противоположное.Примечание: при использовании rtl
направления меняются на противоположные, т.е. row будет идти справа налево.
Свойство justify-content
Css свойство justify-content
определяет то, как будут выровнены элементы вдоль главной оси. Очень важное свойство для построения системы сеток, т.к. позволяет распределить контент внутри контейнера.
Возможные значения свойства justify-content:
flex-start
(значение по умолчанию) : блоки прижаты к началу главной осиflex-end
: блоки прижаты к концу главной осиcenter
: блоки размещаются по центру главной осиspace-between
: первый блок располагается в начале главной оси, последний блок – в конце, все остальные блоки равномерно распределены в оставшемся пространстве.space-around
: все блоки равномерно распределены вдоль главной оси, разделяя все свободное пространство поровну, но до первого блока и после последнего блока свободное пространство уменьшается вдвое. То есть, если блоков 4, то и свободное пространство делится на 4 части, но 4-я часть делится надвое и распределяется в начало и в конец flex-контейнера.space-evenly
: все свободное пространство между блоками по главной оси разделяется поровну. В отличие от предыдущего значения, абсолютно все отступы между flex-элементами будут равными, или одинакоыми.
Свойство align-items
Css-свойство align-items определяет то, как будут выровнены элементы вдоль поперечной оси. Для того чтобы это свойство можно было использовать, высота контейнера должна быть больше высоты блоков. В примере она задана свойством height: 300px
. Например, это свойство хорошо подойдет для шапки сайта с большим изображением, чтобы разместить текст по центру.
Возможные значения свойства align-items
:
stretch
(значение по умолчанию) : блоки растянуты, занимая все доступное место по поперечной оси, при этом все же учитываются min-width/max-width, если таковые заданы.flex-start
: блоки прижаты к началу поперечной оси, т.е. к верхуflex-end
: блоки прижаты к концу поперечной оси, т.е. к низуcenter
: блоки располагаются в центре поперечной осиbaseline
: блоки выровнены по базовой линии текста в них. Зависит от размера шрифта. На примере в разных блоках цифры помещены в заголовки разных уровней. Например, блок с цифрой 2 больше остальных, т.к. в нем использован заголовок h1.
Вы можете протестировать многое свойства Flexbox-модели в примере ниже:
See the Pen flexFruits | a kawaii flexbox visualization guide by Delvigne Frédéric (@delvignefred) on CodePen.
Свойство flex-wrap
Первоначально подразумевается, что flexbox — это контейнер для установки его элементов в одну единственную строку. Свойство flex-wrap
управляет тем, как flex-контейнер будет устраивать свои элементы — в одну строку или в несколько, и направлением, в котором будут укладываться новые строки. Т.е. при изменении значения по умолчанию получается многострочный контейнер.
Это свойство нужно использовать, когда размеры контейнера слишком малы для размеров его дочерних элементов. Также, как правило, нужно устанавливать размеры дочерних элементов, т.к. они могут располагаться, как и блочные элементы, по одному в ряду, если их контент не позволяет разместить больше элементов.
В примере ниже указаны такие свойства:
1 2 3 4 5 6 7 8 9 | .container { display: flex; flex-wrap: wrap; border: 1px solid #ccc; } .item { padding: 10px; max-width: 50%; } |
Возможные значения flex-wrap:
nowrap
(значение по умолчанию) : блоки расположены в одну линию слева направо (в rtl справа налево)wrap
: блоки расположены в несколько горизонтальных рядов (если не помещаются в один ряд). Они следуют друг за другом слева направо (в rtl справа налево)wrap-reverse
: то-же что и wrap, но блоки располагаются в обратном порядке.
Свойство flex-flow
flex-flow
– удобное сокращение для двух свойств Flexbox-модели: flex-direction + flex-wrap
По сути,flex-flow
предоставляет возможность в одном свойстве описать направление главной и многострочность поперечной оси.
1 | flex-flow: flex-direction || flex-wrap |
Поскольку по умолчанию значение flex-flow: row nowrap
, то имеет смысл его использовать тогда, когда нужно изменить оба эти значения, например:
1 2 3 | .container{ flex-flow: column wrap; } |
или хотя бы одно
1 2 3 | .container{ flex-flow: wrap; } |
Свойство align-content
Существует также свойство align-content
, которое определяет то, каким образом образовавшиеся ряды блоков будут выровнены по вертикали и как они поделят между собой все пространство flex-контейнера. Это свойство удобно использовать там, где нужно указывать высоту контейнера и распределять внутренние блоки по вертикали.
Примечание: align-content
работает только в многострочном режиме (т.е. в случае flex-wrap:wrap;
или flex-wrap:wrap-reverse;
)
Возможные значения align-content:
stretch
(значение по умолчанию): ряды блоков растянуты, чтобы занять все имеющееся пространство.flex-start
: ряды блоков прижаты к началу flex-контейнера, т.е. начинаются от верхнего края контейнера.flex-end
: ряды блоков прижаты к концу flex-контейнераcenter
: ряды блоков находятся в центре flex-контейнера, а расстояния сверху и снизу от них равныspace-between
: первый ряд блоков располагается в начале flex-контейнера, последний ряд блоков блок – в конце, все остальные ряды равномерно распределены в оставшемся пространстве.space-around
: ряды блоков равномерно распределены в от начала до конца flex-контейнера, разделяя все свободное пространство поровну, но при этом сверху от первого flex-элемента и снизу от последнего будет половина от всех остальных отступов. То есть свободное пространство делится на количество строк, но при этом одно из значений делится пополам для создания отступа перед первым элементом и после последнего.space-evenly
: ряды блоков равномерно распределены в от начала до конца flex-контейнера, разделяя все свободное пространство поровну, то есть все отступы будут равными.
Свойство gap
Свойство gap стало доступным для Flexbox-модели с 2021 года, поэтому может не поддерживаться браузерами, выпущенными ранее. Оно пришло из модели CSS Grid, в которой первоначально называлось grid-gap
. Теперь это название поменялось.
Свойство gap позволяет устанавливать отступы между колонками и строками, которые получаются при делении пространства flex-контейнера на части находящимися в нем flex-элементами. Для того, чтобы получались строки, для flex-контейнера нужно назначить свойство flex-wrap
. В качестве значений для gap вы можете использовать любые единицы измерений, принятые в CSS: px, pt, %, em, rem, ex, vw, vh
и т.п. в зависимости от необходимости. Значение по умолчанию - normal
, т.е. отступов нет, если вы не создали их, использовав свойство justify-content
.
Вы можете указать одно значение, и оно применится и для строк, и для столбцов, или 2 значения - первое для строк, второе для столбцов.
Синтаксис:
1 2 3 4 5 6 7 8 9 10 11 | .flex-container { display: flex; flex-wrap: wrap; gap: 20px; /* gap: 10px 20px; */ } .flex-item { padding: 10px; flex: 1 0 calc(33.33% - 20px); } |
Обратите внимание, что эти отступы должны учитываться при указании размеров flex-элементов (.flex-item
в коде выше). Мы используем функцию calc()
для того, чтобы рассчитать ширину колонки, заданную в обобщенном свойстве flex, отнимая от 33% 20px
, указанных в свойстве gap
для .flex-container
.
Это свойство подразделяется на 2: column-gap
и row-gap
, которые позволяют назначить отступы между колонками (столбцами) и строками соответственно. В каждом из свойств можно указать одно значение:
1 2 3 4 5 6 | .flex-container { display: flex; flex-wrap: wrap; column-gap: 20px; row-gap: 1rem; } |
Попробуйте различные варианты свойства gap
:
Свойства дочерних элементов flex-контейнера
Свойство order
Это свойство определяет порядок (англ. order), в котором дочерние элементы flex-контейнера появляются внутри него. По умолчанию, flex-элементы следуют друг за другом в том порядке, в котором добавлены во flex-контейнер в html-коде. Задается order
целым числом и по умолчанию для всех элементов равен 0. Можно использовать как положительные, так и отрицательные числа.
В примере ниже увеличьте значение в поле с номером элемента и посмотрите, куда он "переедет".
Использовать это свойство можно, например, для изменения положения боковой колонки - справа или слева от основного контента. Или при сортировке блоков с какими-либо товарами.
Стоит сказать, что все свойства Flexbox-модели могут быть полезны при построении адаптивной верстки. Например, это свойство используется при перестройке контента вкладок при уменьшении ширины экрана. Чтобы посмотреть на эффект, включайте вкладки HTML или CSS. Кроме того, вы можете отредактировать этот код на codepen.io.
See the Pen Flexbox tabs by Elen (@ambassador) on CodePen.
Свойство align-self
Свойство align-self
позволяет изменить выравнивание отдельно взятого flex-блока по поперечной оси по сравнению со свойством flex-контейнера align-items
.
В качестве значений align-self имеет те же 5 вариантов, что и свойство align-items
, а именно:
stretch
(значение по умолчанию) : flex-блок растянут, чтобы занять все доступное место по поперечной оси, при этом учитываютсяmin-width
/max-width
, если таковые заданы.flex-start
: flex-блок прижат к началу поперечной осиflex-end
: flex-блок прижат к концу поперечной осиcenter
: flex-блок располагаются в центре поперечной осиbaseline
: flex-блок выравнен по baseline
Свойство flex-grow
Это свойство указывает, каким будет фактор растягивания flex-элемента. Что значит "фактор растягивания"? По сути дела это коэффициент, который определяет, насколько больше будет растянут flex-элемент относительно других flex-элементов при распределении свободного пространства внутри flex-контейнера.
По умолчанию это свойство имеет значение 0. Можно указывать только целые положительные числа. Отрицательные значения будут проигнорированы.
Принято думать, что если у какого-либо элемента указано свойство flex-grow
, равное 2, то этот элемент будет занимать в 2 раза больше пространства, чем остальные. На самом деле это будет так только при отсутствии контента внутри flex-элемента, что бывает только в демо-примерах и для реальной верстки не подходит. На самом деле это свойство определяет способность flex-элемента изменять свои размеры для заполнения собой свободного пространства. Т.е., если ширина одного flex-элемента 500px
, второго - 200px
, а ширина их родительского flex-контейнера 1000px
, то свободными останутся 300px
1 | 1000px - (500px + 200px) = 300px |
Т.е. для распределения в соответствии с flex-grow
останется только часть пространства, а не все оно.
Если у одного элемента flex-grow: 2
, а у второго - flex-grow: 1
, то 300px нужно будет делить на 3 части:
1 | 300px/(2+1) = 100px |
Соответственно, ширина первого элемента увеличится на 200px (500px + 100px*2 = 700px)
, а ширина второго станет больше всего на 100px: 200px+100px*1 = 300px
.
Если flex-grow
у первого и второго элементов будет по 1, то они разделят 300px свободного пространства поровну, т.е. по 150px:
1 | 300px/(1+1) = 150px |
В этом случае ширина первого станет 500px + 150px = 650px, а второго 200px+150px = 350px. И так будет происходить при любых равных значениях для свойства flex-grow
для обоих элементов.
В примере ниже вы можете сами посмотреть, какова будет ширина блоков section и aside при различных значениях свойства flex-grow
. Первоначально оба элемента имеют 0 в качестве значения этого свойства внутри составного свойства flex, поэтому свободное пространство мы видим справа от aside.
Свойство flex-shrink
Свойство flex-shrink
указывает фактор сужения flex-элемента относительно других flex-элементов в контейнере, чтобы разместить весь контент в одну строку при распределении отрицательного свободного пространства. Т.е. это свойство будет работать тогда, когда для размещения элементов в одну строку места недостаточно, а вместить их надо.
Свойство flex-shrink
похоже на flex-grow
, но имеет свои нюансы. Оно зависит от flex-basis
элемента и убавляется от величины, указанной или рассчитанной браузером для flex-basis
каждого из flex-элементов.
В примере у 5 flex-элементов flex-shrink равен 1
, также каждому задано значение flex-basis в 25%
. Однако, исходя из того, что родительский элемент имеет ширину 100%, а элементов 5, реальная ширина каждого из них составляет 20%. Здесь мы сталкиваемся с недостатком пространства в 25% . Т.е. отрицательное свободное пространство составляет 250px
(исходя из ширины flex-контейнера 1000px*25% = 250px
). Поэтому каждый из элементов получает -50px
, и реальная ширина каждого из элементов будет 200px
.
Если для одного из этих элементов изменить коэффициент flex-shrink
, то ширина этого отдельного элемента будет больше (flex-shrink: 0
) или меньше (flex-shrink: 2
) . В случае flex-shrink: 0
"рулит" свойство flex-basis
элемента, и его ширина составляет 250px (25% от 1000px)
, и сжиматься ему не нужно.
Если flex-shrink: 2
, то расчетная величина "убавляемого" пространства увеличивается и будет такова:
1 | 250px/(4*1+2) = 41.667px |
4 элемента имеют фактор flex-shrink: 1
(4*1) и один имеет flex-shrink: 2
, поэтому делить отрицательное пространство нужно на 6
. Каждый из элементов, имеющих flex-shrink: 1
, получает такую ширину:
1 | 250px - 41.667px = 208.333px |
А элемент с flex-shrink: 2
имеет ширину:
1 | 250px - 41.667px*2 = 166.666px |
Некоторое количество пикселей может отличаться, т.к. есть еще контент, который может не помещаться в расчетную ширину.
Еще один пример, демонстрируюший применение свойств flex-grow
и flex-shrink
: в обычном виде свойство flex-grow
задано, как 0.25. При наведении на элемент это свойство становится равным 2, и этот элемент занимает сразу значительно больше места, чем соседние. Все остальные элементы уменьшаются за счет пересчета ширины и за счет flex-shrink: 1
, чтобы поместиться в контейнере.
See the Pen Simple Hover Transition by Envato Tuts+ (@tutsplus) on CodePen.
Свойство flex-basis
Свойство flex-basis
определяет базовый размер отдельно взятого flex-элемента до распределения свободного пространства в соответствии с flex-grow
и flex-shrink
. Оно в какой-то мере напоминает width
, но несколько отличается по поведению, т.к. в "довесок" к нему идут коэффициенты flex-grow
и flex-shrink
, корректирующие конечную ширину элемента.
Свойство flex-basis
может быть указано в различных единицах: px, pt, em, rem, mm или в %
вдоль главной оси (main axis). В последнем случае размер вычисляется относительно родителя. Нельзя использовать отрицательные величины. По умолчанию имеет значение auto
, и тогда за основу вычисления размеров блока берутся его размеры (свойства width, height), а они, в свою очередь, могут зависеть от размера контента, если не указанны явно. Т.е. контент может растянуть или "ужать" блок в зависимости от своего размера.
Для flex-basis
доступно в спецификации еще значение content
, но оно пока не поддерживается браузерами и отображается как auto
. Обозначает это свойство, что размер элемента рассчитывается на основе его контента.
Сокращенное свойство flex
Предыдущие 3 свойства желательно писать не по отдельности, а указывать в одном общем свойстве flex
:
1 | flex: flex-grow flex-shrink flex-basis; |
В составе этого свойства сразу видно, как соотносится flex-basis
с остальными свойствами, поэтому легче будет управлять размерами flex-элемента.
Значения:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | Значение по умолчанию: 0 1 auto; /* 0 0 auto */ flex: none; /* 1 1 auto */ flex: auto; /* Одно значение, число без размерности: flex-grow */ flex: 2; /* Одно значение, ширина/высота: flex-basis */ flex: 10em; flex: 30px; flex: content; /* Два значения: flex-grow | flex-basis */ flex: 1 30px; /* Два значения: flex-grow | flex-shrink */ flex: 2 2; /* Три значения: flex-grow | flex-shrink | flex-basis */ flex: 2 2 10%; /* Глобальные значения */ flex: inherit; flex: initial; flex: unset; |
Какое из значений выбрать, определяется в каждом конкретном случае в зависимости от макета.
Стоит прочитать:
Зачем верстальщику лягушки?
В сети довольно давно существует ресурс, посвященный изучению свойств Flexbox-модели в виде небольшой интерактивной игры с лягушками. Доступен он и на русском языке - http://flexboxfroggy.com/#ru. Очень советую пройти ее - помогает разобраться со свойствами на наглядных примерах.
И в конце вы можете попробовать еще раз различные свойства Flexbox-модели:
See the Pen Animated Flexbox Playground by Elen (@ambassador) on CodePen.
Отличный и наглядный труд. Но насчет отличий display: flex и display: inline-flex написано не очень понятно. И у вас там рисунки перепутаны к этим свойствам.
Можно так:
Эти свойства влияют только на размер контейнера. display: flex растягивает контейнер на 100% места на странице (или родительского элемента), тогда как display: inline-flex ограничивает размер контейнера до размера дочерних элементов.
display: inline-flex does not make flex items display inline. It makes the flex container display inline. A similar comparison can be made between display: inline-block and display: block.
Ничего там не перепутано, т.к. это не рисунки, а HTML + CSS-код - посмотрите в Инспекторе свойств сами.
И объяснение совпадает по сути с вашим, хоть и написано другими словами.
Спасибо за комментарий.
Спасибо! Все очень понятно написано!