Golden canon grid: страшилка для фронтендеров
Большая часть людей, так или иначе причастных к верстке сайтов, проходят через… Назовем это «путь бутстрапа». Это такая философская позиция, когда у тебя есть 12 колонок и ничего больше. Ты берешь элементы, кладешь их в определенные колонки и все у тебя хорошо. Можно выключить мозг, погрузиться в нирвану и руки будут сами расставлять элементы. Красота… Но тут появляется современный дизайнер, который рисует что-то, что ну совсем не сходится с этой замечательной концепцией. Колонок явно больше, они все разной ширины, да еще и по высоте что-то нужно выравнивать. Жуть. А встречается такое все чаще, особенно если сделать шаг в сторону от магазинов или админок. Сегодня мы поговорим о том, что же это за чудо такое там используется и как его можно готовить в современном CSS. Кода будет совсем немного, в основном — размышления и картинки.
У традиционных художников есть очень классная штука — своеобразная сетка из диагоналей и добавленных к ним перпендикулярных линий, которая не только помогает строить стандартные композиции, но и позволяет вручную переносить изображение между холстами с разными пропорциями, сохраняя при этом эти самые композиции. Я не знаю, кто и когда ее придумал, но изобретение явно не новое. Если вы будете листать глянцевые журналы достаточно продолжительное время, то заметите, что и там есть определенные закономерности, которые не зависят от размеров элементов, и сохраняются при разных пропорциях страниц или блоков, выделенных под контент. Там это вроде как связывают с термином «типографические модульные сетки». Вообще в книгопечатании издревле было модно заморачиваться по поводу пропорций, композиций и соотношений. Многие известные в свое время типографы и архитекторы придумывали свои каноны, как лучше/проще/красивее делить прямоугольник без линейки с делениями. Некоторые из них были привязаны к пропорциям бумаги, ну, а некоторые позволяли работать с любыми прямоугольниками. И вот, этот подход с отталкиванием от композиции вне зависимости от пропорций носителя информации медленно, но верно, приехал к нам, в веб, потеснив отталкивание от колонок, по крайней мере в контексте рекламных и «вау»-сайтов. Собственно речь идет о сетке, широко известной в узких кругах, которую в последние пару лет часто называют «golden canon grid», а до этого как я понимаю просто использовали без конкретного названия.
Golden canon grid
Обычно, когда звучат слова «золотой», «канон» и «дизайн», люди вспоминают разные замороченные геометрические построения, что-то в этом духе:
Эта простая схема показывает, какие в целом действия нужно производить, чтобы построить ту загадочную сетку, о которой пойдет речь в этой статье. Художники и фотографы обычно останавливаются на шаге №2, дизайнеры идут немного дальше, а нам же понадобится результат самого последнего шага, где все диагонали уже стерты, а остались только вертикальные и горизонтальные линии, поскольку в браузере у нас все состоит из прямоугольников и мыслим мы в прямоугольниках и вообще у нас мир прямоугольный:
Видно, что сетка состоит из разного размера ячеек. Они все разные! И их очень много! А-а-а-а-а-а!!!
Любой верстальщик-перфекционист сейчас должен убежать:
На самом деле, если взять бумажку и порисовать, то все станет понятнее. Если поделить лист бумаги на 4 равные части, а потом провести все возможные диагонали, то образуются точки пересечения диагоналей между собой и с горизонтальными или вертикальными линиями. Если через эти точки провести еще горизонтальных или вертикальных линий, а потом построить еще диагоналей, то получим еще точки пересечения и.т.д. Так можно бесконечно продолжать.
Если вы еще помните школьную геометрию, то скорее всего уже догадались, что тут хитро спрятана задача о делении отрезка на равные части с помощью циркуля и линейки. И оно так и есть. В конечном счете мы получаем линии, которые отсекают от листа ½, ⅓, ¼, 1/6, 1/8 и.т.д. На самом деле в современном мире даже строить ничего не нужно — компьютер может сам все поделить, но все же ради кругозора полезно знать, как это строится дедушкиным способом.
Я не знаю, есть ли какие-то названия у элементов этой сетки в художественном мире, но мы будем использовать термины «строки», «столбцы» и «блоки» или «ячейки», поскольку они ближе всего к миру CSS. Самое большое количество строк и столбцов в такой сетке, которой мне встречалось — 20, как и на картинке выше. Иногда бывает меньше, когда было сделано меньшее количество шагов при построении сетки. Думаю, что больше 20 делать смысла нет, т.к. разница в размерах шрифтов на разных экранах почти нивелирует разницу между более мелкими блоками при большем количестве строк и столбцов.
Если взять такую 20-строковую и 20-колоночную сетку и немного ее покрасить, то станет видно, что там и правда линии разделяют все на равные части. Вся сложность восприятия заключается в том, что четные и нечетные дроби тут смешиваются в одной схеме.
При разработке стандартных магазинов, лендингов и.т.д. такая сетка не нужна. Она только усложнит все на ровном месте, а пользователь разницы все равно не заметит. Но я считаю, что каждому фронтендеру стоит хоть раз поверстать какой-нибудь дизайн, построенный на ней, в спокойной обстановке, чтобы немного прочистить себе мозги и не впасть в панику, если все же придется с чем-то таким столкнуться в будущем.
Много пространства, мало контента
Особенно хорошо такая сетка заходит на сайтах, где контента не очень много, он не меняется, а акцент делается на его представлении и оказании впечатления на посетителя. Глядя на такие сайты я не могу выбросить из головы те самые модные журналы и мне кажется уместным называть такую верстку «журнальной версткой». Просмотр таких сайтов действительно похож на листание журналов, особенно при постраничном скролле. При этом можно заметить, что они почти всегда проектируются во всей красе только для десктопа, для горизонтальных экранов, где очень похожи на разворот на две страницы. Для примера возьмем вот эти два концепта:
Мы воспользуемся ими, как примерами использования нашей сетки. Но для начала стоит сказать пару слов про пропорции и негативное пространство. Если вы не знаете, что это такое, то очень рекомендую почитать книгу «Дизайн для недизайнеров».
На таких сайтах у нас обычно есть три типа элементов — текст, картинки или видео и декоративные фигуры. Начинающие, а иногда и не очень начинающие верстальщики берут макет и начинают в лоб копировать размеры всего этого в пикселях. Включая отступы. И размеры шрифтов. В результате при изменении пропорций окна браузера все «съезжает» и выглядит уже не так здорово. Это происходит из-за того, что ломаются свойства элементов, связанные с размером шрифта в них (включая примерное количество букв или слов в строках, радиусы закруглений и.т.д.), и перераспределяется негативное пространство. И если вопрос со шрифтами еще можно решить с помощью CSS-шлюзов, адаптивной типографики и задания размеров всего в REM/EM (как на том же Smashing Magazine к примеру), то с негативным пространством нужны меры посерьезнее. И на помощь приходит именно наша странная сетка.
Магические проценты против системы
Если делать верстку подобных страниц по-старинке, абсолютным позиционированием, не привязываясь к сетке, то это занятие превратится в бесконечное копирование самых разных чисел, обозначающих проценты или пиксели для свойств top, left, right и bottom в CSS. Это будет просто гора магических чисел, в которых невозможно ориентироваться, которые совершенно невозможно проверить «на глазок», не говоря уже о хоть какой-нибудь системе. А хотелось бы выразить все в простом и понятном наборе чисел, как с колонками у бутстрапа. Тут помимо удобства еще стоит вопрос постоянства, непротиворечивости, или, как это модно говорить, consistency. В нашем контексте, если набор размеров и положений элементов не ограничен, то очень сложно поддерживать постоянство и все на страницах начинает «плясать» в разные стороны. Это вечная болезнь сайтов, не имеющих руководства по стилю, заложенного непосредственно в код и головы разработчиков.
Чтобы вы прочувствовали всю боль, представьте, что элемент навигации повернут на 90 градусов, выровнен своим верхним (оказавшимся теперь слева) краем по сетке в правой части страницы, но его высота (теперь ширина) меньше ширины ячеек сетки, в которых он расположен, и люди, не знающие о сетке, по привычке измеряют расстояние от его нижнего (теперь правого) края до правой части окна браузера, как самое маленькое, но это расстояние уже не имеет ни малейшего отношения к сетке. Это расстояние от правого края экрана до направляющей линии сетки минус размер условного текста с определенной высотой строки в этом конкретном элементе. И таких элементов на странице десятки. И их положения в CSS не имеют никакого отношения к сетке, хотя они по ней по идее выравниваются. Тут нужно бы вставить картинку из первого Black Ops, где герой видит числа. Много чисел.
А что, если я скажу вам, что во всем этом есть система? Давайте наложим нашу «кривую» сетку 20×20 на вышеупомянутые страницы и просто посмотрим.
Ух ты. Все элементы расставлены ровно по сеточке. Вопрос только в том, в какую сторону в них выровнен текст — влево, вправо, вверх или вниз, но положение самих блоков явно не случайное. Давайте посмотрим второй пример:
И снова, все расположено не случайно. Единственный элемент, который слегка выбивается — текст в центре. Но присмотревшись становится понятно, что он немного сдвинут вправо (показано стрелочками), но если трансформацию убрать, то он точно также ровно встанет на свое место, которое я обвел розовым цветом.
Какой бы странной не казалась сетка на первый взгляд, она вносит систему в дизайн, и было бы логично эту систему сохранить и в коде. Располагая все строго по сетке и используя CSS-трансформации по мере необходимости мы делаем код более понятным и поддерживаемым.
Возможно вы видели сайты с такого рода дизайнами и множеством анимаций (даже если там нет WebGL и сложных переходов между страницами, то уж wow.js точно есть почти всегда). Так вот, там все верстается точно также по сетке, а все появления элементов происходят с помощью CSS-трансформаций, когда элемент заранее «вынимается» из сетки трансформацией, а потом анимируется в изначальное состояние.
Важно отметить тонкий ромб вокруг девушки. Можно подумать, что он вылетел из системы влево, но это только на первый взгляд. На самом деле он привязан не к ней, а к картинке, а «вылетел» он лишь за счет неравномерности сетки.
Логика поведения важнее конкретных чисел
На примере этой малозаметной на первой взгляд детали вскрывается очень важный, чуть ли не самый важный принцип верстки подобных дизайнов для десктопа, а именно: логика поведения элементов всегда стоит на первом месте. К чему он привязан? Относительно чего выравнивается? Как связан общий дизайн страницы с состоянием этого конкретного элемента? Что с ним происходит при незначительном изменении размера окна или содержимого? Это те вопросы, которые делают из просто верстки хорошую верстку, которая хорошо смотрится на любых экранах.
Не копируйте размеры в пикселях просто так, изучайте разные варианты позиционирования в CSS и всегда обращайте внимание на контекст. Это может сильно упростить поддержку кода и работу над адаптивностью.
Учимся считать до 20
Перед тем, как перейти к практической части и написанию кода, хотелось бы сказать пару слов о подсчете блоков в такой сетке. Ее можно одновременно отобразить как в макете, так и на странице (через background-image размером в 100% на 100% для контейнера с сеткой), но считать все равно придется.
Лично мне кажется удобным при таком подходе покрасить сетку на куски 5×5 блоков и ориентироваться по ним:
Считать от 1, 5/6, 10/11, 15/16, 20, добавляя или вычитая числа от 1 до 5 не так сложно, единственное что может немного путать — это вычитание (поначалу все ошибаются на единицу в ту или иную сторону), но это быстро проходит. Вы конечно спросите, а почему бы не считать с 0, как нормальные люди? А дело в том, что в CSS Grid счет идет с 1.
Гриды в CSS — золотая пуля
Помните тот челлендж, когда что-то делается в 30 строк кода? Так вот, такую страницу вполне можно сверстать в 30 строк и при этом код будет вполне понятным. Не верите? Ну давайте посмотрим.
Современный CSS предоставляет нам замечательную возможность сделать такую сетку — гриды. Они как будто специально сделаны под эту задачу. С помощью свойств grid-template-columns и grid-template-rows можно задать соотношения между размерами наших блоков, нужно только их посчитать.
Вооружившись калькулятором сделать это несложно. А если под рукой есть уже нарисованная сетка с направляющими, то это превращается в чисто механическую задачу. Если взять первую ячейку в строке или столбце за 1, то получится последовательность размеров 1, 1, 2, 4, 2.66, 5.33 и.т.д. Это размеры ячеек относительно первой в случае сетки с 20 строками или колонками и теми направляющими, что и в наших примерах. Если у вас в проекте другое количество ячеек в сетке — придется пересчитать все самостоятельно. Подставим их в вышеупомянутые свойства:
.golden-grid {
grid-template-rows: 1fr 1fr 2fr 4fr 2.66fr 5.33fr 5.33fr 4.33fr 2.83fr 3.5fr 3.5fr 2.83fr 4.33fr 5.33fr 5.33fr 2.66fr 4fr 2fr 1fr 1fr;
grid-template-columns: 1fr 1fr 2fr 4fr 2.66fr 5.33fr 5.33fr 4.33fr 2.83fr 3.5fr 3.5fr 2.83fr 4.33fr 5.33fr 5.33fr 2.66fr 4fr 2fr 1fr 1fr;
}
Не так уж и сложно. Обычно нужно растянуть сетку на весь экран и задать ей позиционирование, так что сделаем это. Можно на фон вывести картинку с сеткой, чтобы проверять себя по ней:
.golden-grid {
display: grid;
position: relative;
height: 100vh;
width: 100%;
grid-template-rows: 1fr 1fr 2fr 4fr 2.66fr 5.33fr 5.33fr 4.33fr 2.83fr 3.5fr 3.5fr 2.83fr 4.33fr 5.33fr 5.33fr 2.66fr 4fr 2fr 1fr 1fr;
grid-template-columns: 1fr 1fr 2fr 4fr 2.66fr 5.33fr 5.33fr 4.33fr 2.83fr 3.5fr 3.5fr 2.83fr 4.33fr 5.33fr 5.33fr 2.66fr 4fr 2fr 1fr 1fr;
background: url('grid.jpg') left top / 100% 100% no-repeat;
}
На этом сетку можно считать готовой.
Верстаем
Возвращаемся к картинкам, на которых отмечали расположение блоков на макетах, и начинаем верстать. Ничего не измеряем, никаких пикселей, только номера ячеек в таблице. Начнем с фиолетового концепта.
...
Смотрим на расположение фото с девушкой — начинается с левой границы, занимает половину по вертикали и чуть больше половины по горизонтали. В контексте сетки — начинается с ячейки [11, 1] и простирается на 10 вниз и на 12 вправо. На самом деле, если немного попрактиковаться, то можно будет с большой точностью угадывать эти числа, не считая ячейки.
Едем дальше — левая фоновая картинка. Занимает все 20 ячеек по высоте и шесть по длине. Начинается с седьмой? Глазомер может обманывать, проверяем — все верно.
Таким образом проходим по всем объектам на странице:
Я специально пишу инлайновые стили, чтобы это было макимально компактно и можно было охватить всю страницу одним взглядом. На практике, конечно, имеет смысл выносить это в классы в CSS, чтобы было по крайней мере проще писать media-выражения.
Расположение блоков на первой странице готово. Переходим ко второй и действуем аналогичным образом:
Для текста добавили трансформацию, чтобы он оставался в сетке. Посмотрим на результат (сверху картинки, снизу скриншоты сверстанных положений элементов с подложенной под них сеткой):
Остается задать цвета элементам, вставить картинки, написать тексты и добавить повороты на 90 градусов (через CSS-трансформацию rotate) и выравнивание влево-вправо и вверх-вниз для них. Но это все мелочи — главное, что самая проблемная задача с позиционированием решилась быстро и просто.
Песочница для экспериментов.
А что там с адаптивностью?
Практика показывает, что такие сайты проектируются под горизонтальные экраны, а сетка позволяет сохранить красивый внешний вид на разных их пропорциях — fullhd, повернутый iPad, повернутый Nexus 7 — везде будет хорошо. Есть две основных ситуации, когда что-то нужно менять:
- Слишком маленькая высота вьюпорта (очень широкий, но низкий — бывает если изменить размер окна вручную или если на планшете клавиатура показывается).
- Высокий, но узкий вьюпорт, когда «разворот на две страницы» не влезает по ширине и деформируется (телефоны, планшеты в вертикальной ориентации).
Первый вопрос обычно решается заданием минимальной высоты для секций, сделанных по такой сетке, и отключением постраничного скролла, если он там есть. Таким образом внешний вид сохраняется, а интерактивные элементы остаются доступными — до них можно доскроллить.
Вертикальная мобильная версия нужна в первую очередь для потребления контента. Там уже не получится развернуться и делать гигантские отступы в угоду красоте и произведению впечатления. Обычно постраничный скролл отключается, сетка отходит на второй план (вплоть до того, что всем ее элементам делается display: block) и остается важным только вертикальный ритм, который получается больше из отступов, связанных с размером шрифта. Хотя иногда бывают исключения, когда и на маленьких экранах дизайнер умудряется все красиво расставить. В таком случае мы просто меняем свойство grid-area на новое и выравниваем текст в нужную сторону.
Важным моментом являются брейкпоинты, на которых все перестраивается. Есть сторонники привязывания их к размерам популярных устройств, но здесь регулярно случаются ситуации, когда после добавления таких точек все получается не очень — или на мобильной версии можно было бы и больше уместить, или на середине планшетной стоит уже что-то убрать или переставить и.т.д. Все упирается в изначальный дизайн для большого экрана. Так что часто процесс адаптации приходит к концепции content-first или вариациям на эту тему, когда за основу берется содержимое и точки выбираются исходя из соображений дизайна, удобства, а не размеров экранов популярных устройств. То есть первичен контент, важно, чтобы его было удобно потреблять в задуманном виде, а мобильные, планшентые и десктопные версии — это уже вторично. Это просто названия для инструментов, но не основа. Да, это может приводить к тому, что брейкпоинтов будет больше обычных 2–3, может получиться 5 или даже 7, но такой подход позволяет сделать верстку, которая красиво выглядит на любых размерах экранов в обозначенных пределах.
Подводя итоги
Я понимаю, что не всем и не каждый день приходится работать с такими страницами, но подобные сетки довольно часто встречаются в разных нестандартных сайтах и по крайней мере полезно о них знать, чтобы в случае столкновения с такой версткой не паниковать и не тратить кучу времени на измерение ненужных размеров в пикселях или процентах, а один раз посчитать соотношения размеров ячеек и использовать современный CSS, благо поддержка старых браузеров в таких проектах — большая редкость.