image

Модуль CSS Grid — это фантастический инструмент для создания макетов веб-сайтов. Он позволяет вам экспериментировать с макетами быстрее, чем любой другой инструмент, которые я пробовал.

В этой статье я научу вас, как это сделать.

Во-первых, я объясню HTML и CSS, которые нам нужны для этой задачи, которую я разбил на четыре части. Как только вы с этим разберетесь, мы перейдем к экспериментам с макетами.

Если вы совершенно не знакомы с CSS Grid, вам может понадобиться просмотреть мою предыдущую статью Учим CSS Grid за 5 минут.

Наш Grid


Мы собираемся начать с очень простой сетки, которая имитирует классический веб-сайт:

image

Я немного стилизовал наш пример, но это не имеет ничего общего с CSS Grid, поэтому я оставляю это.

1. Разметка


Первое, что нам нужно, это немного HTML. Контейнер (элемент который мы превратим в сетку) и элементы (хедер, меню, контент, футер).

<div class="container">
  <div class="header">HEADER</div>
  <div class="menu">MENU</div>
  <div class="content">CONTENT</div>
  <div class="footer">FOOTER</div>
</div>

2. Базовая настройка CSS


Затем нам нужно настроить нашу сетку и указать, сколько строк и столбцов нам нужно. Вот изначальный CSS для этого:

.container {
    display: grid;    
    grid-template-columns: repeat(12, 1fr);
    grid-template-rows: 50px 350px 50px;
    grid-gap: 5px;
}

Я собираюсь добавить еще, но сначала хочу, чтобы вы разобрались с этим.

Вот что говорит вышеприведенный код: создать сетку с двенадцатью столбцами, каждый шириной доли единицы (1/12 общей ширины). Создать три строки, где первая будет 50px высотой, вторая 350px и третья 50px. Наконец, добавить промежуток между элементами в сетке.

3. Добавление grid-template-areas


Функция, которая позволит нам легко экспериментировать с макетом, называется шаблоном.
Чтобы добавить его в Grid, мы просто дадим контейнеру свойство grid-template-areas. Синтаксис может быть немного странным, поскольку он отличается от любого другого синтаксиса CSS. Вот он:

.container {
    display: grid;
    grid-gap: 5px;    
    grid-template-columns: repeat(12, 1fr);
    grid-template-rows: 50px 350px 50px;
    grid-template-areas:
        "h h h h h h h h h h h h"
        "m m c c c c c c c c c c"
        "f f f f f f f f f f f f";
}

Логикой свойства grid-template-areas является то, что вы создаете визуальное представление вашей сетки в коде. Как видите, он имеет три строки и двенадцать столбцов, точно так же, как мы определили в grid-template-columns и grid-template-rows.

Каждая строка кода представляет строку в макете, и каждый из символов (h, m, c, f) представляет ячейку сетки.
Каждая из четырех букв теперь образует прямоугольную grid-area.

Как вы могли догадаться, я выбрал символы h, m, c, f, потому что наш Grid состоит из header, menu, content и footer. Разумеется, я мог бы назвать их так, как захочу, но имеет смысл использовать первый символ элементов, которые они описывают.

4. Предоставление областей для элементов


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

.header {
    grid-area: h;
}

.menu {
    grid-area: m;
}

.content {
    grid-area: c;
}

.footer {
   grid-area: f;
}

Вот что мы получим:

image

Эксперименты с макетом


Теперь мы наконец достигли красоты этой функции, так как мы можем легко экспериментировать с макетом. Это просто изменения положения символов в свойстве grid-template-areas. Давайте, например, переместим меню в правую сторону:

grid-template-areas:
        “h h h h h h h h h h h h”
        "c c c c c c c c c c m m”
        “f f f f f f f f f f f f”;

Вот такой результат получится в этом макете:

image

Мы можем использовать точки для создания пустых ячеек сетки.

grid-template-areas:
        “. h h h h h h h h h h .”
        "c c c c c c c c c c m m”
        “. f f f f f f f f f f .”;

Вот как это будет выглядеть:

image

Теперь я рекомендую вам посмотреть этот скринкаст моего курса CSS Grid, где вы сможете экспериментировать с кодом самостоятельно.

