Авторазмещение в сетковом макете
Помимо возможности точно размещать элементы в созданной сетке, спецификация CSS Grid Layout содержит правила, управляющие тем, что происходит, когда вы создаете сетку и не размещаете некоторые или все дочерние элементы. Вы можете увидеть авторазмещение в действии простейшим способом, создав сетку на наборе элементов.
По умолчанию
Если вы не предоставите элементам информацию о размещении, они разместятся в сетке, по одному элементу в каждой ячейке.
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
<div class="wrapper"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> </div>
Правила авторазмещения по умолчанию
Как вы можете видеть в приведенном выше примере, если вы создаете сетку, все дочерние элементы будут выстроены по одному в каждую ячейку сетки. По умолчанию элементы располагаются по строкам. Сетка поместит элемент в каждую ячейку первой строки. Если вы создали дополнительные строки, используя свойство grid-template-rows, то сетка продолжит размещать элементы в этих строках. Если в явной сетке не хватает строк для размещения всех элементов, будут созданы новые неявные строки.
Размер строк в неявной сетке
По умолчанию автоматически созданные строки в неявной сетке имеют автоматический размер. Это означает, что они будут содержать добавленное в них содержимое без переполнения.
Однако вы можете контролировать размер этих строк с помощью свойства grid-auto-rows. Например, чтобы все созданные строки имели высоту 100 пикселей, вы используете:
<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);
gap: 10px;
grid-auto-rows: 100px;
}
Указание размера строк с помощью minmax()
Вы можете использовать minmax() в своем значении для grid-auto-rows, что позволит создавать строки с минимальным размером, которые затем будут увеличиваться, чтобы вместить содержимое, если оно выше.
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>
Four <br />This cell <br />Has extra <br />content. <br />Max is auto
<br />so the row expands.
</div>
<div>Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
grid-auto-rows: minmax(100px, auto);
}
Указание размера строк с помощью списка треков
Вы также можете передать список треков, он будет повторяться. Следующий список треков создаст начальную неявную строку трека размером 100 пикселей и вторую размером 200px. Это будет продолжаться до тех пор, пока содержимое не будет добавлено в неявную сетку.
<div class="wrapper"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> <div>Six</div> <div>Seven</div> <div>Eight</div> </div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
grid-auto-rows: 100px 200px;
}
Авторазмещение по столбцам
Вы также можете попросить сетку авторазместить элементы по столбцам. Используя свойство grid-auto-flow со значением column. В этом случае сетка будет добавлять элементы в строки, которые вы определили с помощью grid-template-rows. Когда столбец заполняется, она переходит к следующему явному столбцу или создает новый столбец в неявной сетке. Как и неявные строки, эти столбцы будут иметь автоматический размер. Вы можете контролировать размер неявных столбцов с помощью grid-auto-columns, что работает аналогично grid-auto-rows.
В следующем примере я создала сетку с тремя строками по 200 пикселей в высоту. Я авторазмещаю по столбцам, а созданные столбцы будут иметь ширину 300 пикселей, затем 100 пикселей, пока не будет достаточно столбцов, чтобы разместить все элементы.
.wrapper {
display: grid;
grid-template-rows: repeat(3, 200px);
gap: 10px;
grid-auto-flow: column;
grid-auto-columns: 300px 100px;
}
<div class="wrapper"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> <div>Six</div> <div>Seven</div> <div>Eight</div> </div>
Порядок авторазмещенных элементов
Сетка может содержать смесь элементов. Некоторые элементы могут иметь позицию в сетке, а другие могут быть автоматически размещены. Это может быть полезно, если порядок документа отражает порядок расположения элементов в сетке, вам может не потребоваться писать правила CSS для размещения абсолютно всех элементов. В спецификации есть большой раздел, посвященный алгоритму размещения элементов сетки алгоритм размещения элементов сетки, но для большинства из нас достаточно запомнить несколько простых правил для наших элементов.
Изменённый порядок документа
Сетка размещает элементы, которым не задана позиция в сетке, в том порядке, который описан в спецификации как «изменённый порядок документа». Это означает, что если вы вообще использовали свойство order, элементы будут размещены в соответствии с этим порядком, а не с порядком в DOM. В противном случае они останутся по умолчанию в том порядке, в котором они введены в исходный код документа.
Элементы со свойствами размещения
Первое, что сделает сетка, — это разместит все элементы, имеющие позицию. В примере ниже у меня 12 элементов сетки. Элемент 2 и элемент 5 были размещены с помощью размещения на основе линий в сетке. Вы можете увидеть, как эти элементы размещены, а остальные элементы затем автоматически размещаются в освободившиеся места. Автоматически размещенные элементы будут размещены перед размещенными элементами в порядке DOM, они не начинаются после позиции размещенного элемента, который предшествует им.
<div class="wrapper"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> <div>Six</div> <div>Seven</div> <div>Eight</div> <div>Nine</div> <div>Ten</div> <div>Eleven</div> <div>Twelve</div> </div>
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
gap: 10px;
}
.wrapper div:nth-child(2) {
grid-column: 3;
grid-row: 2 / 4;
}
.wrapper div:nth-child(5) {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
Обработка элементов, которые охватывают треки
Вы можете использовать свойства размещения, сохраняя при этом преимущества авторазмещения. В следующем примере я добавил в макет элементы 1, 5 и 9 (4n+1), которые охватывают два трека как по строкам, так и по столбцам. Я делаю это с помощью свойств grid-column-end и grid-row-end, установив значение span 2. Это означает, что начальная линия элемента будет установлена авторазмещением, а конечная линия будет охватывать два трека.
Вы можете видеть, как это создаёт пробелы в сетке, так как для автоматически размещённых элементов, если сетка встречает элемент, который не помещается в трек, она переходит к следующей строке, пока не найдёт место, куда элемент сможет поместиться.
<div class="wrapper"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> <div>Six</div> <div>Seven</div> <div>Eight</div> <div>Nine</div> <div>Ten</div> <div>Eleven</div> <div>Twelve</div> </div>
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
gap: 10px;
}
.wrapper div:nth-child(4n + 1) {
grid-column-end: span 2;
grid-row-end: span 2;
background-color: #ffa94d;
}
.wrapper div:nth-child(2) {
grid-column: 3;
grid-row: 2 / 4;
}
.wrapper div:nth-child(5) {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
Заполнение пробелов
До сих пор, кроме элементов, которые мы специально разместили, сетка всегда продвигается вперёд и сохраняет элементы в порядке DOM. Это, как правило, то, что вам нужно, если, например, вы создаёте форму, вы не захотите, чтобы метки и поля перемешивались, чтобы заполнить какой-либо пробел. Однако иногда мы выкладываем вещи, которые не имеют логического порядка, и мы хотели бы создать макет, в котором нет пробелов.
Для этого добавьте свойство grid-auto-flow со значением dense в контейнер. Это то же самое свойство, которое вы используете для изменения порядка следования на column, поэтому если вы работаете со столбцами, вы добавите оба значения grid-auto-flow: column dense.
Сделав это, сетка теперь заполнит пробелы, так как при движении по сетке она оставляет пробелы, как и раньше, но затем, если она найдёт элемент, который поместится в предыдущий пробел, она подберёт его и выведет из порядка DOM, чтобы поместить его в пробел. Как и при любом другом переупорядочении в сетке, это не изменяет логический порядок. Порядок табуляции, например, по-прежнему будет следовать порядку документа. Мы рассмотрим потенциальные проблемы с доступностью макета сетки в руководстве Макет сетки и доступность, но будьте осторожны при создании этого разрыва между визуальным порядком и порядком отображения.
<div class="wrapper"> <div>One</div> <div>Two</div> <div>Three</div> <div>Four</div> <div>Five</div> <div>Six</div> <div>Seven</div> <div>Eight</div> <div>Nine</div> <div>Ten</div> <div>Eleven</div> <div>Twelve</div> </div>
.wrapper div:nth-child(4n + 1) {
grid-column-end: span 2;
grid-row-end: span 2;
background-color: #ffa94d;
}
.wrapper div:nth-child(2) {
grid-column: 3;
grid-row: 2 / 4;
}
.wrapper div:nth-child(5) {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
.wrapper {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 100px;
gap: 10px;
grid-auto-flow: dense;
}
Анонимные элементы сетки
В спецификации упоминаются анонимные элементы сетки. Они создаются, если у вас в контейнере сетки есть строка текста, которая не заключена ни в один другой элемент. В примере ниже у нас есть три элемента сетки, предполагая, что вы установили родительский элемент с классом grid в display: grid. Первый — анонимный элемент, так как он не имеет заключительной разметки, этот элемент всегда обрабатывается с помощью правил автоматического размещения. Другие два — элементы сетки, заключенные в div, они могут быть размещены автоматически, или вы можете разместить их с помощью метода позиционирования в сетке.
<div class="grid"> I am a string and will become an anonymous item <div>A grid item</div> <div>A grid item</div> </div>
Анонимные элементы всегда размещаются автоматически, так как их невозможно нацелить. Поэтому, если по какой-либо причине у вас в сетке есть некоторый необработанный текст, знайте, что он может появиться в неожиданном месте, так как он будет размещаться автоматически в соответствии с правилами автоматического размещения.
Примеры использования автоматического размещения
Автоматическое размещение полезно всякий раз, когда у вас есть коллекция элементов. Это могут быть элементы, которые не имеют логического порядка, например, галерея фотографий или список товаров. В этом случае вы можете выбрать использование режима плотного размещения для заполнения всех пробелов в вашей сетке. В моём примере галереи изображений у меня есть некоторые изображения пейзажей и некоторые портретные. Я задал изображения пейзажей — с классом landscape — чтобы занимать две дорожки столбцов. Затем я использую grid-auto-flow: dense для создания плотно упакованной сетки.
Попробуйте удалить строку grid-auto-flow: dense , чтобы увидеть, как содержимое перераспределяется, оставляя пробелы в макете.
<ul class="wrapper">
<li>
<img
alt="A colorful hot air balloon against a clear sky"
src="https://mdn.github.io/shared-assets/images/examples/balloon.jpg" />
</li>
<li class="landscape">
<img
alt="Three hot air balloons against a clear sky, as seen from the ground"
src="https://mdn.github.io/shared-assets/images/examples/balloons-small.jpg" />
</li>
<li class="landscape">
<img
alt="Three hot air balloons against a clear sky, as seen from the ground"
src="https://mdn.github.io/shared-assets/images/examples/balloons-small.jpg" />
</li>
<li class="landscape">
<img
alt="Three hot air balloons against a clear sky, as seen from the ground"
src="https://mdn.github.io/shared-assets/images/examples/balloons-small.jpg" />
</li>
<li>
<img
alt="A colorful hot air balloon against a clear sky"
src="https://mdn.github.io/shared-assets/images/examples/balloon.jpg" />
</li>
<li>
<img
alt="A colorful hot air balloon against a clear sky"
src="https://mdn.github.io/shared-assets/images/examples/balloon.jpg" />
</li>
</ul>
.wrapper {
display: grid;
grid-template-columns: repeat(3, minmax(120px, 1fr));
gap: 10px;
grid-auto-flow: dense;
}
.wrapper li.landscape {
grid-column-end: span 2;
}
Автоматическое размещение также может помочь в размещении элементов интерфейса, которые имеют логический порядок. Примером является список определений в следующем примере. Списки определений представляют собой интересную задачу для форматирования, так как они плоские, ничего не заключает группы элементов dt и dd. В моём примере я позволяю автоматическому размещению размещать элементы, однако у меня есть классы, которые начинаются с dt в столбце 1 и dd в столбце 2, это гарантирует, что термины будут располагаться с одной стороны, а определения — с другой, независимо от того, сколько у нас каждого.
<div class="wrapper">
<dl>
<dt>Mammals</dt>
<dd>Cat</dd>
<dd>Dog</dd>
<dd>Mouse</dd>
<dt>Birds</dt>
<dd>Pied Wagtail</dd>
<dd>Owl</dd>
<dt>Fish</dt>
<dd>Guppy</dd>
</dl>
</div>
dl {
display: grid;
grid-template-columns: auto 1fr;
max-width: 300px;
margin: 1em;
line-height: 1.4;
}
dt {
grid-column: 1;
font-weight: bold;
}
dd {
grid-column: 2;
}
Что пока не поддерживается в автоматическом размещении
Есть несколько вопросов, которые часто возникают. В настоящее время мы не можем выполнять такие действия, как нацеливание на каждый другой ячейку сетки с нашими элементами. Связанная проблема, возможно, уже пришла вам в голову, если вы следовали последнему руководству о именованных линиях в сетке. Это было бы создание правила, которое говорило: «разместите элементы автоматически по следующей линии с именем "n"», и сетка затем пропускала другие линии. В репозитории CSSWG GitHub есть открытая проблема по этому вопросу, и вы можете добавить свои примеры использования в неё.
Возможно, вы придумаете свои собственные варианты использования для автоматического размещения или любой другой части макета сетки. Если вы это сделаете, откройте проблему или добавьте её в существующую проблему, которая могла бы решить ваш случай использования. Это поможет сделать будущие версии спецификации лучше.
© 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/Auto-placement_in_grid_layout