CSS Grid и Flexbox: сравнение на практике

Оригинал: http://tutorialzine.com/2017/03/css-grid-vs-flexbox/
Перевод: Влад Мержевич

Ещё недавно макет для всех страниц HTML верстался с помощью таблиц, float и других свойств CSS, которые не очень хорошо подходят для стилизации сложных веб-страниц.

Затем появился Flexbox — режим вёрстки, который был специально разработан для создания надёжных адаптивных страниц. Flexbox упростил правильное выравнивание элементов и их содержимого и теперь является предпочтительной системой CSS для большинства веб-разработчиков.

Но теперь у нас есть новый претендент на титул за звание «лучшей системы для вёрстки макетов HTML» (название титула ещё в процессе разработки»). Это CSS Grid и в ближайшее время эта система будет доступна в браузерах Firefox 52 и Chrome 57, а вскоре, как я надеюсь, и в других браузерах.

Базовый макет

Чтобы понять, каково это — создавать макеты на каждой системе, мы сделаем одну и ту же HTML-страницу дважды — один раз с помощью Flexbox, а затем на CSS Grid. Вы можете скачать оба проекта отсюда или проверить их в этой демонстрационной версии.

Уменьшенный макет веб-страницы

Дизайн довольно простой — он состоит из выровненного по центру контейнера, внутри которого у нас есть шапка, основной раздел, боковая панель и подвал. Вот главные «испытания», которые мы должны провести, сохраняя CSS и HTML по возможности чистыми:

  1. Разместить четыре основных раздела макета.
  2. Сделать страницу адаптивной (боковая панель опускается ниже основного содержимого на маленьких экранах).
  3. Выровнять содержимое шапки — навигация слева, кнопка справа.

Как вы можете видеть, ради сравнения мы оставили всё максимально простым. Начнём с первого испытания.

Испытание 1. Размещение разделов страницы

Решение на Flexbox

Добавляем display: flex к контейнеру и задаём направление дочерних элементов по вертикали. Это позиционирует все разделы друг под другом.

.container {
  display: flex;
  flex-direction: column;
}

Теперь нам нужно сделать так, чтобы основной раздел и боковая панель располагались рядом. Поскольку flex-контейнеры обычно однонаправлены, нам нужно добавить дополнительный элемент.

<header></header>
<div>
  <section></section>
  <aside></aside>
</div>
<footer></footer>

Затем мы устанавливаем этому элементу display: flex и flex-direction с противоположным направлением.

.main-and-sidebar-wrapper {
  display: flex;
  flex-direction: row;
}

Последний шаг — задать размеры основного раздела и боковой панели. Мы хотим, чтобы основное содержимое было в три раза шире боковой панели, что несложно сделать с помощью flex или процентов.

.main {
  flex: 3;
  margin-right: 60px;
}
.sidebar {
  flex: 1;
}

Как вы можете видеть, Flexbox сделал всё хорошо, но нам кроме этого понадобилось довольно много свойств CSS плюс дополнительный элемент HTML. Давайте посмотрим, как будет работать CSS Grid.

Решение на CSS Grid

Существует несколько вариантов использования CSS Grid, но мы воспользуемся синтаксисом grid-template-areas, как наиболее подходящего для наших целей.

Сперва мы определим четыре grid-area, по одному на каждый раздел страницы:

<header></header>
<!-- Обратите внимание, что в этот раз нет дополнительных элементов -->
<section></section>
<aside></aside>
<footer></footer>
header {
  grid-area: header;
}
.main {
  grid-area: main;
}
.sidebar {
  grid-area: sidebar;
}
footer {
  grid-area: footer;
}

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

.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

<header>
  <nav>
    <li><a href="#"><h2>Logo</h2></a></li>
    <li><a href="#">Link</a></li>
    <li><a href="#">Link</a></li>
  </nav>
  <button>Button</button>
</header>

Мы уже делали похожий макет на Flexbox в одной из наших старых статей — Простейший способ создания адаптивной шапки. Техника довольно простая:

header {
  display: flex;
  justify-content: space-between;
}

Теперь список навигации и кнопка выровнены правильно. Осталось только разместить пункты внутри <nav> по горизонтали. Проще это сделать с помощью display: inline-block, но поскольку мы собираемся целиком использовать Flexbox, применим решение только для него:

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. Вот как выглядит наша лучшая попытка:

