CSS flexbox (Flexible Box Layout Module) — модуль макета гибкого контейнера — представляет собой способ компоновки элементов, в основе лежит идея оси.
Flexbox состоит из гибкого контейнера (flex container) и гибких элементов (flex items) . Гибкие элементы могут выстраиваться в строку или столбик, а оставшееся свободное пространство распределяется между ними различными способами.
Модуль flexbox позволяет решать следующие задачи:
- Располагать элементы в одном из четырех направлений: слева направо, справа налево, сверху вниз или снизу вверх.
- Переопределять порядок отображения элементов.
- Автоматически определять размеры элементов таким образом, чтобы они вписывались в доступное пространство.
- Решать проблему с горизонтальным и вертикальным центрированием.
- Переносить элементы внутри контейнера, не допуская его переполнения.
- Создавать колонки одинаковой высоты.
- Создавать прижатый к низу страницы .
Flexbox решает специфические задачи — создание одномерных макетов, например, навигационной панели, так как flex-элементы можно размещать только по одной из осей.
Что такое flexbox
Поддержка браузерами
IE: 11.0, 10.0 -ms-
Firefox: 28.0, 18.0 -moz-
Chrome: 29.0, 21.0 -webkit-
Safari: 6.1 -webkit-
Opera: 12.1 -webkit-
iOS Safari: 7.0 -webkit-
Opera Mini: 8
Android Browser: 4.4, 4.1 -webkit-
Chrome for Android: 44
1. Основные понятия
Рис. 1. Модель flexbox
Для описания модуля Flexbox используется определенный набор терминов. Значение flex-flow и режим записи определяют соответствие этих терминов физическим направлениям: верх / право / низ / лево, осям: вертикальная / горизонтальная и размерам: ширина / высота.
Главная ось (main axis) — ось, вдоль которой выкладываются flex-элементы. Она простирается в основном измерении.
Main start и main end — линии, которые определяют начальную и конечную стороны flex-контейнера, относительно которых выкладываются flex-элементы (начиная с main start по направлению к main end).
Основной размер (main size ) — ширина или высота flex-контейнера или flex-элементов, в зависимости от того, что из них находится в основном измерении, определяют основной размер flex-контейнера или flex-элемента.
Поперечная ось (cross axis) — ось, перпендикулярная главной оси. Она простирается в поперечном измерении.
Cross start и cross end — линии, которые определяют начальную и конечную стороны поперечной оси, относительно которых выкладываются flex-элементы.
Поперечный размер (cross size) — ширина или высота flex-контейнера или flex-элементов, в зависимости от того, что находится в поперечном измерении, являются их поперечным размером.
Рис. 2. Режим строки и колонки
2. Flex-контейнер
Flex-контейнер устанавливает новый гибкий контекст форматирования для его содержимого. Flex-контейнер не является блочным контейнером, поэтому для дочерних элементов не работают такие CSS-свойства, как float , clear , vertical-align . Также, на flex-контейнер не оказывают влияние свойства column-* , создающие колонки в тексте и псевдоэлементы::first-line и::first-letter .
Модель flexbox-разметки связана с определенным значением CSS-свойства display родительского html-элемента, содержащего внутри себя дочерние блоки. Для управления элементами с помощью этой модели нужно установить свойство display следующим образом:
Flex-container { /*генерирует flex-контейнер уровня блока*/ display: -webkit-flex; display: flex; } .flex-container { /*генерирует flex-контейнер уровня строки*/ display: -webkit-inline-flex; display: inline-flex; }
После установки данных значений свойства каждый дочерний элемент автоматически становится flex-элементом, выстраиваясь в один ряд (вдоль главной оси). При этом блочные и строчные дочерние элементы ведут себя одинаково, т.е. ширина блоков равна ширине их содержимого с учетом внутренних полей и рамок элемента.
Рис. 3. Выравнивание элементов в модели flexboxЕсли родительский блок содержит текст или изображения без оберток, они становятся анонимными flex-элементами. Текст выравнивается по верхнему краю блока-контейнера, а высота изображения становится равной высоте блока, т.е. оно деформируется.
3. Flex-элементы
Flex-элементы — блоки, представляющие содержимое flex-контейнера в потоке. Flex-контейнер устанавливает новый контекст форматирования для своего содержимого, который обуславливает следующие особенности:
- Для flex-элементов блокируется их значение свойства display . Значение display: inline-block; и display: table-cell; вычисляется в display: block; .
- Пустое пространство между элементами исчезает: оно не становится своим собственным flex-элементом, даже если межэлементный текст обернут в анонимный flex-элемент. Для содержимого анонимного flex-элемента невозможно задать собственные стили, но оно будет наследовать их (например, параметры шрифта) от flex-контейнера.
- Абсолютно позиционированный flex-элемент не участвует в компоновке гибкого макета.
- Поля margin соседних flex-элементов не схлопываются.
- Процентные значения margin и padding вычисляются от внутреннего размера содержащего их блока.
- margin: auto; расширяются, поглощая дополнительное пространство в соответствующем измерении. Их можно использовать для выравнивания или раздвигания смежных flex-элементов.
- Автоматический минимальный размер flex-элементов по умолчанию является минимальным размером его содержимого, то есть min-width: auto; . Для контейнеров с прокруткой автоматический минимальный размер обычно равен нулю.
4. Порядок отображения flex-элементов и ориентация
Содержимое flex-контейнера можно разложить в любом направлении и в любом порядке (переупорядочение flex-элементов внутри контейнера влияет только на визуальный рендеринг).
4.1. Направление главной оси: flex-direction
Свойство относится к flex-контейнеру. Управляет направлением главной оси, вдоль которой укладываются flex-элементы, в соответствии с текущим режимом записи. Не наследуется.
flex-direction | |
---|---|
Значения: | |
row | Значение по умолчанию, слева направо (в rtl справа налево). Flex-элементы выкладываются в строку. Начало (main-start) и конец (main-end) направления главной оси соответствуют началу (inline-start) и концу (inline-end) инлайн-оси (inline-axis). |
row-reverse | Направление справа налево (в rtl слева направо). Flex-элементы выкладываются в строку относительно правого края контейнера (в rtl — левого). |
column | Направление сверху вниз. Flex-элементы выкладываются в колонку. |
column-reverse | Колонка с элементами в обратном порядке, снизу вверх. |
initial | |
inherit |
Рис. 4. Свойство flex-direction для left-to-right языков
Синтаксис
Flex-container { display: -webkit-flex; -webkit-flex-direction: row-reverse; display: flex; flex-direction: row-reverse; }
4.2. Управление многострочностью flex-контейнера: flex-wrap
Свойство определяет, будет ли flex-контейнер однострочным или многострочным, а также задает направление поперечной оси, определяющее направление укладки новых линий flex-контейнера.
По умолчанию flex-элементы укладываются в одну строку, вдоль главной оси. При переполнении они будут выходить за пределы ограничивающей рамки flex-контейнера. Свойство не наследуется.
Рис. 5. Управление многострочностью с помощью свойства flex-wrap для LTR-языков
Синтаксис
Flex-container { display: -webkit-flex; -webkit-flex-wrap: wrap; display: flex; flex-wrap: wrap; }
4.3. Краткая запись направления и многострочности: flex-flow
Свойство позволяет определить направления главной и поперечной осей, а также возможность переноса flex-элементов при необходимости на несколько строк. Представляет собой сокращённую запись свойств flex-direction и flex-wrap . Значение по умолчанию flex-flow: row nowrap; . свойство не наследуется.
Синтаксис
Flex-container { display: -webkit-flex; -webkit-flex-flow: row wrap; display: flex; flex-flow: row wrap; }
4.4. Порядок отображения flex-элементов: order
Свойство определяет порядок, в котором flex-элементы отображаются и располагаются внутри flex-контейнера. Применяется к flex-элементам. Свойство не наследуется.
Первоначально все flex-элементы имеют order: 0; . При указании значения от -1 для элемента он перемещается в начало сроки, значение 1 — в конец. Если несколько flex-элементов имеют одинаковое значение order , они будут отображаться в соответствии с исходным порядком.
Синтаксис
Flex-container {
display: -webkit-flex;
display: flex;
}
.flex-item {
-webkit-order: 1;
order: 1;
}
Рис. 6. Порядок отображения flex-элементов
5. Гибкость flex-элементов
Определяющим аспектом гибкого макета является возможность «сгибать» flex-элементы, изменяя их ширину / высоту (в зависимости от того, какой размер находится на главной оси), чтобы заполнить доступное пространство в основном измерении. Это делается с помощью свойства flex . Flex-контейнер распределяет свободное пространство между своими дочерними элементами (пропорционально их коэффициенту flex-grow) для заполнения контейнера или сжимает их (пропорционально их коэффициенту flex-shrink), чтобы предотвратить переполнение.
Flex-элемент будет полностью «негибок», если его значения flex-grow и flex-shrink равны нулю, и «гибкий» в противном случае.
5.1. Задание гибких размеров одним свойством: flex
Свойство является сокращённой записью свойств flex-grow , flex-shrink и flex-basis . Значение по умолчанию: flex: 0 1 auto; . Можно указывать как одно, так и все три значения свойств. Свойство не наследуется.
Синтаксис
Flex-container { display: -webkit-flex; display: flex; } .flex-item { -webkit-flex: 3 1 100px; -ms-flex: 3 1 100px; flex: 3 1 100px; }
5.2. Коэффициент роста: flex-grow
Свойство определяет коэффициент роста одного flex-элемента относительно других flex-элементов в flex-контейнере при распределении положительного свободного пространства. Если сумма значений flex-grow flex-элементов в строке меньше 1, они занимают менее 100% свободного пространства. Свойство не наследуется.
Рис. 7. Управление свободным пространством в панели навигации с помощью flex-growСинтаксис
Flex-container { display: -webkit-flex; display: flex; } .flex-item { -webkit-flex-grow: 3; flex-grow: 3; }
5.3. Коэффициент сжатия: flex-shrink
Свойство указывает коэффициент сжатия flex-элемента относительно других flex-элементов при распределении отрицательного свободного пространства. Умножается на базовый размер flex-basis . Отрицательное пространство распределяется пропорционально тому, насколько элемент может сжаться, поэтому, например, маленький flex-элемент не уменьшится до нуля, пока не будет заметно уменьшен flex-элемент большего размера. Свойство не наследуется.
Рис. 8. Сужение flex-элементов в строке
Синтаксис
Flex-container { display: -webkit-flex; display: flex; } .flex-item { -webkit-flex-shrink: 3; flex-shrink: 3; }
5.4. Базовый размер: flex-basis
Свойство устанавливает начальный основной размер flex-элемента до распределения свободного пространства в соответствии с коэффициентами гибкости. Для всех значений, кроме auto и content , базовый гибкий размер определяется так же, как width в горизонтальных режимах записи. Процентные значения определяются относительно размера flex-контейнера, а если размер не задан, используемым значением для flex-basis являются размеры его содержимого. Не наследуется.
Синтаксис
Flex-container { display: -webkit-flex; display: flex; } .flex-item { -webkit-flex-basis: 100px; flex-basis: 100px; }
6. Выравнивание
6.1. Выравнивание по главной оси: justify-content
Свойство выравнивает flex-элементы по главной оси flex-контейнера, распределяя свободное пространство, незанятое flex-элементами. Когда элемент преобразуется в flex-контейнер, flex-элементы по умолчанию сгруппированы вместе (если для них не заданы поля margin). Промежутки добавляются после расчета значений margin и flex-grow . Если какие-либо элементы имеют ненулевое значение flex-grow или margin: auto; , свойство не будет оказывать влияния. Свойство не наследуется.
Значения: | |
flex-start | Значение по умолчанию. Flex-элементы выкладываются в направлении, идущем от начальной линии flex-контейнера. |
flex-end | Flex-элементы выкладываются в направлении, идущем от конечной линии flex-контейнера. |
center | Flex-элементы выравниваются по центру flex-контейнера. |
space-between | Flex-элементы равномерно распределяются по линии. Первый flex-элемент помещается вровень с краем начальной линии, последний flex-элемент — вровень с краем конечной линии, а остальные flex-элементы на линии распределяются так, чтобы расстояние между любыми двумя соседними элементами было одинаковым. Если оставшееся свободное пространство отрицательно или в строке присутствует только один flex-элемент, это значение идентично параметру flex-start . |
space-around | Flex-элементы на линии распределяются так, чтобы расстояние между любыми двумя смежными flex-элементами было одинаковым, а расстояние между первым / последним flex-элементами и краями flex-контейнера составляло половину от расстояния между flex-элементами. |
initial | Устанавливает значение свойства в значение по умолчанию. |
inherit | Наследует значение свойства от родительского элемента. |
Рис. 9. Выравнивание элементов и распределение свободного пространства с помощью свойства justify-content
Синтаксис
Flex-container { display: -webkit-flex; -webkit-justify-content: flex-start; display: flex; justify-content: flex-start; }
6.2. Выравнивание по поперечной оси: align-items и align-self
Flex-элементы можно выравнивать по поперечной оси текущей строки flex-контейнера. align-items устанавливает выравнивание для всех элементов flex-контейнера, включая анонимные flex-элементы. align-self позволяет переопределить это выравнивание для отдельных flex-элементов. Если любое из поперечных margin flex-элемента имеет значение auto , align-self не имеет никакого влияния.
6.2.1. Align-items
Свойство выравнивает flex-элементы, в том числе и анонимные flex-элементы по поперечной оси. Не наследуется.
Значения: | |
flex-start | |
flex-end | |
center | |
baseline | Базовые линии всех flex-элементов, участвующих в выравнивании, совпадают. |
stretch | |
initial | Устанавливает значение свойства в значение по умолчанию. |
inherit | Наследует значение свойства от родительского элемента. |
Синтаксис
Flex-container { display: -webkit-flex; -webkit-align-items: flex-start; display: flex; align-items: flex-start; }
6.2.2. Align-self
Свойство отвечает за выравнивание отдельно взятого flex-элемента по высоте flex-контейнера. Переопределяет выравнивание, заданное align-items . Не наследуется.
Значения: | |
auto | Значение по умолчанию. Flex-элемент использует выравнивание, указанное в свойстве align-items flex-контейнера. |
flex-start | Верхний край flex-элемента помещается вплотную с flex-линией (или на расстоянии, с учетом заданных полей margin и рамок border элемента), проходящей через начало поперечной оси. |
flex-end | Нижний край flex-элемента помещается вплотную с flex-линией (или на расстоянии, с учетом заданных полей margin и рамок border элемента), проходящей через конец поперечной оси. |
center | Поля flex-элемента центрируется по поперечной оси в пределах flex-линии. |
baseline | Flex-элемент выравнивается по базовой линии. |
stretch | Если поперечный размер flex-элемента вычисляется как auto и ни одно из поперечных значений margin не равно auto , элемент растягивается. Значение по умолчанию. |
initial | Устанавливает значение свойства в значение по умолчанию. |
inherit | Наследует значение свойства от родительского элемента. |
Рис. 11. Выравнивание отдельных flex-элементов
Синтаксис
Flex-container { display: -webkit-flex; display: flex; } .flex-item { -webkit-align-self: center; align-self: center; }
6.3. Выравнивание строк flex-контейнера: align-content
Свойство выравнивает строки в flex-контейнере при наличии дополнительного пространства на поперечной оси, аналогично выравниванию отдельных элементов на главной оси с помощью свойства justify-content . Свойство не влияет на однострочный flex-контейнер. Не наследуется.
Значения: | |
flex-start | Строки укладываются по направлению к началу flex-контейнера. Край первой строки помещается вплотную к краю flex-контейнера, каждая последующая — вплотную к предыдущей строке. |
flex-end | Строки укладываются по направлению к концу flex-контейнера. Край последней строки помещается вплотную к краю flex-контейнера, каждая предыдущая — вплотную к последующей строке. |
center | Строки укладываются по направлению к центру flex-контейнера. Строки расположены вплотную друг к другу и выровнены по центру flex-контейнера с равным расстоянием между начальным краем содержимого flex-контейнера и первой строкой и между конечным краем содержимого flex-контейнера и последней строкой. |
space-between | Строки равномерно распределены в flex-контейнере. Если оставшееся свободное пространство отрицательно или в flex-контейнере имеется только одна flex-линия, это значение идентично flex-start . В противном случае край первой строки помещается вплотную к начальному краю содержимого flex-контейнера, край последней строки — вплотную к конечному краю содержимого flex-контейнера. Остальные строки распределены так, чтобы расстояние между любыми двумя соседними строками было одинаковым. |
space-around | Строки равномерно распределены в flex-контейнере с половинным пробелом на обоих концах. Если оставшееся свободное пространство отрицательно, это значение идентично цент center . В противном случае строки распределяются таким образом, чтобы расстояние между любыми двумя соседними строками было одинаковым, а расстояние между первой / последней строками и краями содержимого flex-контейнера составляло половину от расстояния между строками. |
stretch | Значение по умолчанию. Строки flex-элементов равномерно растягиваются, заполняя все доступное пространство. Если оставшееся свободное пространство отрицательно, это значение идентично flex-start . В противном случае свободное пространство будет разделено поровну между всеми строками, увеличивая их поперечный размер. |
initial | Устанавливает значение свойства в значение по умолчанию. |
inherit | Наследует значение свойства от родительского элемента. |
Синтаксис
Flex-container { display: -webkit-flex; -webkit-flex-flow: row wrap; -webkit-align-content: flex-end; display: flex; flex-flow: row wrap; align-content: flex-end; height: 100px; }
Flexbox по праву можно назвать удачной попыткой решения огромного спектра проблем при построении лейаутов в css. Но прежде чем перейти к его описанию, давайте выясним, что же не так со способами верстки, которыми мы пользуемся сейчас?
Любой верстальщик знает несколько путей выровнять что-либо по вертикали или сделать 3-х колоночный макет с резиновой средней колонкой. Но давайте признаем, что все эти способы довольно странные, похожи на хак, подходят не во всех случаях, сложны для восприятия и не работают при несоблюдении определенных магических условий, которые сложились исторически.
Случилось так потому, что html и css развивались эволюционно. В начале веб-страницы были похожи на однопоточные текстовые документы, чуть позже разбиение страницы на блоки делали таблицами, затем стало модным верстать float-ами, а после официальной смерти ie6 добавились еще и приемы с inline-block. В итоге мы получили в наследство гремучую смесь всех этих приемов, используемую для построения лейаутов 99,9% всех существующих веб-страниц.
Многострочная организация блоков внутри 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’>
CSS
/* т.е. ... */ .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-контейнеру, а не к его дочерним элементам.
Демо свойств многострочности в 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"> ]
CSS
/* т.е. ... */ .my-flex-block{ flex-grow:12; flex-shrink:3; flex basis: 30em; } /* это то же самое, что... */ .my-flex-block{ flex: 12 3 30em; }Демо для flex-grow, flex-shrink и flex-basis
align-self – выравнивание отдельно взятого flex-блока по поперечной оси.
Делает возможным переопределять свойство flex-контейнера align-items для отдельного flex-блока.
Доступные значения align-self (те же 5 вариантов, что и для align-items)
- flex-start: flex-блок прижат к началу поперечной оси
- flex-end: flex-блок прижат к концу поперечной оси
- center: flex-блок располагаются в центре поперечной оси
- baseline: flex-блок выравнен по baseline
- stretch (значение по умолчанию) : flex-блок растянут, чтобы занять все доступное место по поперечной оси, при этом учитываются min-width / max-width , если таковые заданы.
order – порядок следования отдельно взятого flex-блока внутри flex-контейнера.
По умолчанию все блоки будут следовать друг за другом в порядке, заданном в html. Однако этот порядок можно изменить с помощью свойства order . Оно задается целым числом и по умолчанию равно 0 .
Значение order не задает абсолютную позицию элемента в последовательности. Оно определяет вес позиции элемента.
HTML
В данном случае, блоки будут следовать один за другим вдоль главной оси в следующем порядке: item5, item1, item3, item4, item2
Демо для align-self и order
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 и т.п.). Это все еще спорный момент, но эта статья довольно убедительно показывает недостатки xanthir.com/blog/b4580
В заключение
Я думаю, что flexbox, конечно же, не вытеснит все остальные способы верстки, но, безусловно, в ближайшее время займет достойную нишу при решении огромного количества задач. И уж точно, пробовать работать с ним нужно уже сейчас. Одна из следующих статей будет посвящена конкретным примерам работы с flex-версткой. Подписывайтесь на новости;)
О том, как просто работать с Flexbox на примере верстки шаблона новостного сайта.
Поверьте, нет никакой необходимости в детальном разборе всех аспектов работы с Flexbox, если вы хотите начать им пользоваться уже сейчас. В этом руководстве автор собирается познакомить вас с некоторыми свойствами Flexbox и сделать «новостной лейаут» наподобие того, который вы могли видеть на сайте The Guardian .
Причина, по которой автор использует Flexbox – это большое количество возможностей, которые он предоставляет:
- легкость в создании адаптивных столбцов;
- создание столбцов одинаковой высоты;
- возможность прижатия содержимого к низу контейнера.
Ну, поехали!
1. Начинаем с создания двух столбцов
Создание столбцов при помощи CSS всегда влекло за собой определенные трудности. На протяжении длительного времени для выполнения данной задачи широко использовались (и используются) float’ы и / или таблицы, но каждый из этих методов имел (и имеет) свои недостатки.В свою очередь, Flexbox упрощает этот процесс, обладая рядом таких преимуществ, как:
Написание более «чистого» кода: от нас лишь требуется создать контейнер с правилом display: flex;
- гибкость: мы можем изменять размер, растягивать и выравнивать столбцы путем изменения пары строк CSS;
- семантическая разметка;
- кроме того, с использованием Flexbox отпадает необходимость отменять обтекание во избежание непредсказуемого поведения лейаута.
Давайте начнем работу с создания двух столбцов, один из которых будет занимать 2/3 ширины нашего контейнера, а еще один - 1/3 его часть.
Здесь присутствуют два элемента:
Контейнер columns;
- два дочерних элемента column
, один из которых имеет дополнительный класс main-column
, который мы используем позже для того, чтобы сделать столбец шире.
Columns {
display: flex;
}
.column {
flex: 1;
}
.main-column {
flex: 2;
}
Поскольку main-column
имеет значение flex равное 2
, то этот столбец займет в два раза больше места, чем второй.
Добавим немного визуального оформления и, в итоге, получим:
Кликните для просмотра в действии
2. Делаем каждый столбец flexbox-контейнером
Каждый из двух столбцов будет содержать несколько вертикально расположенных статей, поэтому из этих двух элементов мы, в свою очередь, также должны сделать flexbox-контейнеры.Итак, нам необходимо, чтобы статьи:
Располагались вертикально внутри столбца-контейнера;
- занимали все доступное место.
Правило flex-direction: column , указанное для контейнера, вместе с правилом flex: 1 , указанным для дочернего элемента, позволяет статье заполнить все свободное место по вертикали, при этом высота первых двух столбцов останется неизменной.
Кликните для просмотра в действии
3. Делаем контейнер из статьи
Теперь, чтобы еще больше расширить наши возможности, давайте представим каждую статью в виде flexbox-контейнера. Каждый такой контейнер будет содержать:Заголовок;
- параграф;
- информационную панель с именем автора и количеством комментариев;
- какую-нибудь адаптивную картинку.
Здесь мы используем Flexbox для того, чтобы «прижать» информационную панель к низу элемента. Вот, посмотрите, какой результат мы ожидаем получить.
А вот и сам код:
.article {
display: flex;
flex-direction: column;
flex-basis: auto; /* Устанавливает начальный размер элемента в зависимости от его содержимого */
}
.article-body {
display: flex;
flex: 1;
flex-direction: column;
}
.article-content {
flex: 1; /* Содержимое заполняет все оставшееся место, тем самым прижимая информационную панель к нижней части */
}
Элементы внутри статьи расположены вертикально благодаря использованию правила flex-direction: column
.
Также мы применили свойство flex: 1 к элементу article-content , тем самым растянув его на все свободное место и прижав article-info к низу. Высота столбцов в этом случае не имеет значения.
Кликните для просмотра в действии
4. Добавляем несколько вложенных столбцов
На самом деле, нам нужно, чтобы левый столбец включал в себя еще несколько столбцов. Поэтому нам необходимо заменить второй элемент, отвечающий за статью, контейнером columns , который мы использовали ранее.
Поскольку мы хотим, чтобы первый вложенный столбец был шире, добавим к элементу класс nested-column , а в CSS укажем:
Nested-column {
flex: 2;
}
Теперь этот столбец будет вдвое шире второго.
Кликните для просмотра в действии
5. Делаем первую статью с горизонтальным лейаутом
Первая статья у нас на самом деле большая. Дабы эффективно использовать место на экране монитора, давайте изменим ее ориентацию на горизонтальную.First-article {
flex-direction: row;
}
.first-article .article-body {
flex: 1;
}
.first-article .article-image {
height: 300px;
order: 2;
padding-top: 0;
width: 400px;
}
Свойство order
в данном случае играет большую роль, поскольку оно позволяет изменять очередность HTML-элементов без изменения HTML-разметки. В действительности, article-image
в коде идет перед элементом article-body
, но ведет себя так, будто стоит после него.
Кликните для просмотра в действии
6. Делаем адаптивный лейаут
Теперь все выглядит так, как мы хотели, хотя и немного сплющено. Давайте исправим это, добавив нашему лейауту гибкости.Одной из замечательных вещей в Flexbox является то, что достаточно удалить правило display: flex в контейнере для того, чтобы полостью отключить его (Flexbox), в то время, как остальные его свойства (такие, как align-items или flex ) останутся рабочими.
В результате, мы можем активировать адаптивный лейаут, задействовав Flexbox только тогда, когда в этом будет необходимость.
Итак, мы собираемся удалить display: flex из селекторов .columns и .column , вместо этого «запаковав» их в медиа-запрос:
@media screen and (min-width: 800px) {
.columns,
.column {
display: flex;
}
}
Вот и все! На экранах с маленьким разрешением все статьи будут располагаться друг над другом, а на экранах с разрешением свыше 800 пикселей - в два столбца.
7. Добавляем завершающие штрихи
Для того, чтобы лейаут выглядел более привлекательно на больших экранах, давайте добавим кое-какие CSS-твики: @media screen and (min-width: 1000px) {
.first-article {
flex-direction: row;
}
.first-article .article-body {
flex: 1;
}
.first-article .article-image {
height: 300px;
order: 2;
padding-top: 0;
width: 400px;
}
.main-column {
flex: 3;
}
.nested-column {
flex: 2;
}
}
Содержимое первой статьи выровнено по горизонтали: текст расположен по левой стороне, а картинка - по правой. Также, главный столбец теперь стал шире (75%). То же самое касается и вложенного столбца (66%).
А вот и финальный результат!
Кликните для просмотра в действии
Вывод
Теперь вы и сами видите, что использовать Flexbox в своих проектах можно даже не вникая во все его тонкости, и созданный лейаут - наглядный тому пример. По крайней мере, автор очень надеется на это.Дэнни Марков
Дизайн довольно простой - он состоит из выровненного по центру контейнера, внутри которого у нас есть шапка, основной раздел, боковая панель и подвал. Вот главные «испытания», которые мы должны провести, сохраняя CSS и HTML по возможности чистыми:
- Разместить четыре основных раздела макета.
- Сделать страницу адаптивной (боковая панель опускается ниже основного содержимого на маленьких экранах).
- Выровнять содержимое шапки - навигация слева, кнопка справа.
Как вы можете видеть, ради сравнения мы оставили всё максимально простым. Начнём с первого испытания.
Испытание 1. Размещение разделов страницы
Решение на Flexbox
Добавляем display: flex к контейнеру и задаём направление дочерних элементов по вертикали. Это позиционирует все разделы друг под другом.
Container { display: flex; flex-direction: column; }
Теперь нам нужно сделать так, чтобы основной раздел и боковая панель располагались рядом. Поскольку flex-контейнеры обычно однонаправлены, нам нужно добавить дополнительный элемент.
Затем мы устанавливаем этому элементу display: flex и flex-direction с противоположным направлением.
Main-and-sidebar-wrapper { display: flex; flex-direction: row; }
Последний шаг - задать размеры основного раздела и боковой панели. Мы хотим, чтобы основное содержимое было в три раза шире боковой панели, что несложно сделать с помощью flex или процентов.
Как вы можете видеть, Flexbox сделал всё хорошо, но нам кроме этого понадобилось довольно много свойств CSS плюс дополнительный элемент HTML. Давайте посмотрим, как будет работать CSS Grid.
Решение на CSS Grid
Существует несколько вариантов использования CSS Grid, но мы воспользуемся синтаксисом grid-template-areas , как наиболее подходящего для наших целей.
Сперва мы определим четыре grid-area , по одному на каждый раздел страницы:
Теперь мы можем настроить нашу сетку и определить расположение каждой области. Вначале код может показаться довольно сложным, но как только вы познакомитесь с системой сетки, он становится проще для понимания.
Container { display: grid; /* Определяем размер и число колонок нашей сетки. Единица fr работает подобно Flexbox: колонки делят свободное пространство в строке согласно их значениям. У нас будет две колонки - первая в три раза больше второй. */ grid-template-columns: 3fr 1fr; /* Связываем сделанные ранее области с местами в сетке. Первая строка - шапка. Вторая строка делится между основным разделом и боковой панелью. Последняя строка - подвал. */ grid-template-areas: "header header" "main sidebar" "footer footer"; /* Интервал между ячейками сетки будет 60 пикселей */ grid-gap: 60px; }
Вот и всё! Наш макет теперь будет соответствовать указанной выше структуре и мы его настроили так, что нам не придётся иметь дело с margin или padding .
Испытание 2. Делаем страницу адаптивной
Решение на Flexbox
Выполнение этого шага строго связано с предыдущим. Для решения на Flexbox нам придётся изменить flex-direction и отрегулировать margin .
@media (max-width: 600px) { .main-and-sidebar-wrapper { flex-direction: column; } .main { margin-right: 0; margin-bottom: 60px; } }
Наша страница довольно простая, поэтому в медиа-запросе мало работы, но в более сложном макете придётся много чего переделывать.
Решение на CSS Grid
Поскольку мы уже определили grid-areas , нам просто нужно переопределить их порядок в медиа-запросе. Мы можем использовать ту же настройку колонок.
@media (max-width: 600px) { .container { /* Выравнивание областей сетки для мобильного макета */ grid-template-areas: "header header" "main main" "sidebar sidebar" "footer footer"; } }
Или можем переопределить весь макет с нуля, если считаем, что это решение чище.
@media (max-width: 600px) { .container { /* Переделываем сетку в одноколоночный макет */ grid-template-columns: 1fr; grid-template-areas: "header" "main" "sidebar" "footer"; } }
Испытание 3. Выравнивание компонентов шапки
Решение на Flexbox
Мы уже делали похожий макет на Flexbox в одной из наших старых статей - . Техника довольно простая:
Header { display: flex; justify-content: space-between; }
Теперь список навигации и кнопка выровнены правильно. Осталось только разместить пункты внутри
Header nav { display: flex; align-items: baseline; }
Только две строки! Совсем неплохо. Давайте посмотрим, как с этим справится CSS Grid.
Решение на CSS Grid
Чтобы разделить навигацию и кнопку, мы должны добавить display: grid к header и настроить двухколоночную сетку. Нам также понадобятся две дополнительные строки в CSS, чтобы позиционировать всё на соответствующих границах.
Header{ display: grid; grid-template-columns: 1fr 1fr; } header nav { justify-self: start; } header button { justify-self: end; }
Что касается ссылок в одну строку внутри навигации, у нас не получилось сделать это корректно с CSS Grid. Вот как выглядит наша лучшая попытка:
Header nav { display: grid; grid-template-columns: auto 1fr 1fr; align-items: end; }
Понятно, что CSS Grid не справилась с этой частью макета, но это и не удивительно - основное внимание уделяется выравниванию контейнеров, а не содержимому внутри них. Эта система не для нанесения последних штрихов.
Выводы
Если вы прочитали статью целиком (а это отличная работа!), выводы не должны вас удивить. На деле нет лучшей системы - и Flexbox и CSS Grid хороши по своему и должны использоваться совместно, а не как альтернатива друг другу.
Для тех из вас, кто перепрыгнул непосредственно к выводам этой статьи (не волнуйтесь, мы тоже так делаем), вот краткий итог сравнения:
- CSS Grid отлично подходит для создания большой картины. Эта система облегчает управление макетом страницы и даже может иметь дело с нестандартным и асимметричным дизайном.
- Flexbox отлично подходит для выравнивания содержимого внутри элементов. Используйте эту систему для размещения мелких деталей дизайна.
- Используйте CSS Grid для двумерных макетов (строк И колонок).
- Flexbox лучше работает только в одном измерении (со строками ИЛИ с колонками).
- Нет причин применять только CSS Grid или только Flexbox. Изучайте их и используйте совместно.
Why Flexbox?
For a long time, the only reliable cross browser-compatible tools available for creating CSS layouts were things like floats and positioning . These are fine and they work, but in some ways they are also rather limiting and frustrating.
The following simple layout requirements are either difficult or impossible to achieve with such tools, in any kind of convenient, flexible way:
- Vertically centering a block of content inside its parent.
- Making all the children of a container take up an equal amount of the available width/height, regardless of how much width/height is available.
- Making all columns in a multiple column layout adopt the same height even if they contain a different amount of content.
As you"ll see in subsequent sections, flexbox makes a lot of layout tasks much easier. Let"s dig in!
Introducing a simple example
In this article we are going to get you to work through a series of exercises to help you understand how flexbox works. To get started, you should make a local copy of the first starter file - flexbox0.html from our github repo - load it in a modern browser (like Firefox or Chrome), and have a look at the code in your code editor. You can also.
Flex-direction: column;
You"ll see that this puts the items back in a column layout, much like they were before we added any CSS. Before you move on, delete this declaration from your example.
Note : You can also lay out flex items in a reverse direction using the row-reverse and column-reverse values. Experiment with these values too!
Wrapping
One issue that arises when you have a fixed amount of width or height in your layout is that eventually your flexbox children will overflow their container, breaking the layout. Have a look at our flexbox-wrap0.html example, and try viewing it live (take a local copy of this file now if you want to follow along with this example):
Here we see that the children are indeed breaking out of their container. One way in which you can fix this is to add the following declaration to your element represents a standalone section - which doesn" t have a more specific semantic element to represent it contained within an html document.>
Flex-wrap: wrap; flex: 200px;
Try this now; you"ll see that the layout looks much better with this included:
We now have multiple rows - as many flexbox children are fitted onto each row as makes sense, and any overflow is moved down to the next line. The flex: 200px declaration set on the articles means that each will be at least 200px wide; we"ll discuss this property in more detail later on. You might also notice that the last few children on the last row are each made wider so that the entire row is still filled.
But there"s more we can do here. First of all, try changing your flex-direction property value to row-reverse - now you"ll see that you still have your multiple row layout, but it starts from the opposite corner of the browser window and flows in reverse.
flex-flow shorthand
At this point it is worth noting that a shorthand exists for flex-direction and flex-wrap - flex-flow . So for example, you can replace
Flex-direction: row; flex-wrap: wrap;
Flex-flow: row wrap;
Flexible sizing of flex items
Let"s now return to our first example, and look at how we can control what proportion of space flex items take up. Fire up your local copy of flexbox0.html , or take a copy of flexbox1.html as a new starting point (see it live).
First, add the following rule to the bottom of your CSS:
Article { flex: 1; }
This is a unitless proportion value that dictates how much of the available space along the main axis each flex item will take up. In this case, we are giving each element a value of 1, which means they will all take up an equal amount of the spare space left after things like padding and margin have been set. It is a proportion, meaning that giving each flex item a value of 400000 would have exactly the same effect.
Now add the following rule below the previous one:
Article:nth-of-type(3) { flex: 2; }
Section - article article article - div - button div button div button button button
Let"s look at the code we"ve used for the layout.
Summary
That concludes our tour of the basics of flexbox. We hope you had fun, and will have a good play around with it as you travel forward with your learning. Next we"ll have a look at another important aspect of CSS layouts - CSS Grids.