CSS Grid Layout for Image Gallery

Вступление


Всем привет. Февраль-Март 2017 года запомнились для многих, кто работает с HTML и CSS тем, что большинство браузеров выпустили обновления, среди которых были и обновления для CSS. Теперь можно использовать спецификацию CSS Grid Layout без флагов в следующих браузерах: Firefox 52, Chrome 57, Opera 44, Safari 10.1. Какой из браузеров остался позади, думаю, вы догадываетесь. Точнее он поддерживает старую версию спецификации. Но разработчики этого браузера делают все возможное, чтобы внедрить новую спецификацию. Внедрение поддержки новой CSS Grid Layout спецификации — это самое значимое событие за прошедшие пять лет. Эта спецификация поменяет полностью подход к разработке пользовательских интерфейсов. И это круто.

Я использую Flexible Box Layout


Многие задаются вопросом: «Стоп, я использую flexbox, зачем мне еще какие-то grid’ы?». Вопрос более чем уместен. CSS Grid не заменит Flexbox и наоборот. Первое отличие — это то, что Flexbox работает только в одном измерении. Из этого следует, что мы можем размещать flex элементы только вдоль главной оси или вдоль поперечной оси. Мы не можем разместить flex элементы сразу на нескольких осях. CSS Grid в свою очередь нам позволяет работать с разметкой в двухмерном пространстве и выравнивать содержимое в обоих измерениях. Мне нравится как объясняет эту разницу Tab Atkins.

Одна из самых больших проблем при разработке пользовательских интерфейсов — это то, что при изменении дизайна, функционала или поведения любого блока приходится менять его разметку (в большинстве случаев). CSS Grid позволяет менять расположение grid элементов не меняя сам HTML. Ниже пример простой разметки на Flexbox и CSS Grid.


Основные термины

Grid Layout Concepts and Terminology
Прежде чем приступать к работе с CSS Grid, нужно разобраться с основными терминами. На основе этих терминов построена вся спецификация.

Grid container — это набор пересекающихся горизонтальных и вертикальных grid линий, которые делят пространство grid контейнера на grid области, в которые могут быть помещены grid элементы. Внутри grid контейнера есть два набора grid линий: один определяет ось столбцов, другой определяет ось строк.

Grid lines — это горизонтальные и вертикальные разделители grid контейнера. Эти линии находятся по обе стороны от столбца или строки. Автор может задать для данного элемента имя или числовой индекс, которые может использовать дальше в стилях. Нумерация начинается с единицы. Важный нюанс, данный элемент восприимчив к режиму написания, который используется на вашем ресурсе. Например, вы используете Арабский язык или любой другой язык у которого режим написания справа налево, то нумерация линий будет начинаться с правой стороны.

Grid track — это пространство между двумя смежными grid линиями, вертикальными или горизонтальными.

Grid cell — это наименьшая неделимая единица grid контейнера на которую можно ссылаться при позиционировании grid элементов. Образуется на пересечении grid строки и grid колонки.

Grid area — это пространство внутри grid контейнера, в которое может быть помещен один или больше grid элементов. Этот элемент может состоять из одной или более grid ячеек.

Каждый элемент тесно связан друг с другом и отвечает за определенную часть grid контейнера.

Первый CSS Grid макет


Мы разобрались с основными терминами. Пришло время сделать наш первый grid макет. Ничего сложного, простенький макет три строки на три колонки, чтобы разобраться с основами. Ниже вы можете увидеть пример.


В первом варианте из примера мы создаем три колонки размером 150px 1fr 150px и три строки размером 50px auto 50px соответственно. Обратите внимание на такие значения: 1fr, auto. Давайте разберемся, что это за значения.

1fr — это специальная единица измерения введенная в данной спецификации. Она не измеряется в каких-то конкретных единицах измерения (px, em, rem, др.) Из этого следует, что мы не можем использовать ее вместе с функцией calc(). Эта единица измерения не может быть меньше единицы, а также не может принимать отрицательные значения. Она рассчитывается после того, как все остальные значения, отличные от fr, были рассчитаны.

auto — ведет себя довольно интересно и использует для расчета размеров хитрый алгоритм. В некоторых ситуациях может показаться, что эта единица измерения работает точно также как и fr. Но это не так. Главное отличие, auto будет рассчитан до того, как будет рассчитан fr. Об этом нужно помнить. Вы можете увидеть данное поведение из второго и третьего вариантов примера, который приведен выше.

Для разметки колонок и строк используются следующие правила:

grid-template-columns: 150px 1fr auto;
grid-template-rows: 50px auto 50px;

Сокращенная форма записи выглядит так:

grid-template: 50px auto 50px / 150px 1fr auto;

Типичный шаблон на grid’ах


Давайте сделаем простенький шаблон с которым мы все знакомы. Ничего сложного, шаблон будет состоять из следующих тэгов: header, nav, aside, article, footer. Подавляющее большинство интернет ресурсов использует данный шаблон. Только знаете, даже в таком простом шаблоне наблюдается следующая проблема: «Я дизайнер, я так хочу. Я разработчик, я так не могу». С появлением CSS Grid Layout подобная проблема должна стремиться к нулю.


В данном примере мы знакомимся еще с несколькими свойствами CSS Grid Layout. Первое grid-template-areas. Оно используется для создания именованных областей grid контейнера, которые не связаны с каким-либо конкретным grid элементом. Синтаксис очень удобен, мы сразу видим какой шаблон получится на выходе. Второе свойство grid-area. Оно используется для дочернего элемента grid контейнера. Указывает в какую именованную область поместить grid элемент.

Давайте рассмотрим первый вариант grid-template-areas:

grid-template-areas: "header header"
                     "nav  main"
                     "footer ."

Один или больше идущих подряд символов . (точка) имеют особое значение. Если этот символ используется, то браузер его отрендерит как нулевой токен, что в свою очередь означает следующее: на его месте не будет создана именованная область grid контейнера и в нее нельзя поместить grid элемент.

Если мы не указали для какого-то дочернего grid элемента свойство grid-area, браузер автоматически распределит такие элементы. Такое поведение можно увидеть из последнего варианта, приведенного примера выше.

Полезные ссылки


  1. CSS Grid Layout Module Level 1
  2. How to create a simple layout with CSS Grid Layouts
  3. Grid by Example от Rachel Andrew
  4. Подборка ресурсов для изучения CSS Grid Layout от Jen Simmons
  5. Ресурс для изучения СSS Grid Layout от Mozilla
  6. Jen Simmons про CSS Grid CSS Grid Layout
  7. Моя подборка ресурсов по CSS Grid Layout
  8. Множество годных статей (как своих авторских, так и переводов) по CSS Grid Layout на css-live.ru

Вместо заключения


В данной статье мы рассмотрели всего лишь верхушку CSS Grid Layout айсберга. Я начал обращать внимание на CSS Grid Layout еще когда все браузеры его поддерживали за флагами. Данный текст не способен передать мои впечатления от работы с этой спецификацией. Иногда сложно поверить своим глазам какие штуки удается сделать при помощи CSS Grid. Это разрыв всех шаблонов. И мне это нравится.

Я вам советую обратить внимание на данную спецификацию и потратить немного своего времени на ее изучение. Поверьте, в будущем вам это точно пригодится и не важно, пишете вы на React, Angular, Vue (вставьте свое). Grid’ы пришли надолго.

Напоследок добавлю пример с произвольным появлением grid элемента в разных именованных областях.


На этом все. Спасибо за внимание. Кто дочитал до конца, отдельное спасибо.
Была ли эта статья полезной?

Проголосовал 181 человек. Воздержалось 55 человек.

Хотите прочитать более развернутый вариант статьи про CSS Grid Layout?
97%
(203)
Да
3%
(6)
Нет

Проголосовало 209 человек. Воздержалось 38 человек.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Поделиться с друзьями
-->

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


  1. comerc
    07.04.2017 13:26
    +1

    Конечно интересно! Про полифилы ещё бы пару слов.


    1. var_bin
      07.04.2017 13:48
      +3

      Добрый день.


      Спасибо за отзыв. Хорошо, сделаем. Добавлю пункт "Полифилы, Progressive Enhanced для CSS Grid Layout" в следующую статью.


      1. theWaR_13
        07.04.2017 17:05
        +3

        Плюсую про полифилы. Нашел один, CssGridPolyfill, но непонятно, можно ли использовать в проектах.


  1. Throwable
    07.04.2017 13:33

    Наконец-то в браузере появятся нормальные лейауты! FlexBox вместе с GridLayout покрывают практически всю необходимость разметки в приложениях.
    А вообще, как-то странно: именно производители "того самого браузера" изначально предложили и пилили спецификацию GridLayout, теперь же хуже всех ее поддерживают.


  1. cranium256
    07.04.2017 14:01

    Теперь можно использовать спецификацию CSS Grid Layout без флагов в следующих браузерах: Firefox 52, Chrome 57, Opera 44, Safari 10.1. Какой из браузеров остался позади, думаю, вы догадываетесь. Точнее он поддерживает старую версию спецификации.

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


    1. var_bin
      07.04.2017 14:09

      Добрый день.


      А так всё равно придётся писать кучу флагов для совместимости.

      Да, есть такое. Но можно завтавить машины страдать. И там получается не такая уж и большая куча )


  1. kordenv
    07.04.2017 14:09

    вещь отличная grid, но немного рано еще их юзать по сравнению с flex
    http://caniuse.com/#search=flex — поддерживают все современные браузеры
    http://caniuse.com/#search=grid — некоторые версии не поддерживают
    я думаю еще год и можно будет спокойно юзать grid для любого проекта… имхо


    1. dom1n1k
      07.04.2017 15:19

      Насчет последней строчки — сомнительно как-то.
      Для узконишевых проектов (с технически продвинутой аудиторей) гриды можно будет применять уже в этом году.
      А вот для широких масс, думаю, придется ждать еще минимум года 2, если не больше. Хвост эксплореров, опер мини и тому подобного будет волочиться ещё долго.


      1. var_bin
        07.04.2017 15:54

        Добрый день.


        Да, полностью согласен. Я знаю много проектов, у которых целевой браузер — это Chrome. Вот где свобода для творчества.


  1. sashabeep
    07.04.2017 14:52

    Очень хочется, чтобы grid layout обогнал flexbox по скорости внедрения в браузеры.
    Недавно MS принялась за запиливание гридов в текущей спецификации, которое прилетит с апдейтом во все их браузеры, включая 10-ку, что само по себе неплохо.
    Когда начал первые эксперименты с сетками, получил очень много флешбеков :)

    Заголовок спойлера


    1. psywalker
      08.04.2017 11:47

      А вы не могли бы предоставить пруф на обновление гридов в IE10? Что-то не смог найти в инэте информацию об этом:(


      1. anttoshka
        08.04.2017 16:26

        Даже если вдруг прилетит такое обновление в IE10/11 это совсем не будет гарантировать, что у пользователя есть этот апдейт :)


      1. Aingis
        08.04.2017 17:25

        Наверное, это про 10 версию Windows и Edge. Если даже Edge работает только под десяткой, то явно не будут обновляться старые браузеры.


        1. psywalker
          08.04.2017 18:18

          Да, видимо так оно и есть, спасибо!


        1. sashabeep
          08.04.2017 19:59

          Да, судя по фразе с «10-й версии» реализации. А я-то губищу раскатил


      1. sashabeep
        08.04.2017 19:58

        1. Aingis
          10.04.2017 13:53

          Тут написано, что старая префиксная реализация, введённая в IE10, будет обновлена до актуальной версии сеток (и чего их все гридами называют?). Обновлена, очевидно, в Edge, о других разработках не сообщалось.


          1. sashabeep
            10.04.2017 14:27

            На 1 коммент выше написано, что я неверно перевел фразу относительно про «10 версию», которая, очевидно, написана про реализацию, а не про браузер


  1. token
    07.04.2017 16:28

    1fr, не может быть меньше единицы, а как тогда сделать header и footer, так чтобы их высота регулировалась бы высотой содержимого? Вот так почему то работает: grid-template-rows: 0fr auto 0fr;


    1. var_bin
      07.04.2017 16:53
      +1

      Добрый день, Руслан.


      Спасибо за интересный вопрос. Отвечу сначала как сделать так, чтобы высота header'a и footer 'a зависела от контента. Довольно просто, задайте значение auto или можно использовать функцию minmax() со следующими значениями minmax(auto, 10vh). что в свою очередь будет означать: максимам по высоте будет 10vh минимум auto (по контенту).


      Вот так почему то работает: grid-template-rows: 0fr auto 0fr;

      Конечно работает) Браузер умный и пытается посчитать значение. Тут можно почитать про алгоритм. Если в кратце, то браузер пытается высчитать гипотетическое значение 0_О. Не делайте так ) Вы заставляете страдать браузер.


      1. token
        07.04.2017 16:55

        Пробовал auto X auto, но вместо X не знаю что подставить, 100% не работает )


        1. var_bin
          07.04.2017 16:59

          Ну вы явно что-то не так делаете. Покажите на примере. И опишите подробно как вы хотите, чтобы себя вели строки, колонки.



    1. sashabeep
      10.04.2017 14:34

      min-height: 100vh;
      grid-template-rows: min-content auto min-content;
      


  1. psywalker
    07.04.2017 17:56
    +1

    Кстати, вы в данной статье и у себя на сайте добавили ссылки на изучение этой спецификации. Может, если не сложно, добавите и нашу ссылку, всё же у нас есть очень много годного по этой теме?


    1. var_bin
      07.04.2017 18:16
      +1

      Добрый день, Максим.


      Да, конечно.


      1. psywalker
        07.04.2017 18:40
        +1

        Спасибо вам большое!


  1. pm_wanderer
    07.04.2017 18:55

    Еще, судя по Can I Use, не поддерживается дефолтный браузер андроид и в мобильном хроме есть баг. Также не ясно что там с UC Browser, который в последнее время становится все популярней на Андроиде. Ждем полную поддержку, короче)


  1. Boberdober
    07.04.2017 20:15

    Спасибо за статью. Было бы интересно почитать более развёрнутые статьи с описанием чего-то сложного (например, неявных областей, растягивания элементов и прочего). А-то статей с описанием банальных вещей много, а чего-то толкового — нет.


    1. psywalker
      07.04.2017 23:55
      +1

      А вы уверены? Точно хорошо искали? Поскольку раз статья, два статья, три статья, к примеру :)


      1. Boberdober
        08.04.2017 00:08

        Да, спасибо, эти видел. Я к тому, что статей про grid-template-columns/grid-template-rows уже куча, а таких, где разбираются сложные вещи — маловато.


        1. psywalker
          08.04.2017 00:22
          +1

          Ну да, есть такое. Но вы подождите, этот модуль уже поддерживается почти во всех современных браузерах, кроме Edge, но даже и он уже обновляет свою старую реализацию! Так что уверен, что статьи по гридам сейчас должны появляться одна за другой :) А вообще, да, было бы весьма интересно почитать статьи var_bin и других неравнодушных к этой мощной и долгожданной спецификации разработчиков :)


        1. var_bin
          08.04.2017 09:20

          Добрый день.


          Да, вы правы. Таких статей хватает. У меня был соблазн написать сразу большую сложную статью. Но я от этой идеи отказался. Потому как даже такие простые штуки как grid-template-columns/grid-template-rows скрывают у себя под капотом очень много сложного. Говорю из своего опыта. Нужно с ними для начала разобраться, постоить с помощью этих штук не один макет, а потом двигаться к таким крутым вещам, как auto-fill, auto-fit, auto-flow, grid-auto-flow, grid-auto-rows, grid-auto-columns и т.д. Также важно понимать как работают алгоритмы расчетов значений, чтобы представлять, что вы получите на выходе.


          И только после этого, можно делать что-то сложное.


          Статей про такие простые вещи много, потому что каждый, кто начинал сам разбираться с CSS Grid Layout спецификацией находил для себя что-то непонятное, новое, что не было описано во всех предыдущих статьях. Ну и в итоге делился своим опытом в виде статьи. Я не считаю это плохо.


  1. beduin01
    08.04.2017 08:37

    На старые браузеры можно и нужно класть болт. Доля IE около 5% вместе с Edge. А вот процент людей с плохим зрением или ограниченными возможностями куда выше. Позаботьтесь лучше о них, а не о тех кто не может нормальный браузер себе поставить.


    1. var_bin
      08.04.2017 09:25

      Добрый день.


      На старые браузеры можно и нужно класть болт.

      Ну не обязательно ) Можно подойти к данной проблеме с другой стороны. Использовать Progressive Enhancement. подход.


      А вот процент людей с плохим зрением или ограниченными возможностями куда выше.

      Тут согласен. На это нужно обращать внимание.


  1. vintage
    08.04.2017 12:11
    -2

    Вы бы хоть скриншоты прикладывали для тех, у кого ваши примеры не работают.


    Не знаю, чего все так носятся с этими гридами. Сила флексбоксов в переносах при переполнении, из-за чего раскладка может динамически меняться, подстраиваясь под размер контейнера (а контейнер — далеко не только окно браузера). А возможность "не менять хтмл" — уже давно не актуальна, так как сейчас страницы собираются из компонент по шаблонам и шаблон — такой же равноправный код компонента, как и стили и скрипты.


    1. psywalker
      08.04.2017 13:21

      Боюсь, что не согласен с вами. Почитайте внимательнее раздел «Гибкие гриды без медиавыражений» вот в этой статье, а после посмотрите вот этот пример.


    1. var_bin
      08.04.2017 13:38
      +1

      Добрый день, Дмитрий.


      Вы бы хоть скриншоты прикладывали для тех, у кого ваши примеры не работают.

      Возможно вы и правы. Думаю, что те кто читают эту статью и у них не завелись примеры, то у них есть developer edition версия браузера. Плюс ко всему, можно включить флаги, и тогда полюбому заведется.


      А возможность "не менять хтмл" — уже давно не актуальна, так как сейчас страницы собираются из компонент по шаблонам и шаблон — такой же равноправный код компонента, как и стили и скрипты.

      Ну тут не соглашусь. Шаблон я так понимаю из html собирается. Я слабо себе представляю шаблон, который хоть раз не пришлось менять из-за смены поведения какого-то элемента в этом шаблоне или еще чего-то там.


      Сила флексбоксов в переносах при переполнении, из-за чего раскладка может динамически меняться, подстраиваясь под размер контейнера (а контейнер — далеко не только окно браузера).

      Гриды тоже это все умеют. Единственная с ними проблема (пока) — поддержка. Это да, очень большая проблема. Но CSS Grid Latout очень крут и он прекрасно решает множество задач и при этом не нужно себе "стрелять в ногу".


      К примеру. Мы с коллегами пробовали сделать шаблон на flexbox и на grid. Базовая разметка и код на grid заняли намного меньше места и проблем с ними было меньше. Пример, конечно, из вакуума, но все же.


      Вы попробуйте CSS Grid Layout для себя, для фана. Я вас уверяю, результатами останетесь довольны )


      1. psywalker
        08.04.2017 13:48

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


      1. vintage
        08.04.2017 18:45
        -1

        Я слабо себе представляю шаблон, который хоть раз не пришлось менять из-за смены поведения какого-то элемента в этом шаблоне или еще чего-то там.

        Я и говорю о том, что изменение шаблона — не проблема. Более того, изменения в шаблоне более явные — если вам нужно разместить 4 элемента в 2 строки, то в шаблоне у вас будет ровно это. Если же вы будете раскладывать элементы через css, то придётся раскладывать блоки в уме по тем коэффициентам, что заданы в css. Короче, при компонентном программировании изменение шаблона — вообще не проблема.


        Думаю, что те кто читают эту статью и у них не завелись примеры, то у них есть developer edition версия браузера.

        А зачем она им? Я вот занимаюсь разработкой веб приложений. Если в моём первом попавшемся браузере примеры не заводятся, значит технология ещё не готова к продакшену. Совсем. А пока не будет готова — её и копать нет особого смысла.


        Гриды тоже это все умеют.

        Раньше не умели. В статье тоже на этом не акцентировалось внимание. Ну, это замечательно. Хотя, лучше бы расширили возможности флексбокса, чем делать совсем другой display.


        Мы с коллегами пробовали сделать шаблон на flexbox и на grid.

        Покажете что за шаблон? Я бы тоже поучаствовал.


        1. var_bin
          08.04.2017 20:08

          По поводу шаблона. Ну такое. Спорить не буду. У каждого свои взгляды на это. Как говорится, карандаши на вкус и цвет разные )


          А зачем она им?

          У меня, например, всегда есть Chrome Canary и FF Developer Edition. Я их использую не для того, чтобы какие-то новые фичи смотреть (хотя и это бывает), а потому что, инструментарий разработчика там намного богаче. В тот же обычный Chrome не выкатывают никакие обновления для разработчиков, пока они не пройдут хорошую обкатку в Canary.


          Покажете что за шаблон? Я бы тоже поучаствовал.

          Набросал похожий пример (реальный шаблон не могу показать) http://codepen.io/var-bin/pen/yMWoOX К пример, тот же mobile first на grid'ах решается очень изящно. (поизменяйте размеры браузера). Если развить данную тему, взять flexbox, @support, grid'ы, то получиться довольно круто (Progressive Enhancement)


          1. vintage
            08.04.2017 22:40
            +1

            1. var_bin
              08.04.2017 22:58

              Жаль, что плюс можно ставить только один раз )


            1. var_bin
              08.04.2017 23:04

              Только вы все-таки поменяли разметку )


              1. vintage
                08.04.2017 23:21

                Ну да, асайд унёс вниз, где ему и место, а тело страницы (всё, что между шапкой и подвалом) завернул в секцию.


    1. SelenIT3
      09.04.2017 20:09
      +3

      Сила флексбоксов в переносах при переполнении, из-за чего раскладка может динамически меняться, подстраиваясь под размер контейнера

      У гридов эта сила тоже есть (auto-fill и auto-fit), при этом при переполнении структура этих самых компонентов остается именно сеткой, с вертикальным и горизонтальным ритмом, без странностей в последней строке, независимо от размеров контента каждого компонента. И при любом размере контейнера эта сетка может использовать доступное пространство оптимальным образом (пример частного случая).

      Но в основном с гридами «носятся» потому, что они избавляют от головной боли и хаков в решении первоочередной задачи верстки страниц — размещения и взаиморасположения основных структурных блоков (шапка, меню, сайдбар, подвал и т.п.). До сих пор для этого требовались горы хаков. Даже флексбоксы, хотя и здорово облегчили задачу, не решили ее до конца — с ними по мере загрузки страница перестраивается, блоки перепрыгивают, удаление/добавление блока влияет на поведение остальных ит.д. С гридами же задача решается тривиально, а блоки остаются каждый на своем месте, надежность старых добрых таблиц и гибкость семантической разметки «в одном флаконе». А если еще медиавыражения добавить..:)


      1. vintage
        09.04.2017 23:07

        И при любом размере контейнера эта сетка может использовать доступное пространство оптимальным образом

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


        Даже флексбоксы, хотя и здорово облегчили задачу, не решили ее до конца — с ними по мере загрузки страница перестраиваетс

        Это проблема не флексбоксов, а рассмотренного там кривого решения загрузки стилей. Путём разбиения стилей на 2 там добились более быстрого отображения шапки, но более медленного отображения основного контента, что довольно глупо.


        А если еще медиавыражения добавить

        А они зачем?