Ссылки строчные, но они не могут быть выровнены правильно, поскольку не существует варианта baseline, как у align-items. Мы также должны определить ещё одну вложенную сетку.

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. Изучайте их и используйте совместно.

htmlbook.ru

HTML5 | Flexbox

Что такое Flexbox. Flex Container

Последнее обновление: 18.04.2017

Flexbox — это общее название для модуля Flexible Box Layout, который имеется в CSS3. Данный модуль определяет особый режим компоновки/верстки пользовательского
интерфейса, который называется flex layout. В этом плане Flexbox предоставляет иной подход к созданию пользовательского интерфейса,
который отличается от табличной или блочной верстки. Развернутое описание стандарта по модулю можно посмотреть в спецификации.

Благодаря Flexbox проще создавать сложные, комплексные интерфейсы, где мы с легкостью можем переопределять направление и выравнивание элементов, создавать адаптивные
табличные представления. Кроме того, Flexbox довольно прост в использовании. Единственная проблема, которая может возникнуть при его применении, — это кроссбраузерность.
Например, в Internet Explorer поддержка Flexbox и то частичная появилась только в последней версии — IE11. В то же время все современные браузеры, в том числе
Microsoft Edge, Opera, Google Chrome, Safari, Firefox, имеют полную поддержку данного модуля.

Основными составляющими компоновки flexbox являются flex-контейнер (flex container) и flex-элементы (flex items). Flex container представляет
некоторый элемент, внутри которого размещены flex-элементы.

Основные понятия

Прежде чем переходить к изучению верстки flexbox, стоит рассмотреть некоторые основные понятия.

Одно из ключевых понятий представляет main axis или центральная ось. Это условная ось во flex-контейнере,
вдоль которой позиционируются flex-элементы.

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

Термины main start и main end описывают соответственно начало и конец центральной оси, а расстояние между между ними обозначается
как main size.

Кроме основной оси существует также поперечная ось или cross axis. Она перпендикулярна основной. При расположении элементов в виде строки cross axis
направлена сверху вниз, а при расположении в виде столбца она направлена слева направо. Начало поперечной оси обозначается как cross start, а ее
конец — как cross end. Расстояние между ними описывается термином cross size.

То есть, если элементы располагаются в строку, то main size будет представлять ширину контейнера или элементов, а cross size — их высоту. Если же
элементы располагаются в столбик, то, наоборот, main size представляет высоту контейнера и элементов, а cross size — их ширину.

Создание flex-контейнера

Для создания flex-контейнера необходимо присвоить его стилевому свойству display одно из двух значений:
flex или inline-flex.

Создадим простейшую веб-страницу, которая применяет flexbox:


