Недавно на уроках дошкольной подготовки моему сыну поручили в течение недели присматривать за плюшевым мишкой, что предполагало необходимость взять мишку в какое-то приключение, а свои воспоминания об этом добавить в альбом. Мне очень понравилось делать этот альбом и подтолкнуло к мысли о том, как бы я сделал нечто подобное с помощью CSS Grid!
Andy Clarke выступил с фантастическим докладом «Вдохновлённый технологией CSS Grid» на конференции State of the Browser, которая была настоящим озарением для таких как я, разработчиков с дизайнерскими корнями. В докладе он рассказывал о способах, с помощью которых идеи из дизайна печатных изданий могут быть применены в вебе для создания поразительных макетов, и как CSS Grid делает это не только возможным, но и гораздо более простым, чем когда-либо раньше. Одним из этих принципов было использование составных сеток.
Большинство из нас, вероятно, знакомы с использованием гридов для веб-дизайна и разработки. Практически все макеты сайтов, которые мне поручали разрабатывать, делились на стандартную 12-колоночную (или изредка 24-колоночную) сетку с колонками равной ширины. Пока что всё достаточно предсказуемо.
С другой стороны, составные сетки создаются путём наложения друг на друга двух или более сеток. Сопоставления, например, 5-колоночной сетки, наложенной на 4-колоночную сетку, создают ритмический рисунок и открывают возможности для построения более динамичного макета, чем обычная сетка.
Рис 2 — Мы начинаем с 4-колоночной и 5-колоночной сетки
Рис 3 — Сетки накладываются одна на другую. В результате получаем составную сетку
Это применимо как с психологической, так и с технической точки зрения — мы можем создать самый обычный макет, несмотря на использование составной сетки. Энди написал детальную статью «Inspired Design Decisions: Pressing Matters», в которой более подробно рассказывается о составных сетках. Также доступно его выступление с конференции «State of the Browser».
Единицы измерения fr позволяют очень легко реализовывать составные сетки в CSS Grid. Мне нравится идея использования составных сеток в веб-дизайне, но я чувствовал, что процесс их вычисления (особенно более сложной сетки) может быть достаточно трудоёмким. Я хотел иметь возможность быстро и удобно создавать составные сетки, поэтому, вдохновлённый докладом Энди, я засучил рукава и создал небольшой инструмент для их создания и визуализации. Введите количество колонок для двух сеток (максимально с 10 колонками для каждой) и генератор объединит их, выдав итоговое значение, которое можно задать свойству
Этот инструмент представлен на Codepen, поэтому не стесняйтесь использовать его или адаптировать под свои потребности.
Составная сетка идеально подходит для макета альбома, который я хотел бы сделать немного непредсказуемым, но сохраняющим чувства ритма и баланса. После небольшого количества экспериментов с генератором, я остановился на составной сетке 6/5, которая, как мне показалось, давала нужное количество колонок для дальнейших манипуляций. Это даёт мне исходную сетку для работы:
Определить строки сетки было сложнее и требовало немного больше проб и ошибок. Каждая фотография в сетке должна перекрывать другую. Оказалось полезным приблизительно нарисовать сетку на бумаге, чтобы понять, сколько строк потребуется.
Чтобы сохранить чувство вертикального ритма, я решил, что фотографии должны определённым образом перекрывать друг друга. Я присвоил этот размер наложения переменной, чтобы её можно было использовать по всей странице и обновлять, если потребуется (Рис. 4).
Рис 4 — Вертикальное наложение изображений
Каждое изображение также имеет сопроводительный текст. Для этого должно быть достаточно пространства сверху и снизу, чтобы он не накладывался на предыдущую фотографию. Это предусматривает добавление строк сетки выше и ниже подписи, которые будут выступать в роли "'padding". Теперь каждое изображение должно охватывать как минимум четыре строки сетки — а изображение, которое перекрывается вверху и внизу, должно занимать пять строк.
Рис 5 — строки, выполняющие роль «padding», позволяют поддерживать минимальный интервал между концом текстового блока и началом следующего изображения.
Но мы еще не закончили с проектированием сетки: я решил задать фиксированное соотношение сторон для изображений. Некоторые фотографии будут портретными, а другие — пейзажными. Я бы хотел, чтобы макет сетки работал независимо от соотношения сторон фотографий или длины текста, поэтому требовалось, чтобы строки сетки были способны адаптироваться.
Вместо использования фиксированных значений для строк, выполняющих роль наложения или «padding», мы можем сделать эти треки гибкими с помощью функции minmax(). Это обеспечит ситуацию, в которой строчные треки будут иметь минимальный размер, но будут расширяться, если это потребуется для содержимого.
Теперь, когда у нас есть скелет сетки, самое время заняться размещением элементов. Понимание и выбор лучшего способа их размещения в сетке любой структуры порой может быть сложным. У нас есть ряд различных вариантов: номера линий, ключевое слово «span», именованные линии или области — и некоторые из них работают лучше других в определенных ситуациях. Но не существует правильного или неправильного варианта и часто всё сводится к тому, чтобы найти метод, наиболее подходящий именно вам.
Пока всё работает как нужно, нет неправильных подходов
Я часто начинаю с размещения элементов, используя начальные и конечные значения — обычно номеров первой и последней линии, но если я знаю точное количество дорожек, которые должен охватить элемент, вместо этого я буду использовать ключевое слово «span». Иногда я именую линии сетки для добавления важных ориентиров (например,
Элемент, расположенный через свойство
Я больше склоняюсь к именованию грид-линий в ситуациях с сетками, имеющими очень большое количество треков. В рассматриваемом случае у нас есть только 10 колоночных треков, поэтому мне размещение элементов по номеру линии кажется более удобным для дальнейшего манипулирования.
Используя смесь положительных/отрицательных grid-линий и значений «span», достаточно просто разместить элементы по оси колонок. Включение grid-инспектора в панели разработчика Firefox очень помогает в этом, так как позволяет нам увидеть номера линий.
Если мы посмотрим на сетку. сможем увидеть, что у нас есть достаточно большое количество строк.
Рис 7 — скриншот из Firefox grid-inspector в панели разработчика, показывающий грид-колонки и строки
Хотя я начал размещать элементы по номеру линии на оси строк, этим быстро становится трудно управлять. Элементы должны перекрывать друг друга, и мне кажется трудным отслеживать трек, на котором один элемент должен закончиться, а другой начаться. К тому же, я не хочу использовать отрицательные grid-линии, потому что есть вероятность, что я захочу дополнить свой макет в будущем. Если я в конечном счете добавлю больше явных строк в грид, тогда отрицательные номера линий больше не будут правильными, потенциально вызывая много ошибок макета.
Это было, когда я решил создать именованные grid-области на оси строк. Grid-области создаются двумя способами:
Свойство
Если мы именуем линии и для оси строк и для оси колонок, мы получаем grid-область (рис 8)
Рис 8 — суффиксы имён строк со
Затем можно ссылаться на эту область, когда размещаем элемент с помощью свойства
Это делает наш код более кратким и удобочитаемым, чем использование свойств grid-column и grid-row, и перечисление имен строк:
Но в этом случае нам нужна только именованная grid-область на оси строк. Это нормально, так как мы можем просто сослаться на неё с помощью свойства grid-row:
Так как у нас имеется большое количество строк, мне показалось, что гораздо проще записать свойство
Теперь добавление имён линий в правильное место становится более простым, так как мы можем визуализировать структуру сетки:
Всё, что осталось — сослаться на имена областей на оси строк, когда размещаются наши grid-элементы:
Итоговый результат (рис. 10) доступен для ознакомления на Codepen
Рис 10
Хотя я не приложил дополнительных усилий, чтобы сделать этот макет адаптивным, его можно использовать на экранах даже меньшего размера, чем у планшетов. Адаптировать макет для маленьких экранов не вызвало бы больших трудностей. Лично я бы для таких ситуаций выбрал более простую сетку, так как многие визуальные особенности всё равно будут потеряны. Но опять же, в этом нет ничего правильного или неправильного.
Составные сетки
Andy Clarke выступил с фантастическим докладом «Вдохновлённый технологией CSS Grid» на конференции State of the Browser, которая была настоящим озарением для таких как я, разработчиков с дизайнерскими корнями. В докладе он рассказывал о способах, с помощью которых идеи из дизайна печатных изданий могут быть применены в вебе для создания поразительных макетов, и как CSS Grid делает это не только возможным, но и гораздо более простым, чем когда-либо раньше. Одним из этих принципов было использование составных сеток.
Большинство из нас, вероятно, знакомы с использованием гридов для веб-дизайна и разработки. Практически все макеты сайтов, которые мне поручали разрабатывать, делились на стандартную 12-колоночную (или изредка 24-колоночную) сетку с колонками равной ширины. Пока что всё достаточно предсказуемо.
С другой стороны, составные сетки создаются путём наложения друг на друга двух или более сеток. Сопоставления, например, 5-колоночной сетки, наложенной на 4-колоночную сетку, создают ритмический рисунок и открывают возможности для построения более динамичного макета, чем обычная сетка.
Рис 2 — Мы начинаем с 4-колоночной и 5-колоночной сетки
Рис 3 — Сетки накладываются одна на другую. В результате получаем составную сетку
Это применимо как с психологической, так и с технической точки зрения — мы можем создать самый обычный макет, несмотря на использование составной сетки. Энди написал детальную статью «Inspired Design Decisions: Pressing Matters», в которой более подробно рассказывается о составных сетках. Также доступно его выступление с конференции «State of the Browser».
Генератор составной сетки
Единицы измерения fr позволяют очень легко реализовывать составные сетки в CSS Grid. Мне нравится идея использования составных сеток в веб-дизайне, но я чувствовал, что процесс их вычисления (особенно более сложной сетки) может быть достаточно трудоёмким. Я хотел иметь возможность быстро и удобно создавать составные сетки, поэтому, вдохновлённый докладом Энди, я засучил рукава и создал небольшой инструмент для их создания и визуализации. Введите количество колонок для двух сеток (максимально с 10 колонками для каждой) и генератор объединит их, выдав итоговое значение, которое можно задать свойству
grid-template-columns
. Например, сетка с четырьмя колонками плюс сетка с пятью колонками выдаст значение 4fr 1fr 3fr 2fr 2fr 3fr 1fr 4fr
.Этот инструмент представлен на Codepen, поэтому не стесняйтесь использовать его или адаптировать под свои потребности.
Создание сетки для макета альбома
Составная сетка идеально подходит для макета альбома, который я хотел бы сделать немного непредсказуемым, но сохраняющим чувства ритма и баланса. После небольшого количества экспериментов с генератором, я остановился на составной сетке 6/5, которая, как мне показалось, давала нужное количество колонок для дальнейших манипуляций. Это даёт мне исходную сетку для работы:
.grid {
display: grid;
grid-template-columns: 5fr 1fr 4fr 2fr 3fr 3fr 2fr 4fr 1fr 5fr;
gap: 1rem;
}
Определение строк сетки
Определить строки сетки было сложнее и требовало немного больше проб и ошибок. Каждая фотография в сетке должна перекрывать другую. Оказалось полезным приблизительно нарисовать сетку на бумаге, чтобы понять, сколько строк потребуется.
Чтобы сохранить чувство вертикального ритма, я решил, что фотографии должны определённым образом перекрывать друг друга. Я присвоил этот размер наложения переменной, чтобы её можно было использовать по всей странице и обновлять, если потребуется (Рис. 4).
Рис 4 — Вертикальное наложение изображений
.grid {
--verticalPadding: 2rem;
--overlap: 6rem;
}
Каждое изображение также имеет сопроводительный текст. Для этого должно быть достаточно пространства сверху и снизу, чтобы он не накладывался на предыдущую фотографию. Это предусматривает добавление строк сетки выше и ниже подписи, которые будут выступать в роли "'padding". Теперь каждое изображение должно охватывать как минимум четыре строки сетки — а изображение, которое перекрывается вверху и внизу, должно занимать пять строк.
Рис 5 — строки, выполняющие роль «padding», позволяют поддерживать минимальный интервал между концом текстового блока и началом следующего изображения.
Но мы еще не закончили с проектированием сетки: я решил задать фиксированное соотношение сторон для изображений. Некоторые фотографии будут портретными, а другие — пейзажными. Я бы хотел, чтобы макет сетки работал независимо от соотношения сторон фотографий или длины текста, поэтому требовалось, чтобы строки сетки были способны адаптироваться.
Вместо использования фиксированных значений для строк, выполняющих роль наложения или «padding», мы можем сделать эти треки гибкими с помощью функции minmax(). Это обеспечит ситуацию, в которой строчные треки будут иметь минимальный размер, но будут расширяться, если это потребуется для содержимого.
minmax(var(--padding, auto));
Размещение элементов
Теперь, когда у нас есть скелет сетки, самое время заняться размещением элементов. Понимание и выбор лучшего способа их размещения в сетке любой структуры порой может быть сложным. У нас есть ряд различных вариантов: номера линий, ключевое слово «span», именованные линии или области — и некоторые из них работают лучше других в определенных ситуациях. Но не существует правильного или неправильного варианта и часто всё сводится к тому, чтобы найти метод, наиболее подходящий именно вам.
Пока всё работает как нужно, нет неправильных подходов
Размещение с помощью линий сетки
Я часто начинаю с размещения элементов, используя начальные и конечные значения — обычно номеров первой и последней линии, но если я знаю точное количество дорожек, которые должен охватить элемент, вместо этого я буду использовать ключевое слово «span». Иногда я именую линии сетки для добавления важных ориентиров (например,
wrapper-start
и wrapper-end
), но редко захожу настолько далеко, чтобы именовать линии сетки или создавать grid-области прямо для каждого элемента в гриде. Стратегия, которая мне очень помогает, заключается в указании отрицательных grid-линий в ситуациях, когда я хочу разместить элемент до конца сетки. Я писал об этом в отдельной статье. Я использую отрицательные grid-линии наиболее часто в колоночной оси, так как в большинстве случаев (для гридов, с которыми я работаю) количество столбцов известно и фиксировано.Элемент, расположенный через свойство
grid-column
со значением 1 / -1, охватит все колонки сетки, от первой до последней:.item {
grid-column: 1 / -1;
}
Я больше склоняюсь к именованию грид-линий в ситуациях с сетками, имеющими очень большое количество треков. В рассматриваемом случае у нас есть только 10 колоночных треков, поэтому мне размещение элементов по номеру линии кажется более удобным для дальнейшего манипулирования.
Используя смесь положительных/отрицательных grid-линий и значений «span», достаточно просто разместить элементы по оси колонок. Включение grid-инспектора в панели разработчика Firefox очень помогает в этом, так как позволяет нам увидеть номера линий.
Размещение с помощью grid-областей
Если мы посмотрим на сетку. сможем увидеть, что у нас есть достаточно большое количество строк.
Рис 7 — скриншот из Firefox grid-inspector в панели разработчика, показывающий грид-колонки и строки
Хотя я начал размещать элементы по номеру линии на оси строк, этим быстро становится трудно управлять. Элементы должны перекрывать друг друга, и мне кажется трудным отслеживать трек, на котором один элемент должен закончиться, а другой начаться. К тому же, я не хочу использовать отрицательные grid-линии, потому что есть вероятность, что я захочу дополнить свой макет в будущем. Если я в конечном счете добавлю больше явных строк в грид, тогда отрицательные номера линий больше не будут правильными, потенциально вызывая много ошибок макета.
Это было, когда я решил создать именованные grid-области на оси строк. Grid-области создаются двумя способами:
- С помощью свойства
grid-template-areas
, которое позволяет вам эффективно «рисовать» grid-макет как ascii-рисунок - Используя именованные grid-линии, используя
-start
и-end
как суффиксы к именам линий
Свойство
grid-template-areas
не позволяет определять области для перекрывающихся элементов, поэтому оно не особо помогает нам с этим конкретным макетом. Тем не менее, использование именованных grid-областей определенно облегчает задачу.Если мы именуем линии и для оси строк и для оси колонок, мы получаем grid-область (рис 8)
Рис 8 — суффиксы имён строк со
-start
и -end
создают grid-областьЗатем можно ссылаться на эту область, когда размещаем элемент с помощью свойства
grid-area
:.item {
grid-area: image;
}
Это делает наш код более кратким и удобочитаемым, чем использование свойств grid-column и grid-row, и перечисление имен строк:
.item {
grid-row: image-start / image-end;
grid-column: image-start / image-end;
}
Но в этом случае нам нужна только именованная grid-область на оси строк. Это нормально, так как мы можем просто сослаться на неё с помощью свойства grid-row:
.item {
grid-row: image;
}
Так как у нас имеется большое количество строк, мне показалось, что гораздо проще записать свойство
grid-template-rows
по вертикали, чтобы оно отражало структуру страницы:grid-template-rows:
/* Первые две строки являются заголовком */
auto
3rem
/* Остальное содержимое сетки начинается здесь */
minmax(var(--verticalPadding), auto)
minmax(0, auto)
minmax(var(--verticalPadding), auto)
var(--overlap)
minmax(var(--verticalPadding), auto)
minmax(0, auto)
minmax(var(--verticalPadding), auto)
var(--overlap)
minmax(var(--verticalPadding), auto)
minmax(0, auto)
minmax(var(--verticalPadding), auto);
Теперь добавление имён линий в правильное место становится более простым, так как мы можем визуализировать структуру сетки:
grid-template-rows:
[header-start]
auto
[fig1-start]
3rem
[header-end]
minmax(var(--verticalPadding), auto)
[p1-start]
minmax(0, auto)
[p1-end]
minmax(var(--verticalPadding), auto)
[fig2-start]
var(--overlap)
[fig1-end]
minmax(var(--verticalPadding), auto)
[p2-start]
minmax(0, auto)
[p2-end]
minmax(var(--verticalPadding), auto)
[fig3-start]
var(--overlap)
[fig2-end]
minmax(var(--verticalPadding), auto)
[p3-start]
minmax(0, auto)
[p3-end]
minmax(var(--verticalPadding), auto)
[fig3-end];
Всё, что осталось — сослаться на имена областей на оси строк, когда размещаются наши grid-элементы:
.fig--1 {
grid-column: span 5 / -1;
grid-row: fig1;
}
.fig--2 {
grid-column: 1 / span 7;
grid-row: fig2;
}
.fig--3 {
grid-column: span 5 / -2;
grid-row: fig3;
}
Итоговый результат (рис. 10) доступен для ознакомления на Codepen
Рис 10
Хотя я не приложил дополнительных усилий, чтобы сделать этот макет адаптивным, его можно использовать на экранах даже меньшего размера, чем у планшетов. Адаптировать макет для маленьких экранов не вызвало бы больших трудностей. Лично я бы для таких ситуаций выбрал более простую сетку, так как многие визуальные особенности всё равно будут потеряны. Но опять же, в этом нет ничего правильного или неправильного.