CSS сетка — максимальное количество столбцов без медиа-запросов

#html #css #fivem

Вопрос:

Можно ли определить сетку с максимальным количеством столбцов, но разрешить перенос элементов в новые строки при изменении ширины экрана?

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

Вот кодовое описание одного метода с использованием Flexbox:

CSS:

 .flex-container {
  display: flex;
  flex-wrap: wrap;
}
 

Другой метод заключается в использовании сетки:

 .grid {
  display: grid;
  counter-reset: grid-items;
  position: relative;
}


.grid--auto-fit {
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
 

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

Комментарии:

1. вы пробовали : grid-template-columns: repeat(auto-fit, minmax(25%, 1fr)); для четырех столбцов максимум ? или 12,5% для восьми и так далее ?

Ответ №1:

С помощью CSS-сетки вы можете рассмотреть возможность использования max(width, 100%/N) параметра «Где N максимальное количество столбцов». Если ширина контейнера увеличится, 100%/N то наверняка будет больше , чем width , таким образом, у нас будет не более N элементов в строке.

 .grid-container {
  --n: 4; /* The maximum number of columns */
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(max(200px, 100%/var(--n)), 1fr));
}

.grid-item {
  background: tomato;
  padding: 5px;
  height: 50px;
  margin: 10px;

  line-height: 50px;
  color: white;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  box-sizing: border-box;
} 
 <div class="grid-container">
  <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 class="grid-item">8</div>
</div>

<div class="grid-container" style="--n:3">
  <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 class="grid-item">8</div>
</div> 

С пробелами:

 .grid-container {
  --n: 4; /* The maximum number of columns */
  display: grid;
  grid-template-columns: repeat(auto-fill,
           minmax(max(200px,(100% - (var(--n) - 1)*10px)/var(--n)), 1fr));
  gap: 10px;
  margin: 5px;
}

.grid-item {
  background: tomato;
  padding: 5px;
  height: 50px;

  line-height: 50px;
  color: white;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  box-sizing: border-box;
} 
 <div class="grid-container">
  <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 class="grid-item">8</div>
</div>

<div class="grid-container" style="--n:3">
  <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 class="grid-item">8</div>
</div> 

С помощью flexbox вы можете просто установить a max-width в контейнер, так как ваши элементы имеют фиксированную ширину:

 .flex-container {
  display: flex;
  flex-wrap: wrap;
  max-width: calc(5*(200px   20px));
}

.flex-item {
  background: tomato;
  padding: 5px;
  width: 200px;
  height: 100px;
  margin: 10px;

  line-height: 100px;
  color: white;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  box-sizing: border-box;
} 
 <div class="flex-container wrap">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>
</div> 

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

Если вы хотите, чтобы ваши элементы расширялись и покрывали всю ширину, вы можете использовать трюк, min-width как показано ниже:

 .flex-container {
  display: flex;
  flex-wrap: wrap;
}

.flex-item {
  background: tomato;
  padding: 5px;
  min-width: 200px;
  width: calc(100%/5 - 20px); /* 5 columns */
  height: 100px;
  margin: 10px;

  line-height: 100px;
  color: white;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  box-sizing: border-box;
} 
 <div class="flex-container wrap">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>
</div> 

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

 .flex-container {
  display: flex;
  flex-wrap: wrap;
}

.flex-item {
  --m: 10px;
  background: tomato;
  padding: 5px;
  min-width: 200px;
  width: calc(100%/5 - 2*var(--m)); /* 5 columns */
  height: 100px;
  margin: var(--m);

  line-height: 100px;
  color: white;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  box-sizing: border-box;
} 
 <div class="flex-container wrap">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>
</div> 

Вы также можете подумать flex-grow , хотите ли вы, чтобы ваш элемент всегда расширялся (даже если есть перенос), но вы можете столкнуться с проблемой последней строки, которую вам нужно исправить с помощью некоторых хаков:

 .flex-container {
  display: flex;
  flex-wrap: wrap;
  --m: 10px;
}

.flex-item {
  background: tomato;
  padding: 5px;
  min-width: 200px;
  flex-grow: 1;
  width: calc(100%/5 - 2*var(--m)); /* 5 columns */
  height: 100px;
  margin: var(--m);

  line-height: 100px;
  color: white;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  box-sizing: border-box;
}

.flex-container span {
  min-width: 200px;
  flex-grow: 1;
  width: calc(100%/5 - 2*var(--m)); /* 5 columns */
  margin: 0 var(--m);
} 
 <div class="flex-container wrap">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>

  <!-- 4 empty elements to fix the issue (we can also use a pseudo element) -->
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div> 

В приведенном ниже примере мы увеличили количество столбцов до 5, поэтому нам понадобится как минимум 4 пустых элемента, чтобы устранить проблему, если в последней строке будет от одного до 4 элементов.

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

