Рубріки: Front-endТеория

Grid в CSS: полное руководство и справочник по верстке

Сергій Бондаренко

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

Интересно? Тогда начнем.

Что такое Grid в CSS

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

Например, сайт может состоять из бокового блока, футера, контентной части и иметь шапку (header):

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

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

Для настройки расположения элементов сайта используется условная решетка (сетка), которая называется grid. Блоки сайта выстраивают с привязкой к grid-макету, который выглядит как массив ячеек внутри сетки.

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

Используя верстку по сетке (grid) разработчики могут легко управлять размером, позиционированием и порядком слоев страницы.

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

Принцип работы Grid в CSS

Одно из фундаментальных понятий в верстке — это Grid Layout, или макет сетки. На слэнге верстальщики часто называют их просто «гридами».

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

Адаптивный веб-дизайн — это дизайн, который обеспечивает корректное отображение содержимого сайта вне зависимости от размера окна браузера.

Grid Layouts напоминают таблицы, но с помощью них проще работать с веб-примитивами.

Например, благодаря им, дочерние элементы grid-контейнера могут наслаиваться один на другой.

Создадим макет веб-страницы с простой базовой разметкой, и на его примере рассмотрим свойства Grid Layout.

Создаем шаблон сайта с CSS Grid

В файле с html-разметкой добавим блок <div> с классом box и поместим в него 16 элементов <div> с классом item. Внутри каждого элемента поместим разное количество текста — от одного слова до пяти — это необходимо для наглядности примера. 

<!DOCTYPE html>
<html lang="en">
<head>
        <title>Document</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="css/style.css" >
</head>
<body>
    <div class="box">
        <div class="item">Highload</div>
        <div class="item">Highload, today</div>
        <div class="item">Highload, today dolor</div>
        <div class="item">Highload today dolor sit omet</div>
        <div class="item">Highload</div>
        <div class="item">Highload, today</div>
        <div class="item">Highload, today dolor</div>
        <div class="item">Highload today dolor sit omet</div>
        <div class="item">Highload</div>
        <div class="item">Highload, today</div>
        <div class="item">Highload, today dolor</div>
        <div class="item">Highload today dolor sit omet</div>
        <div class="item">Highload</div>
        <div class="item">Highload, today</div>
        <div class="item">Highload, today dolor</div>
        <div class="item">Highload today dolor sit omet</div>
    </div>
</body>
</html>

Далее переходим в файл CSS и зададим некоторые параметры наших элементов:

body{
    padding: 50px 100px;
    font-family: sans-serif;
    font-size: 22px;
    font-weight: bold;
}
.item{
    border: 2px solid rgb(77, 77, 77);
    background-color: rgb(9, 188, 131);
    color: rgb(255, 255, 255);
}

Вот что выведет такой код:

Для того, чтобы обозначить родительский элемент box как часть grid-макета, мы должны установить в свойствах CSS display: grid;. После того, как мы это сделаем, визуально ничего не поменяется, но свойства элементов будут другими, потому что теперь мы работаем с грид-разметкой.

Чтобы управлять разметкой, нужно задать ее параметры:

  • число столбцов и строк;
  • их размеры.

Для описания колонок в Grid Layout используется команда grid-template-columns:.

Предположим, нам необходимо задать две колонки, шириной 200 и 300 пикселей соответственно. Для этого пишем такой CSS-код:

.box{
    display: grid;
    grid-template-columns: 200px 300px ;
}

Так как мы указали два значения (200px и 300px), мы получили две колонки:

Укажи мы три значения, мы бы получили три колонки, четыре значения — четыре, и т. д.

Значения, описывающие размеры могут быть указаны в любых единицах размерности, что используется в CSS:

  • px;
  • vh;
  • rem;
  • %.

Например, если дополнительно указать 15%, мы получим третью колонку, ширина которой будет автоматически определена как пятнадцать процентов от ширины элемента box:

.box{
    display: grid;
    grid-template-columns: 200px 300px 15% ;
}

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

.box{
    display: grid;
    grid-template-columns: 200px 300px 15% auto ;
}

Теперь на макете у нас есть четыре колонки:

  • первая шириной 200 пикселей;
  • вторая — 300 пикселей;
  • третья займет 15 процентов от ширины box;
  • а четвертая — заполнит оставшееся место:

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

Но почему так?

Дело в том, что ширина колонки с параметром auto рассчитывается в зависимости от количества контента, который ее заполняет. Поэтому, если указать этот параметр для нашего случая, все столбцы получатся разного размера.

CSS Grid выравнивание

Чтобы указать равные размеры элементов сетки, используйте специальную единицу измерения — фракцию (fr).

Например, если нужно указать соотношение ширин колонок как одна часть, одна часть, одна часть и одна часть, мы указываем:

.box{
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr;
}

Результат исполнения этого кода:

Когда нужно сделать много колонок, использовать фракции неудобно. В такой ситуации применяют функцию repeat. Ее аргументы показывают сколько раз нужно повторить колонку и в какой пропорции.

//например, вместо того, чтобы писать в свойствах 
    grid-template-columns: 1fr 1fr 1fr 1fr;
//можно указать
    grid-template-columns: repeat( 6, 1fr );

Результат будет тот же самый:

Размерности для repeat можно применять любые. Например, указать их в пикселях:

.box{
    display: grid;
    grid-template-columns: repeat( 3, 400px );
}

Результат:

Работа со строками в Grid

Похожее по смыслу свойство есть и для строк. Оно называется grid-template-rows.