<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Flexbox в CSS3</title>
        <style>
			.flex-container {
				display: flex;
			}
			.flex-item {
				text-align:center;
				font-size: 1.1em;
				padding: 1.5em;
				color: white;
			}
			.color1 {background-color: #675BA7;}
			.color2 {background-color: #9BC850;}
			.color3 {background-color: #A62E5C;}
        </style>
    </head>
    <body>
        <div>
			<div>Flex Item 1</div>
			<div>Flex Item 2</div>
			<div>Flex Item 3</div>
		</div>
    </body>
</html>

Для контейнера flex-container установлено свойство display:flex. В нем располагается три flex-элемента.

Если значение flex определяет контейнер как блочный элемент, то значение inline-flex определяет элемент как строчный (inline). Рассмотрим оба способа на примере:


<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Flexbox в CSS3</title>
        <style>
			.flex-container {
				display: flex;
				border:2px solid #ccc;
			}
			.inline-flex-container {
				display: inline-flex;
				border:2px solid #ccc;
				margin-top:10px;
			}
			.flex-item {
				text-align:center;
				font-size: 1.1em;
				padding: 1.5em;
				color: white;
			}
			.color1 {background-color: #675BA7;}
			.color2 {background-color: #9BC850;}
			.color3 {background-color: #A62E5C;}
        </style>
    </head>
    <body>
        <div>
			<div>Flex Item 1</div>
			<div>Flex Item 2</div>
			<div>Flex Item 3</div>
		</div>
		
		<div>
			<div>Flex Item 1</div>
			<div>Flex Item 2</div>
			<div>Flex Item 3</div>
		</div>
    </body>
</html>

В частности, в первом случае flex-контейнер растягивается по ширине страницы, а во втором случае занимает именно столько места, сколько необходимо для flex-элементов.

metanit.com

flex-basis | CSS | WebReference

Свойство flex-basis определяет основу флекса, которая является начальным размером элемента. Похоже на свойства width и height, к которым добавляется содержимое элемента.

Краткая информация

Значение по умолчанию auto
Наследуется Нет
Применяется К флекс-элементам
Анимируется Да

Синтаксис ?

flex-basis: auto | <размер>

Обозначения

Описание Пример
<тип> Указывает тип значения. <размер>
A && B Значения должны выводиться в указанном порядке. <размер> && <цвет>
A | B Указывает, что надо выбрать только одно значение из предложенных (A или B). normal | small-caps
A || B Каждое значение может использоваться самостоятельно или совместно с другими в произвольном порядке. width || count
[ ] Группирует значения. [ crop || cross ]
* Повторять ноль или больше раз. [,<время>]*
+ Повторять один или больше раз. <число>+
? Указанный тип, слово или группа не является обязательным. inset?
{A, B} Повторять не менее A, но не более B раз. <радиус>{1,4}
# Повторять один или больше раз через запятую. <время>#

×

Значения

auto
Указывает автоматический размер, основанный на содержимом элемента.
<размер>
Задаёт размер элемента в px, mm, pt или в процентах вдоль главной оси. При этом размер вычисляется относительно родителя. Отрицательное значение недопустимо.

Пример

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>flex-basis</title>
  <style>
   .flex-container {
    display: flex; /* Флексы */
    height: 300px; /* Высота */
    color: #fff; /* Белый цвет текста */
    font-size: 2.6em; /* Размер шрифта */
    flex-flow: column wrap; /* Располагаем в виде колонок */
   }
   .flex-item {
    display: flex; /* Флексы */
    align-items: center; /* Выравнивание текста по вертикали */
    justify-content: center; /* Выравнивание текста по горизонтали */
   }
   .one {
    background: #508694; /* Цвет фона */
    margin-right: 10px; /* Отступ справа */
    flex-basis: 100%;
    order: 1; /* Первый блок */
   }
   .two {
    background: #BB844C; /* Цвет фона */
    margin-bottom: 10px; /* Отступ снизу */
    flex: 1 1 0;
    order: 2; /* Второй блок */
   }
   .three {
    background: #929D79; /* Цвет фона */
    flex: 1 1 0;
    order: 3; /* Третий блок */
   }
  </style>
 </head>
 <body>
  <div>
   <div>Первый</div>
   <div>Второй</div>
   <div>Третий</div>
  </div>
 </body>
</html>

Примечание

Safari до версии 9 поддерживает свойство -webkit-flex-basis.

Спецификация ?

Спецификация

Каждая спецификация проходит несколько стадий одобрения.

  • Recommendation (Рекомендация) — спецификация одобрена W3C и рекомендована как стандарт.
  • Candidate Recommendation (Возможная рекомендация) — группа, отвечающая за стандарт, удовлетворена, как он соответствует своим целям, но требуется помощь сообщества разработчиков по реализации стандарта.
  • Proposed Recommendation (Предлагаемая рекомендация) — на этом этапе документ представлен на рассмотрение Консультативного совета W3C для окончательного утверждения.
  • Working Draft (Рабочий проект) — более зрелая версия черновика после обсуждения и внесения поправок для рассмотрения сообществом.
  • Editor’s draft (Редакторский черновик) — черновая версия стандарта после внесения правок редакторами проекта.
  • Draft (Черновик спецификации) — первая черновая версия стандарта.

×

Браузеры

В таблице браузеров применяются следующие обозначения.

  •  — свойство полностью поддерживается браузером со всеми допустимыми значениями;
  •  — свойство браузером не воспринимается и игнорируется;
  •  — при работе возможно появление различных ошибок, либо свойство поддерживается лишь частично, например, не все допустимые значения действуют или свойство применяется не ко всем элементам, которые указаны в спецификации.

Число указывает версию браузера, начиная с которой свойство поддерживается.

×

Автор и редакторы

Автор: Влад Мержевич

Последнее изменение: 15.05.2018

Редакторы: Влад Мержевич

webref.ru