Грид + флексбокс: мощнейшее комбо в веб-раскладке

Перевод статьи Grid + Flexbox: the best 1-2 punch in web layout с сайта www.chenhuijing.com, опубликован на CSS-live.ru с разрешения автора — Чэнь Хуэй Цзин

Через 5 дней выходит стабильный релиз Firefox 52. Знаете, что это значит? Это значит, что через 5 дней начнут поддерживаться CSS-гриды. А совсем скоро, 14 марта, подтянется Chrome 57, за ним Safari 10.1 и, надеемся, до конца 2017-го присоединится и Edge.

Я вся в предвкушении.

Представляете, насколько я в предвкушении? Может, немного эмодзи поможет передать мои чувства (конфетти, человек показывает жест «ОК», хлопушка, человек танцует).

Как я вникала в CSS-гриды

Помните, как Рэйчел Эндрю отвечала на вопрос, когда использовать флексбоксы, а когда — гриды? Нет? Тогда посмотрите видео по предыдущей ссылке.

Флексбоксы — для одномерной раскладки. Гриды — для двумерной.

Рэйчел Эндрю

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

Возможно, кто-то из вас заметил, что я начала писать для CSS-справочника на Codrops. Это одно из лучших событий в моей жизни за 2016-й, кроме шуток. Может быть, я напишу об этом. Может, и нет. Посмотрим. Одним из недостающих пунктов в списке были CSS-гриды. До того, как я взялась заполнять этот раздел, я лишь немного экспериментировала с гридами и сделала прототип сайта о пенангско-миньском наречии (диалект китайского — прим. перев.) на гридах, чтобы посмотреть, лучше ли они справятся с вертикальным текстом, чем флексбоксы.

Затем я села и написала этот раздел справочника.

Три недели спустя у меня было чувство, будто я вобрала в себя самого прокачанного Металлического кактуара (это отсылка к Final Fantasy Brave Exvius, ничего не могу поделать, Final Fantasy — важная часть моей жизни), другими словами, я порядком повысила свой уровень. Я много времени проводила с самой спецификацией, всеми ее 86 страницами (согласно моим настройкам печати).

Еще были статьи о CSS-гридах (многие из них есть у нас в переводе — прим. перев.) Мануэля Рего Касановаса, с поистине глубоким разбором особенностей гридов, вроде позиционированных элементов, размещения элементов в гриде и автоматического размещения. И меня просто спасла шпаргалка по выравниванию блоков Рэйчел Эндрю, потому что в другом ресурсе, которым я пользовалась, оси были подписаны неправильно, что крайне запутало меня на несколько дней кряду.

Вот мой совет. Изучая новое CSS-свойство, держите под рукой пустой HTML-шаблон, чтобы можно было испытать его в чистом и безопасном окружении. Особенно полезно это было для такой новинки, как гриды. Знаю, есть же Codepen и всё такое, но мне нравится экспериментировать на чистом листе, чтобы ничто не отвлекало.

Примеры

Когда я разбиралась со свойствами, я начала с создания простейшего грида, просто чтобы посмотреть, как действует каждое свойство. Если вы видели синтаксис для grid-template-rows в спецификации, вы поймете, что это было не такой уж тривиальной задачей. Сами по себе гриды не очень сложны в изучении. Но, поскольку созданы они с прицелом на гибкость и мощь, вам придется затратить чуть больше времени, чтобы узнать их как следует.

Из нескольких таких элементарных гридов выросли полноценные демо-примеры. На некоторые примеры меня вдохновили беседы с участниками клуба CSS-раскладки. Я также слежу за идеями из истории графического дизайна на сайте Coursera, так что немало вдохновения черпаю и оттуда (прошлая неделя была неделей Баухауса ❤️).

Я наткнулась на эту страницу из работы «Malerei, Fotografie, Film» («Живопись, фотография, кино») Ласло Мохоли-Надя, которая выстроена в виде сетки, и первой моей мыслью было, что это можно сделать на CSS… наверное. Что ж, есть лишь один способ узнать это.

Страница 126 из «Malerei, Fotografie, Film»

Баухаус у меня в браузере

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

.grid {
  display: grid;
  grid-template-columns: 30% 9% 9% 9% 9% 9%;
  justify-content: center; /* чтобы выровнять грид по середине контейнера */
}

После этого шла целая куча кода со свойствами grid-row и grid-column для размещения элементов. Но если снова взглянуть на исходную картинку, видно, что содержимое каждой ячейки выравнивается по-своему. Скажем, содержимое первой ячейки прижато к правому краю, слово во второй ячейке — к левому нижнему углу, и т.д.

Сперва я на автомате, поскольку к этому времени уже разобралась с выравниванием блока целиком, попыталась подогнать положение содержимого в каждой ячейке грида с помощью justify-self и align-self (где нужно). Неплохая попытка, близко, да не совсем. Проблема такого решения в том, что эти два свойства влияют на то, сколько места занимает ячейка.

В дизайне из Баухауса много выразительных черных рамок вокруг каждой ячейки. Свойство border применяется к грид-элементу. Все свойства выравнивания в гриде, кроме stretch, заставляют грид-элемент ужиматься до размеров содержимого. Все границы, заданные для грид-элементов, оказываются обведены вокруг их содержимого, отчего весь дизайн превращается в кашу, так что это мне не подошло.

 

Это не те границы, которые вы ищете
Рисунок грид-элементов с размером по содержимому

Флексбоксы спешат на помощь

