Грид + флексбокс: мощнейшее комбо в веб-раскладке
Перевод статьи 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, по возможности из одного di
v
а. Вам пригодится несколько удобных вспомогательных свойств, 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. Это тоже может быть интересно:
Все ок, поддержка браузерами не ок.
У флексбоксов уже >97%. У гридов к концу этого месяца уже будет больше половины (см. первый абзац статьи:).
Зачетно!!!
Воу воу, тематика годная, НО
Layout в контексте данного повествования — это не расладка, это МАКЕТ.
Добро пожаловать в один из старейших околоверстальных холиворов! :)
Макет — годное слово, НО в контексте работы верстальщика оно обычно значит то, что приходит от дизайнера («заверстай вот этот макет»), т.е. «mockup», а вовсе не «layout» (в любом из его значений). И опыт упрямо показывает, что вариант «раскладка» — наименьшее зло, создающее меньше всего путаницы для большинства читателей.
Но можете попробовать предложить еще более удачный вариант в словарик!
Сам работаю с иностранными дизайнерами и подтверждаю, для макета они используют «mock-up» (только через дефис).
Поделился с автором шестеренкой на одном div’е
А с нами?!