[Перевод] Выбор CSS макета — Grid или Flexbox?

5s44lw-ru8ew49fov8tcxrydwhw.png

Удачно оформленный макет удерживает пользователей на сайте, так как делает важные элементы доступными и легко находимыми. Слабые же макеты отпугивают посетителей, которые покидают ресурс, так и не найдя того, за чем пришли.
В веб-дизайне макет — это то, как сайт отображается на экране. В HTML 5 есть довольно много элементов, определяющих внешний вид веб-страницы: заголовок, навигационный блок, абзац, сноска, статья и нижний колонтитул, каждый из которых имеет свое особое значение в создании макета. Вместе же они формируют четыре основных раздела страницы — заголовок/баннер, поисковый блок, содержимое и нижний колонтитул.
Языки программирования помогают сделать сайты «живыми», но в основе каждой страницы по-прежнему лежит старый добрый HTML. При рассмотрении макетов необходимо учитывать факторы, определяющие их качество, а именно отзывчивость, порты просмотра, устройства отображения, браузеры и размеры экранов пользователей. Грамотный макет не только здорово смотрится, но также может сохранять задуманную структуру, вписываясь в экраны с любым возможным соотношением сторон. Как раз за эту подстройку и отвечает CSS. В текущей статье мы в общих чертах рассмотрим два его мощнейших инструмента: Flexbox и Grid.

Что такое макет CSS FLEXBOX?


Flexbox — это общепринятое сокращение для Flexible Box Module (модуль гибкого контейнера), который представляет собой одномерную модель макета. Это значит, что одновременно он может работать только со строкой или столбцом, но не с обоими сразу. Flexbox эффективно справляется с выравниванием, распределением и направлением элементов страницы.
Двумя основными понятиями этой модели макета являются главная ось и поперечная ось. Главная ось flex-контейнера — это основное направление, вдоль которого выстраиваются flex-элементы, поперечная же ось ей перпендикулярна.

Для начала давайте обернем HTML-элементы div во flex-wrapper.

Header
Nav
Content
Footer


В 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 инструкцией.

Header
Nav
Content
Aside
Section
Footer
.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: 40 px 1fr 20%; — эта строка дает браузеру команду присвоить первому div ширину 40 px, второй же занимает одну долю отведенного места, а третий 20%. Элементы с 4 по 6 автоматически смещаются под первые 3 и принимают те же значения в том же порядке, т.е. div 4 получает размер 40 px, div 5 — одну долю, а div 6 — 20%.
Чтобы поместить все шесть div-элементов в одну строку нужно указать в свойстве grid-template-column шесть значений. При этом не обязательно использовать для столбцов разные единицы измерения, можно задать только проценты, fr или px.

grid-template-rows: 200 px; — эта строка присваивает всем div-элементам высоту в 200 px.

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 сетка идеально подходит для создания галерей. С помощью небольшого количества кода и манипуляций вы можете создать их прекрасные отзывчивые макеты.

Мозаичный макет галереи


Такой макет создает равные плитки изображений, равномерно распределенные по странице/контейнеру.

Image One
Image Two
Image Three
Image Four
Image Five
Image Six
Image Seven
Image Eight
Image Nine
.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; }


Этот код создаст прекрасный макет плиточной галереи изображений.

iqifp2x94h7ti8pduj4b-fxmqu4.png


Мозаичный макет

Макет 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; 
}
ba41nenbqv_81dcrdictugxhmmi.png


Макет Masonry

GRID TEMPLATE AREAS


Свойство Grid-template-areas присваивает элементам имена, чтобы свойство grid-area могло на них ссылаться. Работает оно аналогично grid-column и grid-row, позволяя легко отображать и размещать конкретные области в структуре сетки.

Header
Nav
Aside
Content
Section
Footer
.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; }
5wqvgnq6jfgrh798rm0sfpz7py4.png

GRID AREAS


Ссылаться на именованные области необходимо в порядке их вызова. Например, область сетки для #one не может быть нижним колонтитулом, поскольку эта область сетки именуется последней. Нарушение же правильного порядка приведет к ошибке в дизайне.

Что же лучше — Flexbox или Grid?


В своей сути Grid является макетом на основе контейнеров, а Flexbox на основе содержимого. И тот, и другой по-своему эффективен, хотя CSS Grid включает больше возможностей и позволяет легче манипулировать строками и столбцами сетки. Прежде чем решать, какой использовать, следует проанализировать сложность, структуру и содержимое создаваемого вами сайта. Приведу еще одно несколько углубленное сравнение: в макете flexbox размер ячейки (flex-элемента) определяется в самом flex-элементе, а в макете Grid размер элемента определяется уже в его контейнере.
Лично я могу посоветовать использовать CSS Grid для общего макета сайта, а затем уже Flexbox для элементов контейнера. Однако CSS Grid также отлично работает с отдельными элементами и учитывает нюансы реальной структуры сетки лучше, чем Flexbox. Например, инструкция grid-template-areas отобразит структуру сайта буквально за несколько секунд, после чего вы сможете сосредоточится на выравнивании контента по своему усмотрению.

oug5kh6sjydt9llengsiebnp40w.png

3piw1j3wd_cgmzq9sefgferaumu.png

© Habrahabr.ru