Перевод «Understanding CSS Grid: Creating A Grid Container» Рейчел Эндрю
Хотя технология CSS Grid стала поддерживаться некоторыми браузерами еще в 2017 году, у многих разработчиков пока не было возможности использовать её в своих проектах. Технология CSS Grid привносит множество новых свойств и значений. Из-за этого может казаться сложной. Однако, многие используемые в ней инструменты являются взаимозаменяемыми, а это значит, что вам не нужно изучать всю спецификацию, чтобы начать. Цель серии статей "Понимание CSS Grid" – провести читателей по пути от новичка до эксперта.
В данной начальной статье будет рассказано о том, что происходит, когда вы создаёте grid-контейнер и о различных свойствах, которые можно применять к родительскому элементу для управления сеткой. Вы узнаете, что в некоторых ситуациях достаточно только свойств, применяемых к grid-контейнеру.
В этой статье мы рассмотрим:
- Создание grid-контейнера с помощью
display: grid
илиdisplay: inline-grid
- Создание колонок и строк с помощью
grid-template-columns
иgrid-template-rows
- Управление размерами неявных треков (полос / дорожек) с помощью
grid-auto-columns
иgrid-auto-rows
Создание Grid-контейнера
Grid, как и Flexbox, является значением свойства display
. Следовательно, чтобы сообщить браузеру, что вы хотите использовать grid-разметку, нужно использовать display: grid
. Элемент, к которому применено это свойство, станет блочным, а все его дочерние элементы станут принимать участие в контексте форматирования Grid. Это значит, что они ведут себя как grid-элементы, а не как обычные блочные или строчные.
Однако, порой разница в разметке сразу может быть и не видна. Так как какие-либо строки или колонки для сетки заданы не были, получается одноколоночная сетка. В этой сетке появляется достаточное количество строк, чтобы уместились все прямые дочерние элементы, располагаемые в ней друг под другом. Визуально это выглядит как обычное расположение блочных элементов.
Разница будет видна, если присутствует какой-то текст, не обернутый в теги и расположенный непосредственно внутри grid-контейнера, поскольку этот текст будет оформлен в анонимный элемент и станет grid-элементом. Любой элемент, который обычно является строчным, таким как <span>
, также станет элементом сетки, как только родительский станет grid-контейнером.
На примере ниже имеется два блочных элемента плюс строка с тегом <span>
в середине текста. Мы получаем пять grid-элементов:
- Два элемента
<div>
- Строка текста перед
<span>
- Элемент тега
<span>
- Строка текста после
<span>
Если вы проверите сетку в Firefox Grid Inspector, сможете увидеть пять строковых треков, созданных для каждого элемента.
Также можно создать строчную сетку, задав display: inline-grid
; в этом случае ваш grid-контейнер станет строчным блоком. Однако, его дети всё ещё будут элементами сетки и будут вести себя так же, как элементы внутри блочного grid-контейнера. Свойство display
определяет лишь внешний контекст форматирования для сетки. Именно поэтому grid-контейнер в данном случае ведёт себя точно так же, как указано выше, даже если находится рядом с другими блоками страницы.
Следующий пример содержит grid, расположенный перед строкой текста, но так как он строчный, последующий текст может отображаться рядом с ним. Строчные элементы не растягиваются на всю доступную ширину в строчном измерении так, как это делают блочные элементы.
Примечание: В будущем мы сможем лучше описывать разметку макета, используя display: block grid
, чтобы создать блочный контейнер и display: inline grid
для строчного. Почитать подробнее про это изменение в спецификации свойства display можно в моей статье "Digging Into The DIsplay Property: The Two Values Of Display".
Колонки и строки
Чтобы получить что-то похожее на сетку, нужно добавить колонки и строки. Они создаются с помощью свойств grid-template-columns
и grid-template-rows
. Эти свойства определяются в спецификации как принимающие значение, называемое "track-list" (список треков).
Эти свойства позволяют задать треки сетки с помощью имён линий и функций размера, разделённых пробелами. Свойство grid-template-columns
позволяет задать колоночные треки, а свойство grid-template-rows
– строковые.
Вот некоторые допустимые значения списка треков:
grid-template-columns: 100px 100px 200px
– создаёт трёхколоночную сетку. Первая колонка равняется 100px, вторая – 100px, третья – 200pxgrid-template-columns: min-content max-content fit-content(10em)
– создаёт трёхколоночную сетку. Первая колонка имеет размерmin-content
, вторая –max-content
. третья колонка имеет ширинуmax-content
, если содержимое не превышает 10em, если превышает – ограничивается шириной 10em.grid-template-columns: 1fr 1fr 1fr
– создаёт трёхколоночную сетку, используя единицу измеренияfr
. Доступное пространство grid-контейнера распределяется между тремя колонками.grid-template-columns: repeat(2, 10em 1fr)
– создаёт четырёхколоночную сетку с размерами колонок 10em 1fr 10em 1fr, так как используется оператор repeat() с двумя повторениями шаблона колонок.grid-template-columns: repeat(auto-fill, 200px)
– заполняет контейнер таким количеством колонок шириной по 200px, сколько поместится, оставляя в конце пробел, если осталось немного дополнительного места.grid-template-columns: repeat(auto-fill, minmax(200px, 1fr))
– заполняет контейнер таким количеством колонок шириной по 200px, сколько поместится, после чего распределяет оставшееся пространство между этими созданными колонками.grid-template-columns: [full-start] 1fr [content-start] 3fr [content-end] 1fr [full-end]
– создаёт трёхколоночную сетку. Первая и третья колонки имеют ширину, равную 1 части доступного пространства, а третья – 3 частям. Линии именуются путём добавления названий линий в квадратных скобках.
Как вы можете видеть, существует множество способов указать набор треков сетки. Давайте посмотрим, как именно это всё работает, а также узнаем, в какой ситуации лучше использовать каждый из способов.
Единицы длины
Для создания треков можно использовать любые единицы измерения длины или проценты. Если сумма ширин треков меньше доступной в grid-контейнере, по умолчанию треки выстраиваются в начале контейнера, а в конце остаётся свободное место. Это происходит из-за того, что по умолчанию свойства align-content
и justify-content
имеют значение start
. Вы можете разметить треки сетки или переместить их в конец контейнера, используя свойства выравнивания, про которые я подробно рассказывала в статье How To Align Things In CSS.
Также можно использовать ключевые слова min-content
, max-content
и fit-content()
.
Использование min-content
даст вам трек, который будет настолько маленьким, насколько это возможно, при этом не вызывая переполнение содержимым. Следовательно, при его использовании в качестве размера колонки, содержимое будет мягко переноситься в тех местах, где это возможно. Трек обретает ширину, равную самому длинному слову в колонке или наибольшему элементу фиксированного размера.
Использование max-content
приведёт к тому, что содержимое вообще не будет переноситься, что может привести к переполнению.
Ключевое слово fit-content
может быть использовано только вместе с передаваемым значением. Это значение становится максимумом, до которого может растягиваться данный трек. Следовательно, трек будет вести себя как при использовании max-content
, растягивая содержимое, пока ширина не достигнет максимального значения, которое мы указали. А когда это произойдёт, содержимое начнёт переноситься как обычно. Таким образом, трек может быть меньше переданного значения, но никогда не будет больше него.
Узнать больше о размерах в CSS Grid и других технологиях разметки можно в моей статье How Big Is That Box? Understanding Sizing In CSS Layout.
Если в итоге у вас получились треки, которые занимают больше пространства, чем доступно в контейнере, они будут переполнять контейнер. Если используются проценты, то как и в основанной на процентах float или flex разметке, нужно будет внимательно следить за тем, чтобы сумма процентов не превышала 100, если вы хотите избежать переполнения.
Единицы измерения «fr»
CSS Grid включает метод, который может помочь сэкономить время на расчет процентов, этот метод предполагает задание ширины треков с помощью единиц измерения fr
. Это не единицы длины и поэтому не могут использоваться в функции cacl()
; это гибкая единица измерения, которая рассчитывается исходя из количества доступного пространства в grid-контейнере.
Это значит, что задав список треков 1fr 1fr 1fr
, доступное пространство делится на 3 и распределяется поровну между тремя колонками. Если же указать список треков 2fr 1fr 1fr
, доступное пространство делится на 4, из которых 2 части отходят первой колонке, и по одной части для второй и третьей колонки.
Важно помнить о том, что по умолчанию "доступное пространство" – это не всё пространство контейнера. Если какая-то из колонок содержит элемент фиксированного размера или длинное слово, которое не может быть перенесено на новую строку, пространство под эту колонку будет выделено до того, как начнётся его распределение между всеми колонками.
В следующем примере я удалила пробелы между словами в элементе ItemThree
. Из-за этого образовалась длинная непереносимая строка, поэтому распределение доступного пространства происходит только после отрисовки данного элемента.
Вы можете объединять единицы измерения fr
с фиксированными размерами. Например, компонент может состоять из двух колонок с фиксированной шириной по краям и гибкой центральной областью.
Еще один пример – компонент с двумя колонками, одна из которых имеет ширину fit-content(300px)
, а другая 1fr
. Это полезно в ситуации, когда в первой колонке может содержаться что-то меньшее 300px, и в этом случае эта колонка займёт ровно столько пространства, сколько ей потребуется, а вторая колонка с шириной, заданной в fr
займёт всё оставшееся пространство. Если же добавить что-то большее (например, изображение со свойством max-width: 100%
), первая колонка увеличится до 300px, а вторая колонка займёт остальное пространство. Использование fr
совместно со свойством fit-content
– это способ создавать очень гибкие компоненты сайта.
Функция repeat()
Функция repeat()
при указании списка треков может избавить от необходимости снова и снова вводить одинаковые значения.
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
grid-template-columns: repeat(12, 1fr);
При использовании функции repeat()
, значение перед запятой задаёт количество повторений для списка треков, идущих после запятой. Этот список треков может содержать множество значений.В итоге, вы можете задавать таким образом повторение определённого набора треков.
Функцию repeat()
можно использовать лишь для части треков из всего набора. Например, следующая строка задает одну колонку шириной 1fr, затем три колонки по 200px и в конце еще одну шириной 1fr.
grid-template-columns: 1fr repeat(3,200px) 1fr
Помимо числа перед запятой, позволяющего указывать точное количество повторений шаблона, также можно использовать ключевые слова auto-fill
или auto-fit
. Использование одного из этих ключевых слов подразумевает, что вместо заранее определённого, ваш grid-контейнер будет заполнен таким количеством треков, сколько в него поместится.
Использование фиксированных единиц измерения длины означает, что если размер контейнера больше суммы размеров колонок, в конце будет оставаться свободное пространство. В примере выше ширина контейнера равна 500px, поэтому получается две колонки по 200px плюс свободное место в конце.
Мы также можем использовать другую grid-функцию, чтобы сделать значение минимальным, а свободное пространство чтобы распределялось между всеми колонками. Функция minmax()
принимает значения минимального и максимального размера. Если задать минимум = 200px, а максимум = 1fr, мы получим столько колонок шириной 200px, сколько поместится, а благодаря значению максимума = 1fr, если осталось дополнительное пространство, оно равномерно распределится между всеми колонками.
Я упоминала два ключевых слова: auto-fill
и auto-fit
. Если у вас достаточно содержимого, чтобы заполнить весь первый ряд ячеек контейнера, поведение этих ключевых слова будет одинаковым. Если содержимого не хватает – поведение будет разным.
Значение auto-fill
сохраняет размер колонки, даже если в ней нет содержимого.
При использовании значения auto-fit
, пустые колонки схлопываются.
С помощью Firefox Grid Inspector вы можете увидеть, что колонки всё ещё здесь, но были схлопнуты, уменьшив свою ширину до 0px. Последняя линия нашей сетки – это линия 3, поскольку мы всё ещё можем поместить дополнительные два трека.
Именованные линии
В последнем примере допустимых значений для указания списка треков использовался подход с именованием линий. При использовании CSS Grid, всегда есть возможность работать с линиями через их номера. Однако, их также можно именовать. Названия линиям задаются внутри квадратных скобок. Допускается задавать несколько названий для одной линии, разделяя их пробелом. Например, в следующем списке треков всем линиям заданы два названия.
grid-template-columns: [main-start sidebar-start] 1fr [sidebar-end content-start] 4fr [content-end main-end]
Линиям можно давать любые имена, кроме span
, поскольку это зарезервированное слово, которое используется при размещении элементов на сетке.
Примечание: В следующей статье из этой серии я больше расскажу о позиционировании с использованием линий и о том, как их лучше именовать. А пока что можете почитать мою статью "Naming Things in CSS Grid Layout, чтобы лучше понять эту тему.
Явная и неявная сетка
При создании сетки с помощью свойств grid-template-columns
и grid-template-rows
задаётся так называемая явная сетка. Определённая таким образом сетка имеет размеры, равные сумме всех заданных треков.
Если же количество grid-элементов превышает заданное количество ячеек, или просто элемент размещён так, что выходит за границы созданной сетки, это создаст треки неявной сетки. Размер этих треков неявной сетки будет определён по умолчанию. Мы видели эту неявную сетку в действии, когда я объявила display: grid
для родительского элемента и сетка автоматически создала по одной строке для каждого grid-элемента. Я не определяла эти строки явно, но поскольку у неё были дочерние элементы, строковые треки были созданы, чтобы разместить эти элементы на сетке.
Задать размер неявных строк и колонок можно с помощью свойств grid-auto-rows
или grid-auto-columns
. Эти свойства принимают список треков, поэтому если вы хотите, чтобы все неявные колонки были высотой не меньше 200px и увеличивались, если того требовало содержимое, можете можете сделать следующее:
grid-auto-rows: minmax(200px, auto)
Если же нужно, чтобы размер первой неявной строки определялся автоматически исходя из содержимого, а вторая имела фиксированную высоту 100px (и так далее, поочерёдно применяя эти значения ко всем последующим строкам), то свойству можно задать несколько значений.
grid-auto-rows: auto 100px
Использование авторазмещения на сетке
Создание сетки и позволение браузеру автоматически размещать на ней элементы открывает широкие возможности с точки зрения результатов, которых можно добиться. Пока что мы не рассматривали позиционирование элементов на сетке, но нередко при разработке с использованием CSS Grid его и не используют. Вместо этого просто полагаются на расположение в обычном исходном порядке: по одному элементу в каждой ячейчке.
Если вы новичок в CSS Grid, хороший способ начать его использовать – поиграть с размерами треков и посмотреть, как элементы будут размещаться в создаваемых ячейках.
vsb
А есть сравнение производительности похожих лэйаутов на grid/flex/table/просто дивами? Очень интересно, какой подход лучше с точки зрения производительности, особенно на слабых устройствах. А то вроде браузеры уже неплохо поддерживают всё это, но всё равно подспудное опасение остаётся, хочется старые методы использовать, на таблицах верстать, кажется, будто это быстрей работает, может быть зря.