По умолчанию все грид-элементы ведут себя так, будто им задано выравнивание stretch по обеим осям. Я не стала это трогать, чтобы грид выглядел действительно как сетка. Вместо этого я применила к грид-элементам display: flex, что позволило мне использовать для размещения содержимого грид-элементов свойства флекс-выравнивания, задаваемые для флекс-контейнера (крутой смайлик).

Вот так-то лучше
Рисунок грид-элементов с размером по содержимому

.grid__item:nth-child(5) {
  grid-row: 3 / 5;
  border-right: 1em solid;
  padding: 1em;
  
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
}

Примерно так выглядит код, но главная моя мысль — это замечательный прием для построения раскладок. Грид для общей схемы всего и флексбокс для точной настройки отдельных частностей. Вот ссылка на Codepen, если кому-нибудь вдруг интересен итоговый результат.

See the Pen Malerei, Fotografie, Film (pg. 126) by Chen Hui Jing (@huijing) on CodePen.

Довесок: CSS-фигуры

За исключением 2 фотографий на странице, всё остальное сделано на CSS, т.е. стрелка и шестеренка — на самом деле divы со стилями. Мне нравится делать фигуры на CSS, по возможности из одного divа. Вам пригодится несколько удобных вспомогательных свойств, box-shadow, border, а также псевдоэлементы.

Стрелка

Со стрелкой всё достаточно просто. Нужен лишь 1 дополнительный псевдоэлемент для кончика стрелки. Делаем из div основу стрелки и задаем ему position: relative, так что кончик стрелки можно абсолютно позиционировать относительно основы. Кончик стрелки — это треугольник, который можно сделать с помощью фокуса с border-ом.

.arrow {
  width: 0.5em;
  height: 65%;
  background-color: #000;
  position: relative;
  
  &::after {
    display: block;
    content: '';
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: -1em;
    border-style: solid;
    border-width: 1em 1em 0 1em;
    border-color: #000 transparent transparent transparent;
  }
}

Шестеренка

Это было посложнее. Основа шестеренки — круг, т.е. border-radius: 50%, но для зубцов нужно кое-что похитрее. В этот раз я не смогла сделать их одним divом (если вдруг кто-нибудь сможет, пожалуйста, поделитесь со мной этим секретом). Для зубцов шестеренки мне понадобился добавочный вложенный вспомогательный div. К счастью, все зубцы у шестеренки одной формы, так что можно применить трюк с box-shadow.

.gear {
  height: 5em;
  width: 5em;
  background-color: #000;
  border-radius: 50%;
  position: relative;

  &::before,
  &::after {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: block;
    content: '';
  }
  
  &::before {
    height: 3em;
    width: 1em;
    box-shadow: 0em -3em 0em 0em #000, 0em 3em 0 0em #000;
  }
  
  &::after {
    height: 1em;
    width: 3em;
    box-shadow: 3em 0 0em 0em #000, -3em 0 0 0em #000;
  }
}

Основа шестеренки и 4 зубца, направленные «по сторонам света», сделаны одним divом и двумя его псевдоэлементами. Для оставшихся четырех зубцов я воспользовалась внутренним divом с псевдоэлементами, затем повернула тени (box-shadow). Мне еще нужно разобраться с нюансом с transform-origin, а то мне кажется, что сейчас оно выглядит слегка асимметрично.

.inner-gear {
  height: 2em;
  width: 2em;
  border-radius: 50%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: #e1e1d5;
  
  &::before,
  &::after {
    position: absolute;
    display: block;
    content: '';
  }
  
  &::before {
    height: 3em;
    width: 1em;
    box-shadow: 0em -3em 0em 0em #000, 0em 3em 0 0em #000;
    transform: rotate(45deg);
    transform-origin: (75% 75%);
  }
  
  &::after {
    height: 1em;
    width: 3em;
    box-shadow: 3em 0 0em 0em #000, -3em 0 0 0em #000;
    transform: rotate(45deg);
    transform-origin: (25% 75%);
  }
}

Под занавес

Я в восторге от гридов, и, очевидно, не я одна так считаю. Джен Симмонс собрала список поистине замечательных ресурсов по гридам, так что посмотрите «Уроки по CSS-гридам» и попробуйте сделать что-нибудь на гридах. Не пожалеете (широко улыбающийся смайлик).

P.S. Это тоже может быть интересно:

8

Комментарии

  1. Антон

    Все ок, поддержка браузерами не ок.

    1. SelenIT

      SelenIT (Автор записи)

      У флексбоксов уже >97%. У гридов к концу этого месяца уже будет больше половины (см. первый абзац статьи:).

  2. Илья

    Зачетно!!!

  3. Алексей

    Воу воу, тематика годная, НО
    Layout в контексте данного повествования — это не расладка, это МАКЕТ.

    1. SelenIT

      SelenIT (Автор записи)

      Добро пожаловать в один из старейших околоверстальных холиворов! :)

      Макет — годное слово, НО в контексте работы верстальщика оно обычно значит то, что приходит от дизайнера («заверстай вот этот макет»), т.е. «mockup», а вовсе не «layout» (в любом из его значений). И опыт упрямо показывает, что вариант «раскладка» — наименьшее зло, создающее меньше всего путаницы для большинства читателей.

      Но можете попробовать предложить еще более удачный вариант в словарик!

      1. Serator

        Сам работаю с иностранными дизайнерами и подтверждаю, для макета они используют «mock-up» (только через дефис).

  4. shurupkirov

    Поделился с автором шестеренкой на одном div’е

    1. Андрей

      А с нами?!

Добавить комментарий для shurupkirov Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Ваш E-mail не будет опубликован

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