Настройки этого свойства идентичны настройкам параметра grid-template-columns Здесь тоже можно использовать любые размерности для указания высоты строк (проценты, пиксели, фракции и т.д), а также применять repeat для быстрого описания свойств групп строк.

Укажем в стилях следующие параметры:

.box{
    display: grid;
    grid-template-columns: repeat( 3, 400px );
    grid-template-rows: 100px 300px 150px;
}

И получим такой макет для верстки:

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

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

Gap в Grid CSS

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

.box{
    display: grid;
    grid-template-columns: repeat( 3, 400px );
    grid-template-rows: 100px 200px 150px;
    column-gap: 20px; // Для отступа между колонками
    row-gap: 40px; //Для отступа между рядами
}

Результат исполнения кода:

Обратите внимание, что справа и слева никаких полей отступа не добавилось, а ячейки оказались «прижаты» к своему родительскому контейнеру. Чтобы это исправить, вместо column-gap и row-gap можно использовать другую запись, объединяющую оба свойства:

gap: 35px 15px; // Первый аргумент — отступ между строками, второй — расстояние между колонками

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

Если нужно только одно значение, напротив ненужного отступа можно просто поставить 0 (gap: 0 15px;):

Если указать только одно значение, например, gap: 20px;, то отступ будет автоматически назначен как для расстояния между строками, так и для отступа между колонками:

Задание собственных свойств для grid-элементов

По умолчанию, прописанные свойства применяются к Grid-контейнеру, то есть родительскому контейнеру box, внутри которого размещены grid-элементы — items. Назначаемые свойства автоматически распределяются между элементами Grid-контейнера. Однако, для grid-элементов существует возможность назначать свои собственные свойства.

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

<div class="box">
        <div class="item item-1">Highload</div>
        <div class="item">Highload, today</div>
        <div class="item">Highload, today dolor</div>
        <div class="item">Highload today dolor sit omet</div>
        <div class="item">Highload</div>
        <div class="item">Highload, today</div>
        <div class="item">Highload, today dolor</div>
        <div class="item">Highload today dolor sit omet</div>
        <div class="item">Highload</div>
        <div class="item">Highload, today</div>
        <div class="item">Highload, today dolor</div>
        <div class="item">Highload today dolor sit omet</div>
        <div class="item">Highload</div>
        <div class="item">Highload, today</div>
        <div class="item">Highload, today dolor</div>
        <div class="item">Highload today dolor sit omet</div>
    </div>

Теперь в файле CSS в соответствующем разделе укажем его новые свойства:

.item-1{
    grid-column-start: span 2; //число указывает на количество занимаемых ячеек
}

Элемент займет первые две ячейки в ряду:

Если нужно, чтобы элемент занял также две ячейки в столбцах, используем свойство grid-row-start: span 2;.

Span в этом случае означает, что элемент должен увеличиться на две части с того места, где он стоял.

Расстановка grid-элементов по координатам

При работе с CSS модулем раскладки Flexible Box (или попросту флексбоксом) построение элементов происходит относительно главной оси и поперечной оси. В этом случае тоже задействуется технология верстки Grid Layouts, поэтому построение выполняется относительно grid-линий.

Хотя эти линии мы не видим, мы можем их отобразить в инструментах для разработчика. Для этого перейдите в просмотр структуры HTML-кода, найдите кнопку grid в родительском элементе div класса box, а затем нажмите на нее:

Направляющие верстки (гриды) станут видны:

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

Например, если указать для элемента item-1 такие свойства, наша ячейка также займет место от первой grid-линии до третьей:

.item-1{
    grid-column-start: 1;
    grid-column-end: 3;
}


Такой же результат мы бы получили, если бы указали такие свойства:

.item-1{
    grid-column-start: span 2;
}

Но указывать «координаты» ячейки не рекомендуется, потому что так мы можем ее сместить. Лучше определить ее положение со второй линии по четвертую:

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

Таким же способом можно управлять и числом занимаемых ячеек по вертикали, используя свойства grid-row-start и grid-row-end:

Обратите внимание: несмотря на то, что ячейка сдвинулась вправо, в разметке она по-прежнему стоит первой.

Если вам необходимо уточнить положение ячейки по координатам, используйте grid-row-start и grid-row-end. Если необходимо указать положение без привязки к координатам — используйте span.

Перечислять значения этих свойств удобнее всего через слэш:

.item-1{
    grid-column: 2/4;  
    grid-row: 1/3;
}

В обоих случаях первая цифра соответствует параметру start, а вторая — end.

Результат будет тот же:

Также можно комбинировать аргументы свойств, совмещая их со span:

.item-1{
    grid-column: 2/4;  
    grid-row: 2/ span 2;
}

Обратный отсчет в Grid CSS

Если обратите внимание на нумерацию grid-линий, вы увидете, что помимо «понятных» номеров (1, 2, 3…), в Grid Layouts используется также обратный отсчет. В этой системе последняя вертикальная линия — это −1, предпоследняя — −2 и т.д. Аналогичный обратный отсчет  идет и для горизонтальных рядов.

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

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

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

.item-1{
    grid-column: 1/-1;  
    grid-row: 2/span 2;
}

Результат исполнения кода:

Явные и неявные гриды

Число линий может не совпадать с реальным числом промежутков между ячейками. Это объясняется тем, то grid-линии бывают двух типов: явные и неявные.

