company_banner

Выбор CSS макета — Grid или Flexbox?

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



RUVDS.com
VDS/VPS-хостинг. Скидка 10% по коду HABR

Похожие публикации

Комментарии 8

    +1
    у меня была пара проектов, где IE 11 был обязательным условием. Пришлось с тех пор, на всякий случай, отказаться от удобных гридов, хоть они и «расписные» такие.
      +1
      у меня до сих пор один проект существует на гридах, где поддержка ie11 была нужна априори — процент клиентов с ie тогда(года 3 назад) была порядка 27%.
      При этом от гридов не отказывались, а прописать пришлось вручную что то вроде этого
       -ms-grid-columns: 32% 20px 32% 20px 32%;
          -ms-grid-rows: auto 20px auto 20px auto;

      и потом для каждой ячейки — для первой типа
      -ms-grid-row: 1;
          -ms-grid-column: 1;

      а для второй уже
       -ms-grid-row: 1;
          -ms-grid-column: 3;

      и так далее…
      По иронии судьбы, сейчас такого жесткого требования поддержки ie уже нет, этот проект — последний из тех что был так стилизован, буквально в ближайшие пару недель мигрирует на новый движок, обновленный дизайн, но с той же сеткой в макете. И тут еще раз ирония, все на флексах )
        0
        мне не помогало, пришлось затыкать «all and (-ms-high-contrast: none), (-ms-high-contrast: active)»"
        0

        Я делал проект с IE11 и grid'ами, в итоге пришёл к варианту генерации двух вариантов вёрстки на scss (для IE11 и для остальных), работает нормально.

        0
        JUSTIFY-CONTENT И ALIGN-SELF
        Имелось ввиду, наверное, justify-content, align-items
        align-self, justify-self это правила позволяющие определять поведение дочернему элементу флекса/грида.

        На самом деле, гриды могут в некоторые вещи, которые флексами просто не сверстать, например developer.mozilla.org/ru/docs/Web/CSS/grid-auto-flow dense позволяет компактно упаковать карточки разных размеров отрендеренные в случайном порядке в существующее свободное место родительского грид-контейнера. Флексы могут так?
          +2

          Layout — это не макет. Макет (дизайн) — это макет. Layout — это раскладка. Вы снова переводите хорошие материалы плохими словами, которые либо никто не употребляет на практике, либо просто искажают смысл.

            0
            У старых iOS (на старых эппл-устройствах, на которых просто нет обновления прошивки) grid не поддерживается, получается только flexbox для таких случаев…
              0
              таки почему или? когда можно grid + flexbox…

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое