От автора: CSS Grid – отличный инструмент разметки для сайтов, заточенных под контент с длинными фрагментами текста. CSS Grid имеет огромную ценность для множества стандартных макетов UI. В этой статье я расскажу, как с помощью CSS Grid улучшить макеты приложения, которые должны подстраиваться и адаптироваться под взаимодействия пользователя и изменение условий, чтобы ваши панели всегда правильно скролились.
Макеты сайтов CSS Grid обладают множеством достоинств. С помощью Grid веб-дизайнеры могут создавать красивые динамические макеты, используя всего лишь пару строк поддерживаемого кода вместо бесконечных обтеканий, которые мы использовали раньше. Моя подруга и коллега Jen Simmons говорила о CSS Grid очень давно, неустанно подталкивая к внедрению в браузеры. Ее старания не прошли даром. В конце прошлого года актуальные версии всех основных браузеров (десктоп и мобильные устройства) поддерживали CSS Grid.
CSS Grid – очень мощный инструмент, с его помощью можно с легкостью создавать сайты с динамическим контентом, как в этих примерах. Тем не менее, CSS Grid способен не только раскладывать блоки контента. CSS Grid дает полный контроль над двумя измерениями в макете, а также над скролом. То есть функции, которые раньше были нормой в нативных приложениях типа схлопывания боковых панелей и фиксированных тулбаров сейчас можно очень просто реализовать в вебе. Больше никаких хаков и отладки. CSS Grid просто работает.
Я уже несколько лет создаю веб-инструменты. Ниже представлен скриншот из инструмента для создания игры (моя ретро RPG). Когда появился Flexbox, я сразу перешел на него. Я создал сложные макеты с помощью вложенных горизонтальных и вертикальных блоков с парой классов-утилит для таких вещей, как прокрутка и растяжка.
Flexbox определенно повысил продуктивность по сравнению с абсолютным позиционированием div и float, но у него все еще были проблемы. Давайте приблизим в место, где панели соединяются. Смотрите, как футеры слева и справа не стыкуются в одну линию?
Ниже еще один скриншот. Тулбар расположен в верхней части холста. В моем фреймворке он фиксированный и расположен сверху, но как только вы начинаете скролить, происходит следующее. Тулбар исчезает:
Все эти проблемы можно решить еще большим количеством позиционирования и обтеканиями, но это будет очень хрупко. При добавлении новой панели мне придется отлаживать макет снова и снова в поисках того, какой div занимает дополнительное пространство при изменении размера. Разметка просто ужасная. Вложенные горизонтальные и вертикальные блоки становятся очень сложными, а это лишь пример на 2 уровня. По мере усложнения взаимодействия и функциональности дизайн становится еще сложнее.
<div class='vbox'> <div class='hbox'>header</div> <div class='scroll'> <div class='sidebar'>sidebar</div> </div> <div class='footer'>footer</div> </div> <div class=vbox> <div class='hbox'>button button spacer label spacer button button </div> <div class='center'>main content</div> <div class='hbox'>the footer</div> </div> <div class=vbox> <div class='hbox'>header</div> <div class='scroll'> <div class='sidebar'>sidebar</div> </div> <div class='footer'>footer</div> </div> </div>
Вход во второе измерение
Фундаментальная проблема Flexbox заключается в том, что он построен на одном измерении. Flexbox отлично подходит для одного измерения типа тулбаров и меню, но при выравнивании горизонтально и вертикально начинаются проблемы. Мне нужен был двумерный макет, поэтому мне понадобился CSS Grid. По умолчанию CSS Grid – это 2D.
Ниже представлен схожий макет, построенный на CSS Grid.
Присмотритесь к футерам. Они идеально подогнаны. Используя grid-gap вместо рамок для панелей, мне не нужно думать о разной ширине строк. Все просто работает.
Главный плюс CSS Grid – адаптация под изменение условий. В моих приложениях часто встречаются сайдбары. Мне необходимо убедиться, что в макете все работает, несмотря на то, свернуты сайдбары или нет (в идеале без повторного вычисления макета в JS). Сайдбары состоят из нескольких компонентов (хедеры и футеры и т.д.). Все они должны подходить друг к другу, вне зависимости от их размеров. CSS Grid может и это с помощью функции minmax().
Если вы изучали CSS Grid, то знаете, что макет можно определить через шаблоны строк и колонок. Шаблон 200px 1fr 200px даст нам сайдбары шириной 200px и областью для контента в середине, которая будет занимать оставшееся пространство. Но что буде, если схлопнуть панели? Прямо сейчас колонка останется 200px, несмотря на то, что контент схлопнулся. Вместо это можно использовать minmax с ключевым словом min-content для параметра max.
#grid { display: grid; box-sizing: border-box; width: 100vw; height: 100vh; grid-template-columns: [start] minmax(auto, min-content)1fr [end] minmax(auto,min-content); grid-template-rows: [header]2em [content]1fr [footer]2em; grid-gap: 1px; background-color: black; }
Теперь колонка сетки будет подстраиваться по ширине под любой контент с помощью минимальной ширины. Поэтому если одна часть колонки (хедер) шире других, колонка расширится, подстраиваясь под все части. Если они станут уже или исчезнут, колонка подстроится. По сути, мы скопировали поведение при расширении/сжатии в Flexbox, но заставили его работать со всем контентом в столбце, а не только с одним элементом. Это настоящий 2D макет.
Код остальной части демо.
.start { grid-column: start; } .center { grid-column: center; } .end { grid-column: end; } header { grid-row: header; } footer { grid-row: footer; } .sidebar { overflow: auto; }
<div id="grid"> <header class="start">header</header> <header class="center"> <button id="toggle-left">toggle left</button> ... </header> <header class="end">header</header> <div class="start sidebar">sidebar</div> <div class="center content">the center content</div> <div class="end sidebar"> sidebar<br/> ... </div> <footer class="start">left footer</footer> <footer class="center">center footer</footer> <footer class="end">right footer</footer> </div>
Чтобы кнопки в хедере действительно прятали сайдбары, я добавил следующий код. Современные DOM API и стрелочные функции могут копировать jQuery парой строк:
const $ = (selector) => document.querySelector(selector) const $$ = (selector) => document.querySelectorAll(selector) const on = (elem, type, listener) => elem.addEventListener(type,listener) on($('#toggle-left'),'click',()=>{ $$(".start").forEach((elem) => elem.classList.toggle('closed')) }) on($('#toggle-right'),'click',()=>{ $$(".end").forEach((elem) => elem.classList.toggle('closed')) })
Заметьте, что CSS Grid не запрещает использовать Flexbox. Мы все еще используем Flexbox там, где это необходимо: в одномерном контенте типа тулбаров. Ниже представлены стили, которые я использую для тулбаров, сделанных из хедеров:
<header class="center"> <button id="toggle-left">toggle left</button> <button>open</button> <button>save</button> <span class="spacer"></span> <span>filename.txt</span> <span class="spacer"></span> <button>delete</button> <button id="toggle-right">toggle right</button> </header> header { background-color: #ccc; display: flex; flex-direction: row; } .spacer { flex: 1; }
Класс spacer заставляет элемент занимать все дополнительное пространство. Используя 2 spacer между кнопок, я заставляю тулбар прятаться и появляться, а название файла всегда остается посередине. Поведение схоже с нативными тулбарами.
Попробуйте демо на Codepen. Можете его улучшить.
CSS Grid идеально подходит для проектирования интерактивных приложений в двух плоскостях. Мы можем сохранить семантику разметки. Панели и тулбары правильно выравниваются. grid-gap добавляет автоматические рамки. Инструмент проводит сложные настройки макета без JS кода и предоставляет контроль на горизонтальной и вертикальной осью. Все это доступно без использования тяжелого CSS фреймворка.
Jen Simmons запустила новый канал на YouTube Layout Land, где она рассказывает о работе CSS Grid. Если вы работаете над веб-приложениями или сайтами любой тематики с высокой интерактивностью, обязательно попробуйте CSS Grid.
Автор: Josh Marinacci
Источник: https://hacks.mozilla.org/
Редакция: Команда webformyself.