Например, если мы указали в CSS-коде grid-template-rows: 100px 200px 150px;, то для указанных строк будет построены явные гриды. Вокруг остальных элементов гриды будут отображаться как неявные — они будут не видны.

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

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

Например, если мы используем для названий линий имена [one], [two], [griditem3] и [item4], то при исполнении такого кода ячейка займет место между первой и третьей вертикальной линией:

.box{
    display: grid;
    grid-template-columns: [one] 400px [two] 400px [griditem3] 400px [item4];
    grid-template-rows: 100px 200px 150px;
    gap: 20px;
}
.item-1{
    grid-column: one/griditem3;  
    grid-row: 2/span 2;
} 

Использование свойств при работе с неявными гридами

Создадим новый блок div с классом wrapper, а также четыре элемента:

  • класс header;
  • класс main;
  • класс aside;
  • и класс footer.
<div class="wrapper">
    <header class="header element">header</header>
    <main class="main element">main</main>
    <aside class="aside element">aside</aside>
    <footer class="footer element">footer</footer>
</div>

grid-template-areas

В файле с CSS-стилями укажем новое свойство — grid-template-areas. Это свойство описывает структуру сетки с помощью именованных областей. Оно позволяет задавать имена для областей, которые будут занимать элементы на сетке, и затем располагать элементы в соответствии с этими именами.

.wrapper{
    display: grid;
    grid-template-areas:
    "header header header"
    "main main aside"
    "footer footer footer" ;
}
.element{
    border: 1px solid#000;
    height: 200px;
}
.header{
    grid-area: header;
}
.main{
    grid-area: main;
}
.aside{
    grid-area: aside;
}
.footer{
    grid-area: footer;
}

В этом примере мы указываем, что:

  • header занимает три части;
  • main — две части;
  • одну часть занимает aside;
  • а три части занимает footer.

Получился такой прямоугольник:

Названия в grid-template-areas никак не связаны с названиями классов. Там можно записать любое слово, например:

.wrapper{
    display: grid;
    grid-template-areas:
    "text text text"
    "main main aside"
    "footer footer footer" ;
}
.header{
    grid-area: text;
}

Результат будет тем же. 

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

.wrapper{
    display: grid;
    grid-template-rows: repeat(3, 200px);
    grid-template-areas:
    "text text text"
    "main main aside"
    "footer footer aside" ;
}
.element{
    border: 1px solid#000;
}
.header{
    grid-area: text;
}
.main{
    grid-area: main;
}
.aside{
    grid-area: aside;
}
.footer{
    grid-area: footer;
}

grid-auto-rows и grid-auto-column

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

Мы не можем просто удалить в grid-template-areas просто одно main, потому что тогда шаблон поломается и область main разделит доступное пространство с областью aside. Вместо этого, чтобы обозначить пустую ячейку, в свойствах шаблона нужно указать просто точку:

.wrapper{
    display: grid;
    grid-template-rows: repeat(3, 200px);
    grid-template-areas:
    "text text text"
    "main . aside"
    "footer footer aside" ;
}

Вместо второго блока main образовалась пустота, обозначенная в коде точкой:

Как уже говорилось выше, в grid-макете могут присутствовать явные колонки и ряды, а также неявные колонки и ряды. В текущем проекте, явные ряды заданы с высотами 100px, 200px и 150px.

.box{
    display: grid;
    grid-template-columns: [one] 400px [two] 400px [griditem3] 400px [item4];
    grid-template-rows: 100px 200px 150px;
    gap: 20px;
}

Остальные ряды — неявные и у них отсутствует высота. Как ее указать?

Можно прописать в grid-template-rows все оставшиеся высоты, но это не решит проблему. В шаблоне могут вноситься изменения (вручную или по мере добавления контента), поэтому неизвестно, сколько ячеек будет существовать в конечном варианте и сразу прописать высоты всех ячеек невозможно.

Поэтому для решения проблемы используют свойство grid-auto-rows, которое назначает высоты всем неявным рядам. Укажем таким ячейкам высоту в 125px:

.box{
    display: grid;
    grid-template-columns: [one] 400px [two] 400px [griditem3] 400px [item4];
    grid-template-rows: 100px 200px 150px;
    grid-auto-rows: 125px;
    gap: 20px;
}

Теперь все неявные ряды будут получать высоту 125px:

В аргументах свойства grid-auto-rows можно задавать несколько значений, описывая очередность высот ячеек, что будут появляться.

Например, если указать grid-auto-rows: 125px 225px;, то при таких параметрах мы получим макет, где:

  • первый ряд занимает 100px;
  • второй ряд — 200px;
  • третий ряд — 150px;
  • четвертый ряд — 125px;
  • пятый ряд — 225px;
  • шестой — 125px;
  • седьмой — 225px.

Восьмой снова получит значение 125px, а дальше цифры будет повторться согласно значениям высот, указанных в grid-auto-rows.

По мере добавления контента на страницу сайта, число блоков может постепенно расти. Добавляемые в разметку ячейки каждый раз генерируют новые строки. Такое поведение объясняется свойством grid-auto-flow, которое по умолчанию принимает значение row. Если его изменить на column, то новые ячейки будут генерироваться сбоку от основной разметки, создавая новые колонки:

Чтобы управлять шириной таких ячеек, используйте свойство grid-auto-column. Указав grid-auto-columns: 300px;, мы получим ширину всей ячеек с неявными линиями равную 300px:

Аналогично тому, как это было в случае с параметрами grid-auto-rows, несколько записанных чисел обозначают чередующиеся значения ширин ячеек. Для grid-auto-columns: 300px 150px; имеем следующий вид размещения ячеек:

Свойство grid-auto-flow имеет еще одно значение — dense.

Предположим, в макете верстки ячейки размещаются таким образом:

  • для второго элемента указано, что он должен занимать две ячейки;
  • а седьмой элемент должен располагаться между второй и четвертой грид-линиями.

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

<body>
    <div class="box">
        <div class="item item-1">Highload</div>
        <div class="item item-2">Highload, today</div>
        <div class="item">Highload, today dolor</div>
        <div class="item">Highload today dolor sit omet</div>
        <div class="item">Highload</div>
        <div class="item">Highload, today</div>
        <div class="item item-7">Highload, today dolor</div>
        <div class="item">Highload today dolor sit omet</div>
        <div class="item">Highload</div>
        <div class="item">Highload, today</div>
        <div class="item">Highload, today dolor</div>
        <div class="item">Highload today dolor sit omet</div>
        <div class="item">Highload</div>
        <div class="item">Highload, today</div>
        <div class="item">Highload, today dolor</div>
        <div class="item">Highload today dolor sit omet</div>
    </div>
</body>
body{
    padding: 50px 100px;
    font-family: sans-serif;
    font-size: 22px;
    font-weight: bold;
}
.item{
    border: 2px solid rgb(77, 77, 77);
    background-color: rgb(9, 188, 131);
    color: rgb(255, 255, 255);
    padding: 15px;
}

.box{
    display: grid;
    grid-template-columns: [one] 400px [two] 400px [griditem3] 400px [item4];
    grid-template-rows: 100px 200px 150px;
        /* grid-auto-flow: rows; */    gap: 20px;
}
.item-1{
    grid-column: one/griditem3;  
    grid-row: 1/ span 2;
}
.item-2{
    grid-column: span 2;

}
.item-7{
    grid-column: 2/4;
}

Добавление нового свойства в грид-контейнер решает эту проблему:

.box{
    display: grid;
    grid-template-columns: [one] 400px [two] 400px [griditem3] 400px [item4];
    grid-template-rows: 100px 200px 150px;
    grid-auto-flow: dense;
    gap: 20px;
}

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

Тем не менее, если необходимо сохранить «классическую» последовательность размещения элементов, для свойства grid-auto-flow нужно использовать либо значение row, либо column.

По умолчанию свойство работает с grid-auto-flow: rows. Если нужно, чтобы авторазмещение ячеек работало по столбцам, укажите два значения: grid-auto-flow: column dense;:

В процессе верстки часто используется значение minmax, которое применяется для задания размера колонки в сетке (grid) в зависимости от доступного пространства на странице.

Это значение свойства grid-template-columns позволяет указать минимальный и максимальный размер колонки. При его использовании, браузер будет выбирать размер колонки между этими значениями в зависимости от доступного пространства.

.box{
    display: grid;
    grid-template-columns: 400px 400px 400px;
    grid-template-rows: 100px 200px 150px;
    grid-auto-columns: 300px;
    grid-auto-flow: dense ;
    gap: 20px;
}
.item-1{
    grid-column: 1 / 3;  
    grid-row: 1 / span 2;
}
.item-2{
    grid-column: span 2;
}
.item-7{
    grid-column: 2/4;
}

Добавляем в свойства контейнера grid-template-columns: 400px 400px 400px minmax(200px, 500px);. Эта запись означает, что четвертая ячейка должна втискиваться в 200px, если в грид-контейнере мало места, или растягиваться до 500px, если места достаточно.

justify-items

Следующее свойство, которое обязательно пригодится при работе над макетом — justify-items. Оно применяется к родительскому элементу, который является контейнером для дочерних элементов, и может использоваться совместно с другими свойствами для управления расположением элементов внутри контейнера.

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

.box{
    display: grid;
    grid-template-columns: 400px 400px 400px minmax(200px, 500px);
    grid-template-rows: 100px 200px 150px;
    grid-auto-columns: 300px;
    grid-auto-flow: dense ;
    justify-items: center;
    gap: 20px;
}

Например, если указать для этого свойства значение center, ячейки примут следующий вид:

Всего доступно пять вариантов значений свойства justify-items:

 1. center

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

2. start

Выравнивает содержимое элемента к началу главной оси контейнера.

3. end

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

4. stretch

Содержимое элемента растягивается вдоль главной оси контейнера.

5. baseline

Выравнивает содержимое элемента по базовой линии главной оси контейнера.

Аналогично работает свойство align-items, которое также выравнивает элементы макета по вертикальной оси внутри контейнера. Указав для свойства align-items: center;, получим следующую картину размещения элементов:

.box{
    display: grid;
    grid-template-columns: 400px 400px 400px ;
    grid-template-rows: 100px 200px 150px;
    grid-auto-columns: 300px;
    grid-auto-flow: dense ;
    justify-items: start;
    align-items: center;
    gap: 20px;
}

justify-self

Нередко нужно обратиться к какой-то конкретной ячейке, например, седьмой. В этом случае нужно использовать не justify-items, а justify-self.

Для нашего макета размещение седьмой ячейки со значением center будет выглядеть так:

.box{
    display: grid;
    grid-template-columns: 400px 400px 400px ;
    grid-template-rows: 100px 200px 150px;
    grid-auto-columns: 300px;
    grid-auto-flow: dense ;
    gap: 20px;
}
.item-1{
    grid-column: 1 / 3;  
    grid-row: 1 / span 2;
}
.item-2{
    grid-column: span 2;

}
.item-7{
    grid-column: 2/4;
    justify-self: center;
}

