Сделать сетку CSS последней строкой, чтобы заполнить незавершенные столбцы

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

Смотрите изображение:

Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
0
0
87
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете сделать это, выбрав последнего нечетного ребенка и указав grid-column: 1 / -1.

.grid {
  border: 2.5px solid gray;
  border-radius: 10px;
  width: fit-content;
  height: fit-content;
  padding: 1em;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1em;
}

.grid__item {
  min-width: 100px;
  min-height: 100px;
  border: 2.5px solid palevioletred;
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
}

.grid__item:nth-child(2n-1):last-child {
  background: pink;
  grid-column: 1 / -1;
}
<div class = "grid">
  <div class = "grid__item">1</div>
  <div class = "grid__item">2</div>
  <div class = "grid__item">3</div>
  <div class = "grid__item">4</div>
  <div class = "grid__item">5</div>
  <div class = "grid__item">6</div>
  <div class = "grid__item">7</div>
</div>

Отличное исправление для сетки 2x2, которое на самом деле решает мою проблему, но чтобы лучше ответить на вопрос, есть ли способ сделать это, который решает это для сетки 3x3 только с 1 или 2 элементами в последней строке?

Liam Pillay 13.04.2023 07:16

нет нет. Вы не используете сетку для этой задачи.

tacoshy 13.04.2023 08:06

Вам понадобится display: flex и немного математики.

Сначала создайте элемент контейнера и его элементы:

<div id = "grid">
  <div class = "item">
    <!-- ... -->
  </div>
  <!-- ...and more. -->
</div>

Затем сделайте его флексбоксом с помощью flex-wrap: wrap:

#grid {
  display: flex;
  flex-wrap: wrap;
}

Пусть номер столбца, который мы хотим, будет c. По наблюдениям мы знаем, что есть c столбцов (по определению), c - 1 промежутков и 2 заполнения, которые в сумме составляют 100% ширины контейнера:

┌──────────────────────────┐
│ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │
│p│c1│g│c2│g│c3│g│c4│g│c5│p│
│ └──┘ └──┘ └──┘ └──┘ └──┘ │
│                          │
│                          │
│                          │
│                          │
└──────────────────────────┘

Это означает, что ширина элемента может быть рассчитана как:

w = (100% - (g * (c - 1)) - p * 2) / c

Мы соответствующим образом переводим это в CSS и добавляем flex-grow: 1, чтобы последние элементы занимали все оставшиеся места:

.item {
  flex-grow: 1;
  width: calc((100% - var(--gap) * (var(--columns) - 1) - var(--padding) * 2) / var(--columns));
}

Попробуй это:

const grid = document.querySelector('#grid');
const input = document.querySelector('input');

input.addEventListener('input', function() {
  grid.style.setProperty('--columns', this.value);
});

const l = 30 + Math.random() * 71 | 0;

for (let i = 1; i < l; i++) {
  const item = document.createElement('div');
  item.classList.add('item');
  item.textContent = i;
  grid.appendChild(item);
}
#grid {
  --columns: 3;
  --padding: 1em;
  --gap: 1em;
  
  display: flex;
  flex-flow: row wrap;
  gap: var(--gap);
  border: 1px solid #000;
  padding: var(--padding);
}

.item {
  flex-grow: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100px;
  width: calc(
    (
      100% -
      var(--gap) * (var(--columns) - 1) -
      var(--padding) * 2
    ) /
    var(--columns)
  );
  background: #ddd;
}

label {
  position: fixed;
  bottom: 2em;
  left: 2em;
}
<div id = "grid"></div>

<label>
  Columns:
  <input type = "range" min = "1" max = "10" step = "1" value = "3">
</label>

Не рассчитывайте отступы и, кроме того, границу. Сделайте свою жизнь проще и используйте box-sizing: border-box. Для родительского элемента применяется значение по умолчанию content-box, если отступ не используется для ширины в первую очередь. Нет необходимости рассчитывать отступы там.

tacoshy 13.04.2023 08:21

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

InSync 13.04.2023 08:40
Ответ принят как подходящий

В целом это задача не для CSS-Grid, а для Flexbox. Во Flexbox вы можете использовать flex-grow: 1, чтобы элементы увеличивались, чтобы заполнить оставшееся пространство.

Flexbox может использовать flex-wrap: wrap, чтобы элементы, которые переполняются, переносились на следующую строку. Сложность здесь в том, что ширина каждого вызова должна быть рассчитана правильно.

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

width = ((100% - (size of gaps * (amount of columns - 1))) / amount of columns)

Для корректной работы для модели коробки контейнеров должно быть установлено значение по умолчанию (content-box), а для модели коробки карточек должно быть установлено значение border-box, чтобы отступы и границы были включены в ширину:

:root {
  --gap: 1em;
}

section {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap);
}

.col-2 {
  --column: 2;
}

.col-3 {
  --column: 3; 
}

section > div {
  flex-grow: 1;
  box-sizing: border-box;
  width: calc((100% - (var(--gap) * (var(--column) - 1))) / var(--column));
}


/* for demo purpose only */
section > div {
  border: 2px dashed red;
  text-align: center;
  padding: 2em;
}
<h1>Grid with 2 columns and 3 cards</h1>
<section class = "col-2">
  <div>1</div>
  <div>2</div>
  <div>3</div>
</section>

<h1>Grid with 3 columns and 4 cards</h1>
<section class = "col-3">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
</section>

<h1>Grid with 3 columns and 5 cards</h1>
<section class = "col-3">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
</section>

Другие вопросы по теме