Взаимосвязь сеткообразной компоновки с другими методами компоновки
Сетка CSS разработана для работы совместно с другими частями CSS, как часть комплексной системы компоновки. В этом руководстве я объясню, как сетка взаимодействует с другими техниками, которые вы уже используете.
Сетка и гибкая компоновка
Основное различие между сеткообразной компоновкой CSS и гибкой компоновкой CSS заключается в том, что гибкая компоновка была разработана для компоновки в одном измерении — либо строке, либо столбце. Сетка была разработана для двухмерной компоновки — строк и столбцов одновременно. Тем не менее, эти два спецификатора имеют некоторые общие особенности, и если вы уже знаете, как использовать гибкую компоновку, сходства помогут вам разобраться с сеткой.
Компоновка в одном измерении по сравнению с компоновкой в двух измерениях
Простой пример может продемонстрировать разницу между компоновкой в одном и двух измерениях.
В этом первом примере я использую гибкую компоновку для размещения набора блоков. В моём контейнере пять элементов-потомков, и я задал свойства гибкой компоновки, чтобы они могли расти и уменьшаться от базового значения 150 пикселей.
Я также установил свойство flex-wrap в значение wrap, чтобы, если пространство в контейнере станет слишком узким для сохранения базового значения, элементы переносились на новую строку.
<div class="wrapper"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> </div>
.wrapper {
width: 500px;
display: flex;
flex-wrap: wrap;
}
.wrapper > div {
flex: 1 1 150px;
}
На изображении вы можете увидеть, что два элемента переместились на новую строку. Эти элементы делят доступное пространство и не выстраиваются под элементами, расположенными выше. Это происходит потому, что при переносе элементов гибкой компоновки каждая новая строка (или столбец при работе по столбцам) является независимой линией гибкого контейнера. Распределение пространства происходит по линии гибкой компоновки.
Тогда возникает распространённый вопрос о том, как выровнять эти элементы. Для этого нужен двухмерный метод компоновки: необходимо контролировать выравнивание по строкам и столбцам, и здесь на помощь приходит сетка.
Такая же компоновка с помощью CSS-сеток
В этом следующем примере я создаю такую же компоновку с помощью сетки. На этот раз у нас есть три 1fr столбцовых дорожки. Нам не нужно ничего устанавливать для самих элементов; они сами будут выстраиваться в каждую ячейку созданной сетки. Как вы можете видеть, они остаются в строгой сетке, выстраиваясь в строки и столбцы. В случае с пятью элементами у нас появляется зазор в конце второй строки.
<div class="wrapper"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> </div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
Простой вопрос, который нужно задать себе при выборе между сеткой и гибкой компоновкой:
- Нужно ли управлять компоновкой только по строке или столбцу — используйте гибкую компоновку
- Нужно ли управлять компоновкой по строке и столбцу — используйте сетку
Содержание снаружи или компоновка изнутри?
Помимо различия между компоновкой в одном и двух измерениях, есть ещё один способ определить, следует ли использовать гибкую компоновку или сетку для компоновки. Гибкая компоновка работает от содержимого наружу. Идеальный случай использования гибкой компоновки — когда у вас есть набор элементов, и вы хотите равномерно распределить их по контейнеру. Вы позволяете размеру содержимого определять, сколько индивидуального места занимает каждый элемент. Если элементы переносятся на новую строку, они будут рассчитывать свой отступ на основе своего размера и доступного места на этой строке.
Сетка работает от компоновки внутрь. Когда вы используете сетку CSS, вы создаёте макет, а затем размещаете в нём элементы или разрешаете правила автоматического размещения, чтобы разместить элементы в ячейки сетки в соответствии с этой строгой сеткой. Можно создать дорожки, которые реагируют на размер содержимого, но они также изменят всю дорожку.
Если вы используете гибкую компоновку и обнаруживаете, что вам приходится отключать какую-то гибкость, вам, вероятно, потребуется использовать сетку CSS. Пример — если вы устанавливаете процентную ширину на элемент гибкой компоновки, чтобы выровнять его с другими элементами в строке выше. В этом случае сетка, скорее всего, будет лучшим выбором.
Выравнивание блоков
Функция гибкой компоновки, которая наиболее впечатлила многих из нас, заключалась в том, что она впервые предоставила нам надёжный контроль над выравниванием. Это упростило центрирование блока на странице. Элементы гибкой компоновки могут растягиваться до высоты контейнера гибкой компоновки, что означает возможность создания столбцов одинаковой высоты. Это то, что мы хотели сделать очень давно, и придумали различные ухищрения для достижения, по крайней мере, визуального эффекта.
Свойства выравнивания из спецификации гибкой компоновки были добавлены в новый спецификатор, называемый Box Alignment Level 3. Это означает, что они могут использоваться в других спецификациях, включая сеткообразную компоновку. В будущем они могут применяться и к другим методам компоновки.
В последующем руководстве этой серии я подробно разберу выравнивание блоков и то, как оно работает в сеткообразной компоновке. На данный момент вот сравнение простых примеров гибкой компоновки и сетки.
В первом примере, который использует гибкую компоновку, у меня есть контейнер с тремя элементами внутри. У обертки min-height установлена высота, поэтому она определяет высоту контейнера гибкой компоновки. Я установил align-items для контейнера гибкой компоновки в значение flex-end, чтобы элементы выравнивались в конце контейнера гибкой компоновки. Я также установил свойство align-self для box1 , чтобы переопределить значение по умолчанию и растянуть его до высоты контейнера, и для box2 , чтобы выровнять его в начале контейнера гибкой компоновки.
<div class="wrapper"> <div class="box1">One</div> <div class="box2">Two</div> <div class="box3">Three</div> </div>
.wrapper {
display: flex;
align-items: flex-end;
min-height: 200px;
}
.box1 {
align-self: stretch;
}
.box2 {
align-self: flex-start;
}
Выравнивание в CSS-сетках
Во втором примере используется сетка для создания такого же макета. На этот раз мы используем свойства выравнивания блоков, так как они применяются к сеткообразной компоновке. Таким образом, мы выравниваем по start и end вместо flex-start и flex-end. В случае сеткообразной компоновки мы выравниваем элементы внутри их области сетки. В этом случае это одна ячейка сетки, но это может быть область, состоящая из нескольких ячеек сетки.
<div class="wrapper"> <div class="box1">One</div> <div class="box2">Two</div> <div class="box3">Three</div> </div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
align-items: end;
grid-auto-rows: 200px;
}
.box1 {
align-self: stretch;
}
.box2 {
align-self: start;
}
Единица fr и flex-basis
Мы уже видели, как единица fr используется для назначения пропорционального доступного пространства в контейнере сетки нашим дорожкам сетки. Единица fr , в сочетании с функцией minmax(), может обеспечить поведение, очень похожее на свойства flex в гибкой компоновке, при сохранении возможности создания компоновки в двух измерениях.
Если мы вернёмся к примеру, где я продемонстрировал разницу между компоновкой в одном и двух измерениях, вы можете увидеть разницу в том, как эти два макета работают при адаптации. С помощью гибкой компоновки, если мы увеличиваем и уменьшаем размер окна, гибкая компоновка хорошо справляется с регулировкой количества элементов в каждой строке в соответствии с доступным пространством. Если у нас много места, все пять элементов могут поместиться в одну строку. Если контейнер очень узкий, у нас может быть место только для одного.
В отличие от этого, версия с сеткой всегда имеет три столбцовые дорожки. Сами дорожки будут расти и уменьшаться, но их всегда будет три, поскольку мы запросили их три при определении нашей сетки.
Автоматическое заполнение дорожек сетки
Мы можем использовать сетку для создания эффекта, аналогичного гибкой компоновке, сохраняя при этом содержимое, упорядоченное в строгих строках и столбцах, создавая перечисление дорожек с помощью записи repeat и свойств auto-fill и auto-fit.
В этом следующем примере я использовал ключевое слово auto-fill вместо целого числа в записи repeat и задал перечисление дорожек в 200 пикселей. Это означает, что сетка создаст столько столбцовых дорожек размером 200 пикселей, сколько поместится в контейнере.
<div class="wrapper"> <div>One</div> <div>Two</div> <div>Three</div> </div>
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fill, 200px);
}
Гибкое количество полос
Это немного отличается от flexbox. В примере с flexbox элементы больше, чем базовая величина в 200 пикселей, прежде чем произойдёт перенос на следующую строку. Мы можем добиться того же в сетке, объединив auto-fit и функцию minmax(). В этом следующем примере я создаю автоматически заполненные полосы с помощью minmax. Я хочу, чтобы мои полосы были не менее 200 пикселей, поэтому я устанавливаю максимальное значение в 1fr. После того, как браузер определит, сколько раз 200 пикселей поместятся в контейнер (учитывая также отступы сетки), он будет рассматривать максимальное значение 1fr как указание на распределение оставшегося места между элементами.
<div class="wrapper"> <div>One</div> <div>Two</div> <div>Three</div> </div>
.wrapper {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
С помощью сетки мы можем создать сетку с динамическим количеством гибких полос и разместить элементы в сетке, выровненными по строкам и столбцам.
Сетка и абсолютно позиционированные элементы
Сетка взаимодействует с абсолютно позиционированными элементами, что может быть полезно, если вы хотите разместить элемент внутри сетки или области сетки. Спецификация определяет поведение, когда контейнер сетки является контейнером размещения и родителем абсолютно позиционированного элемента.
Контейнер сетки как контейнер размещения
Чтобы сделать контейнер сетки контейнером размещения, вам нужно добавить свойство position к контейнеру со значением relative, так же, как вы бы создали контейнер размещения для любого другого абсолютно позиционированного элемента. После этого, если вы дадите элементу сетки position: absolute, он будет использовать контейнер сетки или, если у элемента также есть позиционирование сетки, область сетки, в которую он помещен, как контейнер размещения.
В приведенном ниже примере у нас есть контейнер, содержащий четыре дочерних элемента. Элемент три абсолютно позиционирован и также размещен в сетке с помощью размещения на основе линий. Контейнер сетки имеет position: relative, поэтому становится контекстом позиционирования этого элемента.
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">
This block is absolutely positioned. In this example the grid container is
the containing block and so the absolute positioning offset values are
calculated in from the outer edges of the area it has been placed into.
</div>
<div class="box4">Four</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 200px;
gap: 20px;
position: relative;
}
.box3 {
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
position: absolute;
top: 40px;
left: 40px;
}
Вы можете увидеть, что элемент занимает область от линии сетки 2 до 4 столбцов, начиная после линии 1. Затем он смещен в этой области с помощью свойств top и left. Однако он удален из потока, как обычно для абсолютно позиционированных элементов, поэтому правила автоматического размещения теперь размещают элементы в то же пространство. Элемент также не приводит к созданию дополнительной строки для разворота до линии строки 3.
Если мы удалим position: absolute из правил для .box3, вы увидите, как он будет отображаться без позиционирования.
Контейнер сетки как родитель
Если у абсолютно позиционированного дочернего элемента есть контейнер сетки как родитель, но этот контейнер не создает новый контекст позиционирования, то он удаляется из потока, как в предыдущем примере. Контекст позиционирования будет тем элементом, который создаёт контекст позиционирования, как это обычно бывает и в других методах макета. В нашем случае, если мы удалим position: relative из контейнера выше, контекст позиционирования будет от области просмотра, как показано на этом изображении.
Вновь элемент больше не участвует в макете сетки с точки зрения размера или при автоматическом размещении других элементов.
С областью сетки в качестве родителя
Если абсолютно позиционированный элемент вложен в область сетки, вы можете создать контекст позиционирования в этой области. В приведенном ниже примере у нас есть наша сетка, как и раньше, но на этот раз я вложил элемент внутрь .box3 сетки.
Я дал .box3 свойство position со значением relative, а затем позиционировал дочерний элемент с помощью свойств смещения. В этом случае контекстом позиционирования является область сетки.
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">
Three
<div class="abspos">
This block is absolutely positioned. In this example the grid area is the
containing block and so the absolute positioning offset values are
calculated in from the outer edges of the grid area.
</div>
</div>
<div class="box4">Four</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 200px;
gap: 20px;
}
.box3 {
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
position: relative;
}
.abspos {
position: absolute;
top: 40px;
left: 40px;
background-color: rgb(255 255 255 / 50%);
border: 1px solid rgb(0 0 0 / 50%);
color: #000;
padding: 10px;
}
Сетка и display: contents
Ещё одно взаимодействие с другой спецификацией макета, которое стоит отметить, это взаимодействие между макетом CSS-сетки и display: contents. Значение contents свойства display — новое значение, описанное в спецификации Display следующим образом:
"Сам элемент не генерирует никаких блоков, но его дочерние элементы и псевдоэлементы по-прежнему генерируют блоки как обычно. Для целей генерации блоков и макета элемент должен обрабатываться так, как если бы он был заменён на своих дочерних элементов и псевдоэлементов в дереве документа."
Если вы установите для элемента display: contents, блок, который он обычно создаёт, исчезает, и блоки дочерних элементов появляются, как если бы они поднялись на один уровень. Это означает, что дочерние элементы элемента сетки могут стать элементами сетки. Звучит странно? Вот простой пример.
Макет сетки с вложенными дочерними элементами
В следующем разметке у нас есть сетка, и первый элемент в сетке настроен на охватывание всех трёх полос столбцов. Он содержит три вложенных элемента. Поскольку эти элементы не являются прямыми дочерними элементами, они не становятся частью макета сетки и отображаются с помощью обычного макета блоков.
<div class="wrapper">
<div class="box box1">
<div class="nested">a</div>
<div class="nested">b</div>
<div class="nested">c</div>
</div>
<div class="box box2">Two</div>
<div class="box box3">Three</div>
<div class="box box4">Four</div>
<div class="box box5">Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
}
.box1 {
grid-column-start: 1;
grid-column-end: 4;
}
Использование display: contents
Если теперь я добавлю display: contents в правила для box1, блок для этого элемента исчезает, а подэлементы теперь становятся элементами сетки и выстраиваются с помощью правил автоматического размещения.
<div class="wrapper">
<div class="box box1">
<div class="nested">a</div>
<div class="nested">b</div>
<div class="nested">c</div>
</div>
<div class="box box2">Two</div>
<div class="box box3">Three</div>
<div class="box box4">Four</div>
<div class="box box5">Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
}
.box1 {
grid-column-start: 1;
grid-column-end: 4;
display: contents;
}
Это может быть способом, чтобы вложенные элементы в сетке действовали так, как будто они являются частью сетки, и это способ обойти некоторые проблемы, которые были бы решены подсетками, после их внедрения. Вы также можете использовать display: contents аналогичным образом с flexbox, чтобы вложенные элементы стали flex-элементами.
Как видно из этого руководства, макет CSS-сетки — лишь одна часть вашего инструментария. Не бойтесь смешивать его с другими методами макета, чтобы получить нужные эффекты.
См. также
© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Relationship_of_grid_layout_with_other_layout_methods