align-self

Свойство align-self позволяет задать выравнивание для каждого отдельного элемента сетки, а не для всей сетки целиком. Так, если используя селектор первой ячейки, указать значение end, первый элемент выравнивается по нижнему краю:

.item-1{
    grid-column: 1 / 3;  
    grid-row: 1 / span 2;
    align-self: end;
}

Изменив значение на align-self: baseline;, мы увидим, как содержимое ячейки «подпрыгнуло», то есть было вертикально выровнено внутри ячейки относительно базовой линии строки:

Shortcuts — упрощенное написание свойств

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

Вместо стандартного описания свойств:

.box{
    display: grid;
    grid-template-columns: 400px 400px 400px ;
    grid-template-rows: 100px 200px 150px;
    grid-auto-columns: 300px;
    grid-auto-flow: dense ;
    gap: 20px;
}

Можно указать сокращенную форму команд:

.box{
    display: grid;
    grid-template: 100px 200px 150px / 400px 400px 400px; 
    grid-auto-columns: 300px;
    grid-auto-flow: dense ;
    gap: 20px;
}

Причем, до знака / в свойстве grid-template, указываются значения для строк (grid-template-rows), а после него — значения для колонок (grid-template-columns).

Аналогичным образом, значения свойств align-items: center и justify-items: center можно заменить на более лаконичную запись place-items: center. При этом в инструментах разработчика свойства align-items: center и justify-items: center будут отображаться для наглядности:

Если требуется разделить значения для align-items и justify-items, их также нужно записывать через пробел. Например, place-items: end start говорит о том, что подразумевались значения свойств align-items: end;и justify-items: start;.

Еще одно сильное сокращение задействуется с помощью свойства grid. В значениях этого шортката можно указать параметры:

  • grid-template-rows;
  • grid-template-columns;
  • grid-template-areas;
  • grid-auto-flow;
  • grid-auto-rows;
  • и grid-auto-columns.

Но применять такое сокращение не рационально, потому что оно визуально слишком длинное и, если над проектом работает несколько человек, есть риск, что не все поймут эту запись.

Что лучше: Flexbox или Grid?

Так как верстальщики часто используют также технологию Flexbox, у начинающих вебмастеров часто возникает вопрос: когда применять Grid-верстку, а когда — Flexbox?

Универсального ответа на этот вопрос нет — понимание этих инструментов приходит с практикой. Тем не менее, ряд закономерностей все же можно вывести. Делая выбор в пользу одной из технологий, вы должны ответить для себя на два вопроса:

  1. Как располагаются элементы — по одной оси или вдоль двух осей одновременно? Если в проекте используется одна ось (X или Y), то с высокой долей вероятности следует выбирать Flexbox. Если в макете используется сетка, где элементы должны выстраиваться по разным осям, то скорее всего стоит использовать Grid.
  2. Относится ли эта стилизация к какой-либо структуре? Если да — используйте Grid. Верстка по гридам применяется для создания более сложных, двухмерных макетов, с разными ячейками, произвольного размера и формы.
    Задействуя технологию Grid, можно управлять расположением элементов в обоих направлениях, как по горизонтали, так и по вертикали, а также контролировать расстояния между элементами.

Также не забывайте, что технологию верстки по гридам можно легко совмещать с Flexbox, так что делать однозначный выбор необязательно.

Преимущества технологии Grid в CSS

Мы уже рассмотрели много примеров, так что можем подвести промежуточные итоги.

Верстка с использованием гридов — это удобно, понятно и быстро. Макеты на гридах наглядны, поэтому веб-разработчикам удобно дорабатывать такие проекты, вносить в них изменения. Так что можно выделить пять основных преимуществ данной технологии:

  1. Простота и понятность разметки. Grid разбивает контент на ряды и столбцы, что упрощает разметку веб-страниц и позволяет легко позиционировать элементы на макете.
  2. Адаптивность. Grid помогает создавать гибкие макеты, которые могут легко адаптироваться к разным экранам и устройствам.
  3. Гибкость и контроль. Grid предоставляет разработчикам удобные инструменты, с помощью которых можно контролировать размещением элементов на странице. Он позволяет создавать сложные макеты с различными зазорами, выравниванием и расположением элементов.
  4. Меньше кода. Grid позволяет сократить количество CSS-кода, необходимого для создания сложных макетов. Вместо того, чтобы задействовать большое число классов и стилей для размещения элементов, можно использовать всего несколько правил Grid.
  5. Поддержка браузеров. Grid поддерживается большинством современных браузеров, включая Chrome, Firefox, Safari и Edge.

Адаптивная верстка Grid на примере

Рассмотрим реальный проект — создадим адаптивную верстку главной страницы для веб-магазина, где элементами макета выступают карточки с товаром (Products) и баннеры (Sale).

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

Сделаем базовую разметку и добавим блоки div с классом cards Grid будет оберткой, определяющей основную сетку.

<div class="cards-grid">
    <div class="card-demo sale-1">Sale 1</div>
    <div class="card-demo sale-2">Sale 2</div>
    <div class="card-demo product-1">Product 1</div>
    <div class="card-demo product-2">Product 2</div>

    <div class="card-demo sale-3">Sale 3</div>
    <div class="card-demo sale-4">Sale 4</div>
    <div class="card-demo product-3">Product 3</div>
    <div class="card-demo product-4">Product 4</div>
