#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. это то, что я уже сказал в своем ответе, зачем повторяться?