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

image

В материале, перевод которого мы сегодня публикуем, Джош Мариначчи рассказывает о том, как использовать CSS-grid для проектирования макетов страниц. Речь пойдёт о страницах, которые способны реагировать на воздействия пользователя и на изменение их содержимого, но при этом всегда ведут себя так, как от них ожидается, в частности — при прокрутке их содержимого.

О технологии CSS Grid Layout


Технология CSS Grid Layout, или просто CSS-сетка, предназначена для построения макетов веб-страниц.

Эта технология позволяет веб-дизайнерам создавать прекрасные динамические макеты, используя совсем немного понятного кода, а не бесконечно экспериментируя со свойством CSS float, которое мы вынуждены были применять раньше. Мой друг и сослуживец Джен Симмонс говорил о CSS-сетка много лет, неустанно стремясь к тому, чтобы их поддержку реализовали в браузерах, и его усилия увенчались успехом. В конце прошлого кода поддержка технологии CSS Grid Layout появилась в текущих версиях всех основных настольных и мобильных браузеров. Кстати, Джен запустил новый канал на YouTube, Layout Land, который предназначен для всех, кто хочет в совершенстве освоить возможности CSS Grid Layout.

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

Дизайн без CSS-grid


Я занимаюсь созданием инструментов для веб-разработки уже многие годы. Вот скриншот редактора, который я создал для разработки моих ретро-игр в стиле RPG. Как только появилась технология Flexbox, я немедленно взял её на вооружение. Я создавал сложные макеты с использованием вложенных горизонтальных и вертикальных блоков, применяя несколько вспомогательных классов для задач вроде скроллинга и изменения размеров элементов.


Инструмент для разработки игр в стиле RPG

Технология Flexbox, без сомнения, позволила мне работать продуктивнее, если сравнивать это с теми временами, когда я пользовался абсолютным позиционированием и боролся с float. Но и тут не всё было гладко. Взгляните на увеличенный фрагмент предыдущего скриншота, на то место, где панели сходятся. Обратите внимание на проблемы с выравниванием нижних панелей.


Проблемы с выравниванием панелей

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


Исчезающая панель инструментов

Каждую из этих проблем можно решить и с помощью свойства float, углубившись в тонкости позиционирования элементов, но то, что в результате получается, оказывается весьма хрупким. Всякий раз, когда я добавляю новую панель, мне приходится снова и снова перепроверять и дорабатывать весь макет, выискивая, какой конкретно элемент div отбирает себе слишком много места при изменении размеров элементов. Кроме того, при таком подходе и код разметки выглядит не очень-то приятно. Структуры из вложенных горизонтальных и вертикальных блоков становятся чрезмерно сложными. Например, ниже показан фрагмент кода, в котором имеются всего два уровня вложенности. А ведь два уровня — это далеко не предел. При этом, по мере развития схем взаимодействия со страницей и её функционала, усложняется и процесс работы над ней.

<div class='hbox'>
  <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 Layout, которая изначально предназначена для формирования двумерных сеток.

Вот макет, похожий на те, что мы уже рассматривали, но построенный с использованием CSS-grid.


Макет, построенный с использованием CSS-grid

Обратите внимание на низ страницы. Все панели идеально выровнены по отношению друг к другу. Кроме того, используя свойство grid-gap для линий, вместо того, чтобы добавлять границы к каждой панели, я могу не беспокоиться о разной ширине линий сетки. Всё, без дополнительных усилий, выглядит так, как должно выглядеть.


Увеличенная часть макета, демонстрирующая идеальное выравнивание панелей

Наиболее значительное преимущество, которое я получаю, используя CSS-grid, заключается в возможности адаптации макета страницы к изменениям. У моих приложений часто имеются боковые панели. Мне нужно, чтобы всё в макете вело себя так, как ожидается, независимо от того, развёрнута панель или свёрнута, причём, в идеале, требуется, чтобы все эти изменения происходили без необходимости пересчёта параметров макета в JavaScript. Боковые панели состоят из множества компонентов, там имеются шапки и подвалы. Всё это должно быть выровнено, вне зависимости от размеров этих элементов. Используя CSS-grid, подобного можно добиться, применив замечательную CSS-функцию minmax().

Если вы уже изучали CSS-grid, тогда вы знаете, что макеты можно описывать с использованием шаблонов для строк и столбцов сеток. Например, шаблон вроде 200px 1fr 200px позволит создать боковые панели шириной 200 пикселей с областью для содержимого в середине, занимающую оставшееся пространство. А что произойдёт, если панели должны быть сворачиваемыми? Если не предпринять никаких дополнительных усилий, то столбец, где была панель, так и будет занимать 200 пикселей, даже если его содержимое будет свёрнуто. В подобной ситуации можно использовать функцию minmax(), при вызове которой, в качестве параметра max (в нашем случае это второй параметр) используется ключевое слово min-content.

#grid {
  display: grid;
  box-sizing: border-box;
  width: 100vw;
  height: 100vh;
  grid-template-columns: 
      [start] minmax(auto, min-content) 
      [center]1fr 
      [end] minmax(auto,min-content);
  grid-template-rows: 
      [header]2em 
      [content]1fr 
      [footer]2em;
  grid-gap: 1px;
  background-color: black;
}

Теперь столбец сетки всегда будет иметь такую ширину, которая достаточна для вывода того, что в него помещено, при этом использоваться будет минимальная необходимая ширина. Таким образом, если одна часть столбца (например, шапка) будет шире, чем другие, ширина столбца увеличится для того, чтобы он мог вместить всё, что нужно.

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

Вот код оставшейся части демонстрационной страницы, которую мы тут обсуждаем.

.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
...
</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:

<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 заставляет элементы занимать всё дополнительное пространство. Используя два таких класса между кнопками, я могу сделать так, чтобы панель инструментов меняла при необходимости размер, но делала это так, чтобы имя файла всегда находилось в её центре. Примерно так же ведут себя панели инструментов обычных приложений.

Вы можете поэкспериментировать со всем этим в специально подготовленном проекте на Codepen.


Проект на Codepen

Итоги


CSS-grid — это потрясающий инструмент для проектирования интерфейсов интерактивных веб-приложений, который позволяет управлять тем, как содержимое страницы располагается по горизонтали и по вертикали. Такие макеты просто и понятно устроены, все элементы в них правильно выровнены, а свойство grid-gap позволяет автоматически создавать границы между ними. Средства CSS-grid позволяют модифицировать внешний вид макетов без привлечения JavaScript, они дают полный контроль над размещением содержимого страниц. Тут очень важно отметить, что всё это — стандартные возможности, поддерживаемые браузерами, не требующие применения тяжёлых CSS-фреймворков.

Если вы занимаетесь разработкой веб-приложений или любых интерактивных веб-сайтов, уверен, вам стоит попробовать CSS-grid.

Уважаемые читатели! Пользуетесь ли вы CSS-grid при проектировании веб-страниц?

Комментарии (8)


  1. Atreides07
    28.02.2018 15:01

    Спасибо за перевод! Но возможно не надо частично/дословно переводить "CSS Grid" как "CSS-Сетка", так как все таки это неделимое название спецификации (или инструмента/технологии как Вы назвали). Это все равно что перводить Flexbox, Sketch и т.п.


    1. dom1n1k
      28.02.2018 18:14

      Не возможно, а совершенно точно не нужно переводить. Уже устоялся термин «гриды», все так говорят. А слово «сетка» используется в более широком и общем смысле.


    1. ru_vds Автор
      28.02.2018 18:27

      Спасибо за комментарий. Все исправили.


      1. Atreides07
        01.03.2018 13:25

        Еще немного занудства. Обычно сокращенное название спецификации пишется как "CSS Grid" а не "CSS-grid"


  1. TanyaS
    01.03.2018 11:39

    Мой друг и сослуживец Джен Симмонс говорил...

    Кстати, Джен запустил новый канал...

    Джен Симмонс — девушка.


  1. rexen
    01.03.2018 12:01

    Кто бы лёгкий css-grid фреймворк посоветовал, в котором при помощи JS и хаков добиваются совместимости с броузерами, которые grid не умеют.


    1. SelenIT3
      02.03.2018 15:16

      Не надо такого делать. Браузеры, которые не умеют гриды ни в каком виде (т.е. всякие IE9- и ископаемые андроиды), как правило, работают на полумертвом ископаемом же железе, и строить в них сетку JS и хаками обойдется такими тормозами, что пользоваться этим всё равно будет невозможно. Общепринятый и идейно правильный подход для них — отдавать им менее красивую, но быстро открывающуюся раскладку, хоть в одну колонку а-ля мобильная версия (ну или что-нибудь простое на флоатах/инлайн-блоках).


      А код для старой версии гридов, которую умеет IE10+ (и в которой, в общем-то, есть почти всё что нужно для простых случаев, кроме grid-gap и, что обиднее, grid-auto-flow), вроде как умеет выдавать Autoprefixer.


  1. evgenWebm
    01.03.2018 12:42

    Уже много лет не использую float.
    Подожду годик и введу в свой css «фреймворк» grid. Не хочется использоваться костыли для совместимости.
    Но вообще грид меня радует. В комплекте с флексом, можно творить чудеса без применения магии и какойто матери.