Добавление адаптивности


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

@media screen and (max-width: 640px) {
    .container {
        grid-template-areas:
            "m m m m m m h h h h h h"
            "c c c c c c c c c c c c"
            "f f f f f f f f f f f f";
    }
}

И это приведет к следующему:

image

Помните, что все эти изменения выполняются с помощью чистого CSS, не касаясь HTML. Мы можем перемещать элементы так, как мы хотим, независимо от того, как теги div находятся в разметке.
Это называется независимостью от источника, и это огромный шаг вперед для CSS.
Это позволяет HTML быть тем, для чего он был предназначен: разметка для контента. А не для стилизации, так как это работа CSS.

Доступ к бесплатному курсу CSS Grid от автора поста.
Превью курса.



Перевод выполнен при поддержке компании EDISON Software, которая профессионально занимается разработкой сайтов на Amiro.CMS и WordPress и для крупных заказчиков.

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


  1. maslyaev
    04.12.2017 08:41

    Синтаксис может быть немного странным
    Это не «странный синтаксис», а залёт. Такое ощущение, что тему css grid проектировал или ребёнок, или толстый тролль.


    1. Zenitchik
      04.12.2017 09:02

      Вы никогда на LaTeX не писали?


      1. maslyaev
        04.12.2017 10:32

        Господь миловал.


    1. izzholtik
      04.12.2017 10:43

      Фронтэнд исторически поражает синтаксисом, рассчитанным на слабоумных, и вырастающими из него тоннами сложностей и исключений. Это нормально.
      плачет


      1. izzholtik
        04.12.2017 10:48

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


        1. Athari
          06.12.2017 20:55

          BBcode — это извращение над HTML, которое не имеет права на существование. Он был придуман для того, чтобы "обезопасить" пользовательский ввод. Если хочется тегов, то в современном мире использовать не HTML (возможно, с дополнительными тегами) — это маразм.


          Кроме того, что HTML, что BBcode очень неприятно набирать в отличной от английской клавиатурной раскладке. Заставлять постоянно переключать раскладку — это издевательство над пользователем.


          И таки для markdown есть какой-никакой стандарт. Много где остаётся царское наследие, но в будущем всё должно свестись к CommonMark.


          И да, markdown включает подмножество HTML, поэтому, если так хочется хочется теги, всегда можно использовать их. На этом сайте даже галочка для отключения парсинга MD есть.


      1. maslyaev
        04.12.2017 12:05

        присоединяется


      1. mrsweet
        04.12.2017 12:15

        А почему вообще синтаксис должен быть сложным?


        1. izzholtik
          04.12.2017 12:41

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

          За примером далеко ходить не надо, из прошлой статьи цикла:

          .item1 {
              grid-column-start: 1;
              grid-column-end: 4;
          }


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


          1. vbif
            04.12.2017 12:51

            Зачем «держать в уме»? Достаточно понять принцип.


            1. izzholtik
              04.12.2017 12:53

              Это и есть заучивание странностей движка. Такой себе извращённый подвид перехода бага в фичу посредством документирования.


              1. vbif
                04.12.2017 12:57

                Где здесь странности? Как раз наоборот, если бы нумеровались колонки, а не границы, было бы сложнее понять принцип работы.


                1. izzholtik
                  04.12.2017 13:07

                  Зачем «понимать» очередной «принцип», если можно просто указывать начало и конец в том виде, в котором их понимает человек?


                  1. vbif
                    04.12.2017 13:10

                    В этом смысле Grid Layout сделан идеально.


                  1. bazil
                    04.12.2017 13:33

                    Спросите авторов, поинтересуйтесь зачем они так сделали. Хейтить всегда легко, использовать фразы "понимает человек". Зачем вы нам своё недовольство выливаете ?


                    1. izzholtik
                      04.12.2017 15:19

                      Потому что могу и потому, что это даже не оффтоп?)
                      Мне вообще больше нравится способ разметки из Java/Android, когда в сетках (GridLayout / GridBagLayout) элементам неединичной ширины задаются не начало и конец, а собственно ширина. Здесь же мы имеем гибрид этих двух подходов: простые элементы располагаются на сетке автоматически, а «широкие» приходится прибивать гвоздями к координатам. Хотя насчёт гвоздей могу ошибаться, пока ещё не сильно лапал эту фичу.


                  1. SelenIT3
                    04.12.2017 16:37

                    Не проблема — возьмите и укажите их в таком виде:). Грид-линиям можно давать произвольные имена. А если у вас есть именованные грид-области, то их начало и конец автоматически получают имена имя_области-start и имя_области-end. Куда уж еще понятнее? :)


                    1. izzholtik
                      04.12.2017 17:57

                      CSS is awesome :D


                      1. SelenIT3
                        04.12.2017 18:07

                        И сейчас, пожалуй, эту фразу впервые можно употреблять без иронии!


              1. Zenitchik
                04.12.2017 13:00

                Понимание принципа — это не заучивание.


          1. SelenIT3
            04.12.2017 16:47

            Не придется. Нумерация грид-линий — лишь один из over 9000 способов обратиться к ним. Выбирайте из всего многообразия то, что вам больше по душе (и по задаче:).


            Вообще когда-то было хорошее правило хотя бы бегло ознакомиться с предметом критики (скажем, пробежавшись по оглавлению спеки), прежде чем бросаться обвинять авторов в чем-либо. Например, прежде чем ругать конструкторов бензопилы за тяжелую и неудобную ручку «этой дурацкой ножовки», было бы неплохо выяснить, что бензопилу можно заправить и включить. Жалко, что в вебе это правило больше не работает...


            1. izzholtik
              04.12.2017 17:36
              +1

              Придётся. Потому что иначе они не смогут читать код людей, ипользующих этот способ. Это как ситуация с ++i: мало кто использует, но помнить приходится всем.


              1. Athari
                06.12.2017 21:00

                Я не понял, а что именно с ++i надо запоминать? Арифметические знаки, знаете, запоминать приходится. Ещё в школе заставляют.


        1. maslyaev
          04.12.2017 20:11

          Тут мы наблюдаем не сложность синтаксиса, а его хаотичность и дырявость. На первый взгляд (взгляд ребёнка или кого-нибудь падкого на вау-эффект) кажется всё предельно просто — берёшь и буковками рисуешь чё в результате хочешь увидеть. Красота. Но мы-то с вами знаем, что код совсем не обязательно пишется руками. Я бы даже сказал, что он чаще пишется алгоритмами, чем руками. А теперь представьте себе, какой это ад написать генератор страницы, который будет выписывать эти все «a a a» и «b b b». В зависимости от каких-нибудь опций, настроек, прав пользователя и чёрта лысого. По постановке задаче, уточняющейся пару раз в день.
          Протрахавшись неделю, разраб константой вклячит что-нибудь вроде такого:

          .container {
              grid-template-areas:
                  "j j j j o o o o p a a a"
                  "a a a a j o p a a a a a"
                  "j o p a j o p a j o p a";
          }
          и пойдёт напишет заявление по собственному. Ибо сколько можно издеваться над организмом?


          1. SelenIT3
            04.12.2017 20:52

            Вот только это не понадобится. Для автоматической генерации в гридах предусмотрены специально обученные инструменты, в частности, именованные линии с волшебными окончаниями -start и -end, которые достаточно один раз поставить в нужные места шаблона в grid-template-columns и -rows соотв-но. А «верстка ASCII-артом» из примера предназначена именно для быстрого набрасывания простого макета человеком (в т.ч. ребенком — почему нет?:).


            1. maslyaev
              04.12.2017 21:06

              Видел эти «start» и «end» в предыдущей статье цикла (которая «за 5 минут»). Это, конечно, менее вопиюще, но по своей сути столь же безумно. ИМХО, конечно.
              Я понимаю, фронтендеры через себя ещё и не такое пропускают, но, господа, это всё же ненормально. Берегите себя.


              1. SelenIT3
                04.12.2017 23:01
                +2

                Там были другие «start» и «end»:). Там были начало и конец элемента в координатах грида. Но можно задать начало и конец и области в самом гриде, не заполняя ее буквами, как здесь. Сила (но и сложность) гридов именно в наличии множества альтернативных записей для одного и того же действия, которые можно выбирать по задаче. Ну и даже самый извращенный из этих вариантов всяко здоровее, чем центрирование через margin:auto, clearfix-хаки и прочие давно привычные для верстальщиков штуковины:)


    1. kuftachev
      04.12.2017 14:20

      Не соглашусь. В этом примере выглядит все логично, достаточно красиво и компактно. Для того же Flex-Box будет больше кода. Вопрос в другом, как это все будет выглядеть в том случае, если будет не 4 элемента на страницу, а хотя бы 100? Как будут выглядеть вложености?

      Кстати, если там не одна буква для обозначения, то можно писать более полно, а для прода минифицировать…

      В общем, я хочу сказать, что есть много вопров, и что многие технологии красивы на уровне «Hello, world!», а потом превращаются в кашу.


      1. SelenIT3
        04.12.2017 17:01

        Для 100 элементов, скорее всего, лучше использовать как раз другие варианты разметки грида — не с именованными областями, а с repeat() и «массивами» именованных линий. Имхо, уж в чем-чем, а в недостатке гибкости синтаксиса CSS-гриды обвинить трудно:).


        Вот со вложенностями, увы, пока всё довольно грустно. В ранних черновиках были подсетки (subgrids), но с ними всплыло много сложностей в реализации, так что их отложили на 2-й уровень спеки. Частично проблему решает display:contents, но он пока работает без флагов только в Firefox и совсем недавно в WebKit (хотя в Хроме он тоже реализован и где-то в ближайшей паре-тройке релизов его должны вынести из-под флага, только Edge как обычно)...


  1. AxisPod
    04.12.2017 12:00

    Что толку экспереминтировать с grid, если нормально не поддерживается тем же IE? А если уж учесть, что якобы полностью поддерживается flex в IE и Safari, но при этом на деле это не так, а grid в IE поддерживается частично, потом так или иначе шаманить и фиксить непонятно откуда всплывшие баги?


    1. Zenitchik
      04.12.2017 12:47

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


    1. ZoomLS
      04.12.2017 13:56

      Не везде нужна поддержка IE.


    1. SelenIT3
      04.12.2017 16:33

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


      1. Akuma
        04.12.2017 17:18
        +1

        Как связаны прогрессивное улучшение и css-сетка?

        Вы можете прогрессивно улучшать, например, box-shadow. Когда он поддерживается — тень есть, когда не поддерживается — да и хрен с ней с тенью. Вот это вот стоит делать.

        А верстать сначала на float:left; а затем то же самое (на 100% совпадающее, иначе никак это ж верстка) на гридах… зачем? Не делайте одно и то же два раза ради… да я даже не знаю ради чего. Просто не делайте так.

        Либо grid, либо float. Не мешайте их.


        1. SelenIT3
          04.12.2017 17:43

          на 100% совпадающее, иначе никак это ж верстка

          Это заблуждение родом из 90-х. Современная вёрстка фактически по определению адаптивная. И в число параметров, к которым можно и нужно адаптироваться, входит не только ширина окна браузера, но и возможности клиентского окружения. Для этого придумали целую директиву supports.


          Пользователи хороших браузеров не должны страдать из-за того, что старые браузеры просто существуют! Ну а что верстальщикам придется написать на 5-10 строк кода больше — ну так это их работа, им за это платят:)


          одно и то же два раза ради… да я даже не знаю ради чего.

          Так узнайте. И делайте так:). Ради удобства пользователей — в конце концов, вы ведь для них стараетесь.


          1. Akuma
            04.12.2017 17:46

            with simple fallbacks for non-supporting browsers

            Перевестать все и вся на float — это не simple fallback. Вот в этом основная проблема.

            Я не спорю, что могут быть ситуации, когда можно сделать простой фалбек или вовсе оставить «как получится» на флоатах и «красиво» на гридах. Но в реалиях будет примерно так:

            1. style.css
            2. style-grid.css

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


            1. SelenIT3
              04.12.2017 18:00

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


              Но не делать хорошо там, где можно, только потому, что настолько хорошо можно сделать не везде — не дело. Это не техническое обоснование, это верстальщицкая лень. Которая дает лишь небольшой сиюминутный тактический выигрыш (больше заработать методом «тяп-ляп и в продакшн», дольше побухать:), но стратегически от нее одни минусы (у конкурентов сайты будут быстрее, красивее и надежнее, можно упустить момент и оказаться морально устаревшим, как верстальщики на таблицах в конце 2000-х:). Конечно, во всём нужен разумный баланс, но просто так поощрять лень не надо:)


              1. Akuma
                04.12.2017 18:03

                Воу, я вроде бы ничего не говорил про «тяп-ляп и в продакшн» :)


                1. SelenIT3
                  04.12.2017 18:06

                  А для чего еще может понадобиться экономить время на том, чтобы сделать хорошо, надежно и современно? :)


                  1. Akuma
                    04.12.2017 18:11

                    Например, чтобы сделать просто «хорошо и надежно».
                    «Современно» в вебе это не всегда хорошо и надежно, к сожалению.

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


                    1. SelenIT3
                      04.12.2017 18:17

                      «Современно» в вебе это не всегда хорошо и надежно, к сожалению.

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


                      «менее красивые» фалбеки для небольших кусочков верстки

                      Именно так!


                      1. Akuma
                        04.12.2017 18:18

                        Смотря для каких участков страницы :)

                        Сложная сетка — да, почему бы и не гриды.
                        Просто блоки 3х33%? Поставьте флоаты и не мучайте мой ИЕ 8 :)


                        1. SelenIT3
                          04.12.2017 18:22

                          Для IE8 по-любому будут флоаты или инлайн-блоки, он другому не обучен.


                          Но зачем мучить флоатами и инлайн-блоками (требующими reflow с repaint-ом чуть ли не всего body при появлении в любом из элементиков малейшего намека на динамику, т.к. они зависят друг от друга, как падающие костяшки домино) мой Хром, когда можно дописать 3-5 строчек CSS и обеспечить его железобетонной сеткой на гридах? :)


                          1. Akuma
                            04.12.2017 18:23

                            Потому что на 99% сайтах никто, включая вас не заметит разницы в скорости? :)


          1. Akuma
            04.12.2017 17:49

            Я это не из головы беру. Во времена, когда не поддерживался border-radius многие делали так же:

            Отдельный код для «уголков картинками» и отдельный с border-radius. И когда вся страница в этих уголках, там получается такая ядреная смесь, что пипец просто.

            Так критичны уголки? Оставьте все на картинках и не мучайтесь.

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

            Да, кстати. caniuse.com/#search=supports
            Отличный вариант для фаллбека на IE :)


            1. SelenIT3
              04.12.2017 18:04

              Именно что отличный. Браузеры, не понимающие supports (в т.ч. IE) просто проигнорят всё, что внутри него.


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


  1. SelenIT3
    04.12.2017 17:42

    [упс, мимо]


  1. iGetPass
    04.12.2017 18:21

    Верстка только на дивах — зло. Спецификация html5 добавила много президент рамных тегов, которые помогают в чтении кода, сео и доступности для скрин ридеров


    1. splav_asv
      04.12.2017 21:55

      президент рамных

      Переведите пожалуйста, если не затруднит.


      1. SelenIT3
        06.12.2017 10:35

        Я вот тоже подзавис над этим шедевром автозамены. По буквам вроде бы подходит «презентационных», но ведь по смыслу подразумевалось как раз противоположное..:)


  1. iGetPass
    04.12.2017 21:57

    Спасибо, за комент. Различных тегов


  1. mSnus
    05.12.2017 00:12

    Какой же ад будет поддерживать сайты с этой сеткой, float-ами и flexbox вперемешку… "… я поставил компонент 'Позвоните нам' и у меня что-то меню пропало.."


    1. vbif
      05.12.2017 18:18

      Ну так и не надо ставить какие попало компоненты.


    1. SelenIT3
      05.12.2017 21:58
      +1

      В рамках одного контейнера «перемешки» быть не может — все три штуки взаимоисключающие. И grid, и flex отменяют действие float для потомков (удобно для фолбэков!), а из них двоих применяется то, что объявлено позже. Только с position:absolute могут быть нюансы, но абсолют — он и в Афри гридах абсолют.


      А компоненты из разных контейнеров друг другу мешать не должны. И если всё-таки мешают — проблема ну явно не в гридах:)