Чтобы сделать его более гибким, вот идея с переменными CSS:

 .flex-container {
  display: flex;
  flex-wrap: wrap;
  border: 1px solid;
  --m: 10px;
  --n: 5;
  --width: 150px;
}

.flex-item {
  background: tomato;
  min-width: var(--width);
  flex-grow: 1;
  width: calc(100%/var(--n) - 2*var(--m));
  height: 50px;
  margin: var(--m);

  box-sizing: border-box;
}

.flex-container span {
  display: contents; /* Each span will give us 2 elements */
}
.flex-container span: before,
.flex-container span: after,
.flex-container: before,
.flex-container: after{
  content: "";
  min-width: var(--width);
  flex-grow: 1;
  width: calc(100%/var(--n) - 2*var(--m));
  margin :0 var(--m);
  order: 1; /* We make sure they are at the end */
} 
 <div class="flex-container wrap">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>

  <!-- A lot of elements !! -->
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="flex-container wrap" style="--n:10">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>

  <!-- A lot of elements !! -->
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="flex-container wrap" style="--n:3">
  <div class="flex-item">1</div>
  <div class="flex-item">2</div>
  <div class="flex-item">3</div>
  <div class="flex-item">4</div>
  <div class="flex-item">5</div>
  <div class="flex-item">6</div>
  <div class="flex-item">7</div>
  <div class="flex-item">8</div>

  <!-- A lot of elements !! -->
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div> 

Раньше я display: contents мог устанавливать N пустых элементов, которые позже будут рассматриваться как 2*N, что может уменьшить код.

Если у вас будет 7 столбцов, нам понадобится всего 6 дополнительных элементов. Мы можем использовать два псевдоэлемента, а затем только 2 пустых элемента, чтобы покрыть оставшиеся 4.

Комментарии:

1. Это здорово, я все еще удивлен, что для этого нет встроенного решения.

2. @BenAllen у нас, вероятно, будет это в будущей итерации 😉 CSS-сетка и Flexbox все еще новы, и они будут обновляться все больше и больше.

Ответ №2:

Вы не можете явно сделать это ни для flexbox, ни для CSS — сетки, но вы можете использовать взлом с использованием переменных CSS (обычно это все, что вам нужно).


Макет сетки CSS

Например, вы можете установить глобальный номер столбца в то :root время как конкретный номер столбца на оболочке сетки — см. Таблицу CSS ниже с четырьмя столбцами, установленными глобально:

 :root {
  --columns: 3;
}

.grid {
  display: grid;
  grid-gap: 10px;
  /* Adjusting for the 10px grid-gap as well */
  grid-template-columns: repeat(auto-fit, minmax(calc(100% / var(--columns) - 20px), 1fr));
}

.grid > * {
  background-color: green;
  height: 200px;
} 
 <div class="grid">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
</div> 

Теперь вы можете установить правило для количества столбцов в контейнере сетки --columns , повторно объявив (или вы можете добавить JavaScript class , содержащий --columns объявление) — см. демонстрацию ниже:

 :root {
  --columns: 3;
}

.grid {
  display: grid;
  grid-gap: 10px;
  --columns: 4; /* Redefine the number of columns */
  grid-template-columns: repeat(auto-fit, minmax(calc(100% / var(--columns) - 20px), 1fr));
}

.grid > * {
  background-color: green;
  height: 200px;
} 
 <div class="grid">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
</div> 

Гибкий ящик

Аналогичные аргументы справедливы для flexboxes — см. упрощенную демонстрацию ниже:

 :root {
  --columns: 3;
}

.flexbox {
  display: flex;
  flex-wrap: wrap;
  --columns: 4; /* Redefine the number of columns */
}

.flexbox > * {
  background-color: green;
  height: 200px;
  margin: 10px;
  flex-basis: calc(100% / var(--columns) - 20px);
} 
 <div class="flexbox">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
</div> 

Комментарии:

1. Насколько это совместимо на данный момент? Потому что это выглядит довольно полезным.

2. Итак, в данном случае, что это за собственность --columns . Насколько я понимаю, вы в основном преобразуете его в число с помощью var() функции, но как это работает с :root элементом?

3. они называются переменными CSS , но они не являются в строгом смысле этого слова — просто заменяемые свойства, которые вы можете использовать… :root представляет html элемент

4. Таким образом, в основном они будут интерпретироваться как правила, которые непонятны для браузера, пока они не будут преобразованы в переменную с помощью var() функции?

5. Ладно, это выглядит довольно полезным. 🙂

Ответ №3:

Немного разбравшись в математике, вы можете добавить процент в максимальную функцию в пределах minmax. Таким образом, он будет разбит на 200 пикселей, но расширится, чтобы заполнить 1/3 страницы (в данном случае, потому что я использовал 33%. Просто добавьте туда любой процент, какой вы хотите).

grid-template-columns: repeat(auto-fit, minmax(max(200px, 33%), 1fr));

Комментарии:

1. это то, что я уже сказал в своем ответе, зачем повторяться?