Выбор CSS макета — Grid или Flexbox?
Блог компании RUVDS.com Разработка веб-сайтов * CSS * Программирование *
Перевод
Автор оригинала: Ivaylo Ivanov
Удачно оформленный макет удерживает пользователей на сайте, так как делает важные элементы доступными и легко находимыми. Слабые же макеты отпугивают посетителей, которые покидают ресурс, так и не найдя того, за чем пришли.
В веб-дизайне макет – это то, как сайт отображается на экране. В HTML 5 есть довольно много элементов, определяющих внешний вид веб-страницы: заголовок, навигационный блок, абзац, сноска, статья и нижний колонтитул, каждый из которых имеет свое особое значение в создании макета. Вместе же они формируют четыре основных раздела страницы – заголовок/баннер, поисковый блок, содержимое и нижний колонтитул.
Языки программирования помогают сделать сайты «живыми», но в основе каждой страницы по-прежнему лежит старый добрый HTML. При рассмотрении макетов необходимо учитывать факторы, определяющие их качество, а именно отзывчивость, порты просмотра, устройства отображения, браузеры и размеры экранов пользователей. Грамотный макет не только здорово смотрится, но также может сохранять задуманную структуру, вписываясь в экраны с любым возможным соотношением сторон. Как раз за эту подстройку и отвечает CSS. В текущей статье мы в общих чертах рассмотрим два его мощнейших инструмента: Flexbox и Grid.
Что такое макет CSS FLEXBOX?
Flexbox – это общепринятое сокращение для Flexible Box Module (модуль гибкого контейнера), который представляет собой одномерную модель макета. Это значит, что одновременно он может работать только со строкой или столбцом, но не с обоими сразу. Flexbox эффективно справляется с выравниванием, распределением и направлением элементов страницы.
Двумя основными понятиями этой модели макета являются главная ось и поперечная ось. Главная ось flex-контейнера – это основное направление, вдоль которого выстраиваются flex-элементы, поперечная же ось ей перпендикулярна.
Для начала давайте обернем HTML-элементы div во flex-wrapper.
<div class="flex-wrapper">
<div id="one">Header</div>
<div id="two">Nav</div>
<div id="three">Content</div>
<div id="four">Footer</div>
</div>
В CSS родительский контейнер “flex-wrapper” преобразуется во flexbox с помощью простой инструкции.
.flex-wrapper {
display: flex;
}
При добавлении элементов и свойств я буду использовать яркие цвета и отступы, чтобы выделить контейнеры и div-элементы.
.flex-wrapper{
display: flex;
background-color: beige;
}
.flex-wrapper > div {
background-color: green;
height: 100px;
width: 100px;
margin: 10px;
}
Вы можете видеть, как удачно элементы div располагаются по горизонтали, но при этом они занимают не всю область контейнера, и в конце остается пустое пространство. Это можно исправить, добавив flex-grow.
.flex-wrapper > div {
flex-grow: 1;
}
Свойство flex-grow отвечает за распределение каждого элемента flex-контейнера. По умолчанию значение этого свойства равно 0, присваивая же разное количество единиц div-элементам, вы увеличиваете их по отношению к остальным. Противоположный эффект дает свойство flex-shrink.
#one{
flex-grow: 10;
}
/* таким образом первый div-элемент станет на 10 единиц больше остальных */
FLEX-DIRECTION
Flex-direction определяет направление размещения элементов контейнера. С его помощью можно заставить их располагаться по направлению вверх, вниз, влево или вправо, а также в обратном порядке. По умолчанию элементы flex-контейнера упорядочены вдоль главной оси слева направо.
.flex-wrapper{
display: flex;
flex-direction: row; /* направление по умолчанию */
}
.flex-wrapper{
display: flex;
flex-direction: row-reverse;
}
Здесь элементы также отображаются слева направо, но в обратном порядке. В итоге четвертый div становится первым, а первый, в свою очередь, последним.
.flex-wrapper{
display: flex;
flex-direction: column;
}
Здесь же упорядочивание происходит уже вертикально – сверху вниз.
.flex-wrapper{
display: flex;
flex-direction: column-reverse;
}
Теперь элементы также расположены вертикально, но в обратном порядке, т.е. четвертый оказался вверху, а первый внизу.
FLEX BASIS
Flex basis определяет размер элемента внутри контейнера. При этом значение размера может указываться в em, px или процентах. Это свойство отличается от flex-grow тем, что не распределяет пространство между элементами контейнера равномерно.
#three {
flex-basis: 200px;
}
FLEX
Flex – это сокращенное свойство, объединяющее flex-shrink, flex-grow и flex-basis. Его рекомендуется использовать вместо раздельного написания свойств, указывая в нем их значения в следующем порядке: flex-grow, flex-shrink, flex-basis.
.flex-wrapper {
display: flex;
flex: 0 0 200px;
}
JUSTIFY-CONTENT И ALIGN-SELF
Justify-content и align-self – это идеальное решение для размещения div или контейнера в центре окна браузера.
.flex-wrapper {
display: flex;
flex: 0 0 200px;
justify-content: center;
align-items: center;
}
CSS GRID Layout
CSS grid (сетка) представляет собой мощный двухмерный макет, при использовании которого можно одновременно работать со строками и столбцами. В основе CSS Grid лежит неявное разделение экрана на сетку из 12 частей, в которые в итоге и вписываются элементы.
Преимущество этой технологии перед Flexbox и другими видами макетов в ее возможности работать двухмерно. При этом она также упрощает позиционирование, и элементы контейнера могут размещаться, перекрывая друг на друга.
ОПРЕДЕЛЕНИЕ СЕТКИ В CSS GRID
Преобразование HTML-структуры в СSS сетку выполняется одной простой CSS инструкцией.
<div class="container">
<div id="one">Header</div>
<div id="two">Nav</div>
<div id="three">Content</div>
<div id="four">Aside</div>
<div id="five">Section</div>
<div id="six">Footer</div>
</div>
.container {
display: grid;
}
GRID TEMPLATE-COLUMNS И GRID-TEMPLATE-ROWS
Свойства grid-template-columns и grid-template-row устанавливают величину столбца или строки, определяя размер div-элементов согласно присвоенным значениям, которые указываются в px, fr, процентах или em.
.container {
display: grid;
grid-template-columns: 40px 1fr 20%;
grid-template-rows: 200px;
background-color: beige;
}
.container > div {
background-color: green;
margin: 10px;
}
grid-template-columns: 40px 1fr 20%; — эта строка дает браузеру команду присвоить первому div ширину 40px, второй же занимает одну долю отведенного места, а третий 20%. Элементы с 4 по 6 автоматически смещаются под первые 3 и принимают те же значения в том же порядке, т.е. div 4 получает размер 40px, div 5 — одну долю, а div 6 – 20%.
Чтобы поместить все шесть div-элементов в одну строку нужно указать в свойстве grid-template-column шесть значений. При этом не обязательно использовать для столбцов разные единицы измерения, можно задать только проценты, fr или px.
grid-template-rows: 200px; — эта строка присваивает всем div-элементам высоту в 200px.
FR
.container {
display: grid;
grid-template-columns: 16.7% 16.7% 16.7% 16.7% 16.7% 16.7%;
}
Присвоив 16,7% для 6 точек, я успешно разделил шесть элементов контейнера по шести равным частям экрана. Значение 16,7% я выбрал, потому что при умножении 16,7 на 6 как раз получится 100% ширины экрана.
Использование процентов и пикселей работает идеально, но им недостает гибкости, и они уступают наиболее эффективному компоненту – долям CSS сетки.
Fr – это дробная единица, которая присваивает каждому элементу одну долю доступного пространства, которое можно увеличивать, выделяя под div необходимую ему область.
Теперь наше свойство grid-template-columns стало:
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
В результате каждый div-элемент был размещен на экране равномерно.
grid-template-columns: 1fr 2fr 1fr 2fr 1fr 1fr;
Изменив второе и четвертое значения, мы сделали соответствующие элементы вдвое больше остальных. Самое же главное, что они по-прежнему распределяются в браузере равномерно и имеют высокую отзывчивость.
ФУНКЦИЯ REPEAT
Вместо того, чтобы повторно переписывать значения, можно задействовать функцию repeat, которая позволит сделать это всего один раз.
.container {
display: grid;
grid-template-columns: repeat(6, 1fr);
}
Синтаксис этой функции относительно прост. Сначала пишем слово “repeat”, после которого определяем, сколько раз нужно повторить размер, в данном случае 6, а затем указываем величину единицы измерения. Эта функция аналогичным образом работает со свойством template-row и позволяет использовать как fr, em, px, так и проценты.
GAP
Gap – это отступ, представляющий свойство CSS сетки, которое позволяет указывать расстояние между div-элементами контейнера. Работает оно точно также, как свойство margin и измеряется обычно в px.
gap: 10px;
GRID-COLUMN-START/GRID-COLUMN-END И GRID-ROW-START/GRID-ROW-END
Свойства grid-column-start и grid-column-end помещают элемент сетки в конкретное место столбца относительно определенных строк сетки. Свойства же grid-row-start и grid-row-end делают то же самое, но в отношении строки. Присваивая этим свойствам значения, можно удобно управлять начальной и конечной точкой элемента сетки, выделяя ему нужную область.
.container {
display: grid;
grid-template-columns: repeat (3, 1fr);
grid-template-rows: repeat(4, 200px);
}
#one {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 4;
}
Если вы присвоите указанные значения первому div, то заметите, что он смещает второй div на одну единицу и занимает первые две позиции, смещая третий div вниз. В отношении же строк теперь он занимает три позиции и становится выше.
В программировании индексация производится по особому правилу, согласно которому мы обычно начинаем отсчет с 0. В этом случае последнее значение, как правило, упоминается, но не учитывается. Например, значение свойства grid-column-end равно 3, но по факту оканчивается оно на 2-х также, как и grid-row-end оканчивается на 3-х, а не на 4-х.
GRID-COLUMNS И GRID-ROW
Это сокращенный вариант для свойств grid-column-start/grid-column-end и grid-row-start/grid-row-end. В качестве значений в этом случае через слэш указываются начальные и конечные позиции элемента:
#one {
grid-column: 1/3;
grid-row: 1/4;
}
СОЗДАНИЕ ГАЛЕРЕЙ
CSS сетка идеально подходит для создания галерей. С помощью небольшого количества кода и манипуляций вы можете создать их прекрасные отзывчивые макеты.
Мозаичный макет галереи
Такой макет создает равные плитки изображений, равномерно распределенные по странице/контейнеру.
<div class="container">
<div id="one">Image One</div>
<div id="two">Image Two</div>
<div id="three">Image Three</div>
<div id="four">Image Four</div>
<div id="five">Image Five</div>
<div id="six">Image Six</div>
<div id="seven">Image Seven</div>
<div id="eight">Image Eight</div>
<div id="nine">Image Nine</div>
</div>
.container{
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 200px);
background-color: beige;
gap: 10px
}
.container > div {
background-color: green;
}
Этот код создаст прекрасный макет плиточной галереи изображений.
Мозаичный макет
Макет Masonry-галереи
Этот макет уже неравномерен, так как не имеет фиксированной высоты строк. Однако при помощи grid-columns и grid-rows мы можем подстраивать изображения, чтобы они вписывались в назначенные дробные единицы и перемещались по ним нужным нам образом.
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(5, 200px);
background-color: beige;
gap: 10px;
}
.container > div {
background-color: green;
}
#one {
grid-column: 1/3;
grid-row: 1/4;
}
#two {
grid-row: 1/3;
}
#five {
grid-column: 4/2;
}
#seven {
grid-row: 6/1;
}
Макет Masonry
GRID TEMPLATE AREAS
Свойство Grid-template-areas присваивает элементам имена, чтобы свойство grid-area могло на них ссылаться. Работает оно аналогично grid-column и grid-row, позволяя легко отображать и размещать конкретные области в структуре сетки.
<div class="container">
<div id="one">Header</div>
<div id="two">Nav</div>
<div id="three">Aside</div>
<div id="four">Content</div>
<div id="five">Section</div>
<div id="six">Footer</div>
</div>
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2,100px);
background-color: beige;
gap: 10px;
grid-template-areas: 'header header header'
'nav nav nav'
'aside content content'
'aside section section'
'footer footer footer';
}
.container > div {
background-color: green;
font-size: 40px;
}
#one {
grid-area: header;
}
#two {
grid-area: nav;
}
#three {
grid-area: aside;
}
#four {
grid-area: content;
}
#five {
grid-area: section;
}
#six {
grid-area: footer;
}
GRID AREAS
Ссылаться на именованные области необходимо в порядке их вызова. Например, область сетки для #one не может быть нижним колонтитулом, поскольку эта область сетки именуется последней. Нарушение же правильного порядка приведет к ошибке в дизайне.
Что же лучше — Flexbox или Grid?
В своей сути Grid является макетом на основе контейнеров, а Flexbox на основе содержимого. И тот, и другой по-своему эффективен, хотя CSS Grid включает больше возможностей и позволяет легче манипулировать строками и столбцами сетки. Прежде чем решать, какой использовать, следует проанализировать сложность, структуру и содержимое создаваемого вами сайта. Приведу еще одно несколько углубленное сравнение: в макете flexbox размер ячейки (flex-элемента) определяется в самом flex-элементе, а в макете Grid размер элемента определяется уже в его контейнере.
Лично я могу посоветовать использовать CSS Grid для общего макета сайта, а затем уже Flexbox для элементов контейнера. Однако CSS Grid также отлично работает с отдельными элементами и учитывает нюансы реальной структуры сетки лучше, чем Flexbox. Например, инструкция grid-template-areas отобразит структуру сайта буквально за несколько секунд, после чего вы сможете сосредоточится на выравнивании контента по своему усмотрению.