</div>

Разметка содержит:

  • два баннера Sale 1 и Sale 2;
  • два продукта Product 1 и Product 2;
  • еще два баннера Sale 3 и Sale 4;
  • и еще два продукта Product 3 и Product 4.

Создадим CSS-файл и начнем работу над разметкой.

Чтобы все аккуратно смотрелось, укажем отступы между ячейками в 20px и создадим четыре колонки с шириной каждой по 260px. Пока ряды определим неявно — их число будет неограничено, но высота каждого ряда будет по 180px.

.cards-grid {
    display: grid;
    gap: 20px;
    grid-template-columns: repeat(4,260px);
    grid-template-rows: repeat(4,180px);
}   

Мы создали базовую сетку четыре на четыре:

Используем свойство grid-template-areas, чтобы описать шаблон наших элементов и добавим для наглядности фон к ячейкам:

.card-demo{
    background-color: rgb(154, 200, 251);
}
.cards-grid {
    display: grid;
    gap: 20px;
    grid-template-columns: repeat(4,260px);
    grid-template-rows: repeat(4,180px);
    grid-template-areas: 
    'wide1 wide1 product1 product2'
    'wide2 wide2 product1 product2'
    'product3 product4 wide3 wide3'
    'product3 product4 wide4 wide4';
}

Растянем первую ячейку на две, добавив в CSS-файл такой код: 

.sale-1{
    grid-area: wide1;
}

Результат:

После того, как мы укажем все области, добавляем свойства:

.card-demo{
    background-color: rgb(154, 200, 251);
}
.cards-grid {
    display: grid;
    gap: 20px;
    grid-template-columns: repeat(4,260px);
    grid-template-rows: repeat(4,180px);
    grid-template-areas: 
    'wide1 wide1 product1 product2'
    'wide2 wide2 product1 product2'
    'product3 product4 wide3 wide3'
    'product3 product4 wide4 wide4';
}
.sale-1 { grid-area: wide1;}
.sale-2 { grid-area: wide2;}
.product-1 { grid-area: product1; }
.product-2 { grid-area: product2; }

.product-3{grid-area: product3;}
.product-4{grid-area: product4;}
.sale-3 {grid-area: wide3;}
.sale-4{grid-area: wide4;}

Такой Grid-макет будет содержать элементы с ячейками, расставленные в нужном нам порядке и на желаемых областях:

Поскольку мы позиционируем элементы, обращаясь к классам, мы можем в родительском блоке поменять очередность элементов — на грид-макет это никак не повлияет:

<div class="cards-grid">
    <div class="card-demo sale-1">Sale 1</div>
    <div class="card-demo sale-2">Sale 2</div>
    <div class="card-demo sale-3">Sale 3</div>
    <div class="card-demo sale-4">Sale 4</div>

    <div class="card-demo product-1">Product 1</div>
    <div class="card-demo product-2">Product 2</div>
    <div class="card-demo product-3">Product 3</div>
    <div class="card-demo product-4">Product 4</div>
</div> 

Но у нас осталась проблема адаптивности верстки. Дело в том, что по мере наполнения сайта товарами, число ячеек будет расти.

Чтобы подготовить макет, укажем через свойство grid-auto-rows неявные ряды. Когда в макете страницы будут добавляться новые ряды, они будут приобретать высоту, которую вы укажем в значении данного свойства.

Добавим в разметку новые товары:

<div class="cards-grid">
    <div class="card-demo sale-1">Sale 1</div>
    <div class="card-demo sale-2">Sale 2</div>
    <div class="card-demo sale-3">Sale 3</div>
    <div class="card-demo sale-4">Sale 4</div>

    <div class="card-demo product-1">Product 1</div>
    <div class="card-demo product-2">Product 2</div>
    <div class="card-demo product-3">Product 3</div>
    <div class="card-demo product-4">Product 4</div>
    <div class="card-demo ">Product 5</div>
    <div class="card-demo ">Product 6</div>
    <div class="card-demo ">Product 7</div>
    <div class="card-demo ">Product 8</div>
</div>

Установим свойство justify-content: center;. Высота карточки с товаром у нас 380px, поэтому выберем в качестве значения высоты неявного ряда именно это число.

Теперь перейдем к вопросу адаптивности.

Как только разрешение для вывода будет меньше 1129 точек, просмотр контента станет неудобным — будет появляться прокрутка, а контент выйдет за пределы видимой области. Чтобы этого избежать, подготовим оптимизированный макет верстки.

Перейдем к настройке адаптивной версии веб-страницы. Для начала необходимо определиться с точкой перелома, для которой нам будет нужна адаптация макета.

Выберем точку медиазапроса 1129px. Для версии экрана, скажем, на планшете, исходный шаблон не годится. В оригинальной верстке у нас четыре колонки, но на планшете мы будем делать две колонки шириной в 260px.

Переопределим свойства grid-template-columns, а также свойства grid-template-rows. Также построим новый шаблон размещения элементов в ячейках по областям. Вот как будет выглядеть код:

.card-demo{
    background-color: rgb(154, 200, 251);
}
.cards-grid {
    display: grid;
    gap: 20px;
    grid-template-columns: repeat(4, 260px);
    grid-template-rows: repeat(4,180px);
    grid-template-areas: 
    'wide1 wide1 product1 product2'
    'wide2 wide2 product1 product2'
    'product3 product4 wide3 wide3'
    'product3 product4 wide4 wide4';
    grid-auto-rows: 380px;
}
.sale-1 { grid-area: wide1;}
.sale-2 { grid-area: wide2;}
.product-1 { grid-area: product1; }
.product-2 { grid-area: product2; }

