Flexbox и grid

Что это такое

Flexbox и grid — две системы раскладки в CSS. Flexbox распределяет элементы вдоль одной оси, строки или столбца, и подходит, когда размеры задаёт содержимое. Grid размещает элементы в двумерной структуре строк и столбцов; к нему прибегают, когда положение содержимого должна задавать структура.

Почему это важно

До них раскладка страницы означала обтекания, абсолютное позиционирование и хаки clearfix, а каждая раскладка была переговорами между элементами, которые друг о друге не знали. Flexbox и grid перенесли выравнивание, отступы и распределение в контейнер, где их можно описать один раз. Поэтому адаптивный ряд карточек, прижатый к низу подвал и центрированный диалог теперь три коротких правила, а не три хрупких трюка. Однако выбрать из двух — почти весь навык: неподходящая всё равно работает, но лишь после борьбы.

Ключевые идеи

Flexbox — одна ось, grid — две

Flex-контейнер раскладывает потомков вдоль одного направления: элементы могут расти, заполняя место, сжиматься при тесноте и выравниваться друг относительно друга. Grid-контейнер сначала задаёт дорожки и размещает элементы по ним. Если вы ловите себя на трёхуровневой вложенности flex-контейнеров ради двумерной раскладки, grid — ответ поспокойнее.

.toolbar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.layout {
  display: grid;
  grid-template-columns: 16rem 1fr;
  gap: 1.5rem;
}

Пространство — свойство контейнера

gap заменяет хаки с margin, которыми раньше раздвигали элементы, не добавляя места снаружи. justify-content и align-items размещают элементы по двум осям, а в grid те же имена применяются к дорожкам через justify-content и собственный justify-self элемента; именно явное называние оси — главная и поперечная в flex, строки и столбцы в grid — и делает свойства читаемыми.

Пусть решает содержимое или структура

flex: 2 и grid-template-columns: 1fr 2fr оба выражают пропорцию, но расходятся, когда содержимое велико. Flex-элементы могут отказаться сжиматься ниже своего содержимого, если не задать min-width: 0, а дорожки grid с 1fr привязаны к дорожке и могут переполниться. Именно здесь и проходит настоящее проектное решение: решить, какое поведение вам нужно.

Повторяйте и задавайте дорожки по содержимому

Grid умеет порождать дорожки по правилу: repeat(auto-fit, minmax(16rem, 1fr)) даёт столько равных столбцов, сколько помещается выше минимальной ширины, и заменяет стопку точек перелома одной строкой.

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1rem;
}

Вложенные контейнеры нормальны, глубокая вложенность — нет

Элемент grid может быть flex-контейнером, и наоборот; так и строятся настоящие раскладки. Однако глубина — уже запах: если для размещения одного элемента нужны четыре уровня, внешняя структура, вероятно, делает работу, с которой справился бы один grid.

Практика

Постройте ряд карточек, который переносится без точек перелома

Разложите восемь карточек через grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)) и gap. Медленно меняйте ширину окна.

Готово, когда: карточки переносятся на ширине, выведенной из минимума столбца, а не из написанной вами точки перелома, и ни одна карточка не становится уже 16rem.

Отцентрируйте диалог сначала flex, потом grid

Постройте модальное окно по центру полноэкранной подложки: один раз центрированием через flex, другой раз размещением через grid. Сравните число правил.

Готово, когда: обе версии центрируют диалог точно, и вы можете сказать, какую оставили бы в кодовой базе и почему.

Частые ошибки

  • Flexbox для двумерной раскладки — вложенные flex-контейнеры накапливаются, и отступы становятся угадыванием; исправить: берите grid для строк и столбцов, а flex — внутри ячейки.
  • Забытый min-width: 0 у flex-элемента — длинное слово мешает элементу сжаться, и ряд переполняется; исправить: разрешите элементу сжиматься или перенесите текст.
  • Починка выравнивания полями — смещения ломаются, как только элемент меняет размер; исправить: используйте align-items, justify-content и gap у контейнера.
  • flex: 1 на всём подряд — каждый элемент борется за одну и ту же долю, и самое мелкое содержимое проигрывает; исправить: задайте flex-значение только тем элементам, которые должны растягиваться.
  • Жёсткая сетка под самый широкий экран — узкие экраны уходят в боковую прокрутку; исправить: используйте auto-fit с minmax или дайте дорожкам схлопываться.

Что читать дальше

  • Каскад и блочная модель (02-frontend/05-css/01-cascade-and-box-model) — box-sizing, gap и размеры дорожек предполагают, что вы знаете, откуда берутся измерения элемента.
  • Медиа- и контейнерные запросы (02-frontend/05-css/03-media-and-container-queries) — как та же раскладка адаптируется при смене окна или родителя.
  • Макетирование и сеточные системы (03-design-ux/30-layout-grid-systems) — словарь со стороны дизайна для решений, которые вы здесь принимаете.