.product-3{grid-area: product3;}
.product-4{grid-area: product4;}
.sale-3 {grid-area: wide3;}
.sale-4 {grid-area: wide4;}
@media (max-width: 1129px) {
    .cards-grid {
        grid-template-columns: repeat(2, 260px);
        grid-template-rows: repeat(8,180px);
        grid-template-areas: 
        'wide1 wide1'
        'wide2 wide2'
        'product1 product2'
        'product1 product2'
        'wide3 wide3'
        'wide4 wide4'
        'product3 product4'
        'product3 product4'
        ;
    }
}

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

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

Аналогичный принцип используется и для мобильной версии, с точкой медиа-запроса на 409px. В этом случае надо подкорректировать грид-шаблон таким образом, чтобы выводимый на экран контент помещался только в один столбец:

Финальный код выглядит так:

.card-demo{
    background-color: rgb(154, 200, 251);
}
.cards-grid {
    display: grid;
    gap: 20px;
    grid-template-columns: repeat(4,260px);
    grid-template-rows: repeat(4,180px);
    grid-template-areas: 
    'wide1 wide1 product1 product2'
    'wide2 wide2 product1 product2'
    'product3 product4 wide3 wide3'
    'product3 product4 wide4 wide4';
    grid-auto-rows: 380px;
}
.sale-1 { grid-area: wide1;}
.sale-2 { grid-area: wide2;}
.product-1 { grid-area: product1; }
.product-2 { grid-area: product2; }

.product-3{grid-area: product3;}
.product-4{grid-area: product4;}
.sale-3 {grid-area: wide3;}
.sale-4 {grid-area: wide4;}
@media (max-width: 1129px) {
    .cards-grid {
        grid-template-columns: repeat(2, 260px);
        grid-template-rows: repeat(8,180px);
        grid-template-areas: 
        'wide1 wide1'
        'wide2 wide2'
        'product1 product2'
        'product1 product2'
        'wide3 wide3'
        'wide4 wide4'
        'product3 product4'
        'product3 product4'
        ;
    }
}
@media (max-width: 409px){
    .cards-grid {
        grid-template-columns: 1fr;
        width:100%;
        grid-template-rows: repeat(12, 140px);
        grid-auto-rows: 300px;
        grid-template-areas: 
        'wide1'
        'wide2'
        'product1'
        'product1 '
        'product2'
        'product2'
        'wide3'
        'wide4'
        'product3 '
        'product3'
        'product4'
        'product4'
        ;
    }
}

Анимация с Grid

Одна из самых интересных опций CSS-верстки — анимация. Некоторые свойства гридов также можно анимировать, создавая интересные дизайнерские идеи. 

Пример №1

Создадим простой блок:

<div id="grid">
  <div id="leftedge"></div>
  <div id="rightedge"></div>
</div>

И анимируем стили:

body {
  margin: 0;
}

#grid {
  height: 100vh;
}

#leftedge {
  background: green;
}

#rightedge {
  background: navajowhite;
  border: 3rem solid rgb(0 0 0 / 10%);
}

#grid {
  transition: 300ms;
  display: grid;
  grid-template-columns: 48px auto;
}

#grid:has(#leftedge:hover) {
  grid-template-columns: 30% auto;
}

#grid {
  transition: 1000ms;
  display: grid;
  grid-template-columns: var(--left, 17px) auto;
}
#grid:has(#leftedge:hover) {
--left: 30%;

Такой код создаст анимированный сайдбар, который «выезжает» при наведении курсора.

Анимация размера столбцов выполняется посредством значений grid-template-columns. А чтобы она была постепенной, используем свойство transition. Псевдокласс :has() может использоваться, чтобы стилизировать grid-контейнер.

Пример №2

Следующий пример — анимация раздвигающихся колонок.

Код HTML:

<div id="grid">
  <div class="left"></div>
  <div class="center"></div>
  <div class="right"></div>
</div>

Код CSS:

body {
  margin: 0;
}

#grid {
  height: 100vh;
  transition: 500ms;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 3px;
  background: violet;
}

:where(.left, .center, .right) {
  background: navajowhite;
  transition: 300ms;
}

:where(.left, .center, .right):hover {
  background: violet;
}

#grid:has(.left:hover) {
  grid-template-columns: 2fr 0.3fr 0.3fr;
}

#grid:has(.center:hover) {
  grid-template-columns: 0.3fr 2fr 0.3fr;
}
#grid:has(.right:hover) {
  grid-template-columns: 0.3fr 0.3fr 2fr;
}

Результат:

В этом примере анимируется переход для изменения ширины колонок, а также меняется заливка их фона.

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

Пример №3

Третий вариант анимации с grid-версткой — увеличение ячеек при наведении.

<div class="container">
    <div class="item item1"></div>
    <div class="item item2"></div>
    <div class="item item3"></div>
    <div class="item item4"></div>
    <div class="item item5"></div>
    <div class="item item6"></div>
  </div>

 

Этот код создает контейнер с шестью элементами, которые расположены в сетке с тремя колонками и двумя строками. У каждого элемента есть фоновый цвет серого цвета, а при наведении на элементы они увеличиваются в размерах на 20%. Элементы расположены в определенных позициях в сетке с помощью свойств grid-column и grid-row.

.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(2, 1fr);
  grid-gap: 20px;
  height: 500px;

}

.item {  
  background-color: #ccc;
  transition: transform 0.3s ease;
  border: 17px solid #000;
  transition: transform 0.3s ease;
}

.item:hover {
  transform: scale(1.2);
}

.item1 {
  grid-column: 1 / span 2;
  grid-row: 1 / span 2;
}

.item2 {
  grid-column: 3;
  grid-row: 1 / span 1;
}

.item3 {
  grid-column: 3;
  grid-row: 2 / span 1;
}

.item4 {
  grid-column: 1 / span 1;
  grid-row: 2 / span 1;
}

.item5 {
  grid-column: 2 / span 1;
  grid-row: 2 / span 1;
}

.item6 {
  grid-column: 1 / span 1;
  grid-row: 1 / span 1;
}

Результат:

 

Пример №4

Пример макета анимированного меню на гридах. Код HTML:

<div class="menu">
    <div class="menu-item">Главная</div>
    <div class="menu-item">О нас</div>
    <div class="menu-item">Контакты</div>
    <div class="menu-item">Блог</div>
    <div class="menu-item">Войти</div>
  </div>

Код CSS:

.menu {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
}

.menu-item {
  background-color: #eee;
  padding: 10px;
  text-align: center;
  transition: transform 0.2s ease-in-out;
}

.menu-item:hover {
  transform: translateY(-5px);
}

Этот пример содержит меню на основе грид-макета, пункты которого анимированы при наведении на них курсором:

Пример №5

В следующем примере создается контейнер с классом .grid-container, который содержит 9 элементов с классом .item. Свойства grid-template-rows и grid-template-columns указываются для создания сетки три на три.

Затем добавляется класс .animate-grid к контейнеру, чтобы применить анимацию animate-grid. Она меняет через некоторое время значения grid-template-rows и grid-template-columns.

Анимация animate-grid использует ключевые кадры from и to (чтобы задать начальное и конечное значение свойств grid-template-rows и grid-template-columns). Затем применяется свойство animation для анимации контейнера с классом .animate-grid.

Код:

<!DOCTYPE html>
<html>
  <head>
    <title>Animated Grid Layout</title>
    <style>
      .grid-container {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        grid-template-rows: repeat(3, 100px);
        gap: 10px;
        width: 500px;
        height: 500px;
        margin: 0 auto;
      }

      .item {
        background-color: #eee;
        border: 1px solid #999;
        text-align: center;
        font-size: 24px;
        display: flex;
        justify-content: center;
        align-items: center;
        transition: all 0.5s ease-in-out;
      }

      .item:hover {
        transform: scale(1.2);
        background-color: #ffcc00;
        color: #fff;
        box-shadow: 0 0 20px #ffcc00;
      }

      .animate-grid {
        animation: animate-grid 2s ease-in-out infinite alternate;
      }

      @keyframes animate-grid {
        from {
          grid-template-rows: repeat(3, 100px);
          grid-template-columns: repeat(3, 1fr);
        }
        to {
          grid-template-rows: repeat(3, 50px);
          grid-template-columns: repeat(3, 2fr);
        }
      }
    </style>
  </head>
  <body>
    <div class="grid-container animate-grid">
      <div class="item">1</div>
      <div class="item">2</div>
      <div class="item">3</div>
      <div class="item">4</div>
      <div class="item">5</div>
      <div class="item">6</div>
      <div class="item">7</div>
      <div class="item">8</div>
      <div class="item">9</div>
    </div>
  </body>
</html>

Результат исполнения кода:

Заключение

Grid-верстка — это мощный инструмент, который позволяет легко управлять контентом на странице. Но эта технология не универсальная и потому подходит не для всех проектов.

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

Зубрить все Grid-свойства — бессмысленно. Используйте их по мере необходимости и, чем больше практики у вас будет, тем лучше вы запомните синтаксис. Если вы будете применять технологию Grid-верстки в своих проектах часто, то освоете ее довольно легко и быстро.

Начинающим верстальщикам, которые только пробуют работать гридами, помогут такие советы:

  1. Используйте гриды в тех проектах, где это возможно. С ними макет будет выглядеть профессионально, а восприниматься легко. Но не применяйте грид там, где он не нужен.
  2. Сокращайте запись свойств на гридах — это упростит ваш код и сделает его более читабельным. При этом помните, что обилие шорткатов может быть неуместно.
  3. Создавайте вложенные элементы соответственно разметке сетки. Каждый элемент должен занимать одну или несколько ячеек сетки, чтобы сохранить симметрию и баланс.
  4. Используйте медиа-запросы. Так гриды можно легко адаптировать к разным размерам экранов.
  5. Не бойтесь экспериментировать. Гриды позволяют создавать необычные макеты и экспериментировать с разными расположениями элементов. Используйте свойства гридов, чтобы создать уникальный и интересный дизайн, который будет привлекать внимание пользователей.

В завершение этого руководства по Grid рекомендуем вам посмотреть инструкцию по адаптивной верстке с использованием технологий Flexbox и Grid:

Останні статті

Что такое прокси-сервер: пояснение простыми словами, зачем нужны прокси

Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…

21.11.2024

Что такое PWA приложение? Зачем необходимо прогрессивное веб-приложение

Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…

19.11.2024

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

Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…

17.11.2024

Google Bard: эффективный аналог ChatGPT

В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…

14.11.2024

Скрипт и программирование: что это такое простыми словами

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

12.11.2024

Дедлайн в разработке: что это такое простыми словами

Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…

11.11.2024