CSS 网格 - 没有媒体查询的最大列数 [英] CSS grid - maximum number of columns without media queries

查看:14
本文介绍了CSS 网格 - 没有媒体查询的最大列数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以定义具有最大列数的网格,但允许元素在屏幕宽度改变时换行到新行上?

我已经实现了允许行换行到新行的类,但没有最大列数.

这是一种方法的CodePen使用弹性盒:

CSS:

.flex-container {显示:弹性;flex-wrap: 包裹;}

另一种方法是使用网格:

.grid {显示:网格;计数器重置:网格项;位置:相对;}.grid--自动适应{网格模板列:重复(自动适应,minmax(200px,1fr));}

我想要一个相当通用的解决方案.我想在没有 JavaScript 或媒体查询的情况下实现什么?

解决方案

有了 CSS grid 你可以考虑使用 max(width, 100%/N) where N> 是最大列数.如果容器的宽度增加,100%/N肯定会大于width,因此我们不会超过N每行元素.

.grid-container {--n: 4;/* 最大列数 */显示:网格;网格模板列:重复(自动填充,minmax(max(200px,100%/var(--n)),1fr));}.grid-item {背景:番茄;填充:5px;高度:50px;边距:10px;行高:50px;白颜色;字体粗细:粗体;字体大小:2em;文本对齐:居中;box-sizing: 边框框;}

<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 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>

有间隙:

.grid-container {--n: 4;/* 最大列数 */显示:网格;网格模板列:重复(自动填充,minmax(max(200px,(100% - (var(--n) - 1)*10px)/var(--n)), 1fr));间隙:10px;边距:5px;}.grid-item {背景:番茄;填充:5px;高度:50px;行高:50px;白颜色;字体粗细:粗体;字体大小:2em;文本对齐:居中;box-sizing: 边框框;}

<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 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>


使用 flexbox,您可以简单地为容器设置 max-width,因为您的元素具有固定宽度:

.flex-container {显示:弹性;flex-wrap: 包裹;最大宽度:calc(5*(200px + 20px));}.flex-item {背景:番茄;填充:5px;宽度:200px;高度:100px;边距:10px;行高:100px;白颜色;字体粗细:粗体;字体大小:2em;文本对齐:居中;box-sizing: 边框框;}

<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>

唯一的缺点是您需要知道元素的宽度及其边距才能正确设置max-width.

如果您希望元素扩展并覆盖所有宽度,您可以使用一个带有 min-width 的技巧,如下所示:

.flex-container {显示:弹性;flex-wrap: 包裹;}.flex-item {背景:番茄;填充:5px;最小宽度:200px;宽度:计算(100%/5 - 20px);/* 5 列 */高度:100px;边距:10px;行高:100px;白颜色;字体粗细:粗体;字体大小:2em;文本对齐:居中;box-sizing: 边框框;}

<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>

在这里您还需要考虑边距.您可以使用 CSS 变量轻松地使其更加灵活:

.flex-container {显示:弹性;flex-wrap: 包裹;}.flex-item {--m: 10px;背景:番茄;填充:5px;最小宽度:200px;宽度:calc(100%/5 - 2*var(--m));/* 5 列 */高度:100px;边距:var(--m);行高:100px;白颜色;字体粗细:粗体;字体大小:2em;文本对齐:居中;box-sizing: 边框框;}

<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>

如果您希望元素始终扩展(即使有换行),您也可以考虑 flex-grow,但您可能会面临需要修复的最后一行的问题一些技巧:

.flex-container {显示:弹性;flex-wrap: 包裹;--m: 10px;}.flex-item {背景:番茄;填充:5px;最小宽度:200px;弹性增长:1;宽度:calc(100%/5 - 2*var(--m));/* 5 列 */高度:100px;边距:var(--m);行高:100px;白颜色;字体粗细:粗体;字体大小:2em;文本对齐:居中;box-sizing: 边框框;}.flex-容器跨度{最小宽度:200px;弹性增长:1;宽度:calc(100%/5 - 2*var(--m));/* 5 列 */边距:0 var(--m);}

<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 个空元素来解决这个问题(我们也可以使用伪元素)--><span></span><span></span><span></span><span></span>

在下面的示例中,我们将列数设为 5,因此我们将需要至少 4 个空元素来解决问题,以防我们在最后一行中有 1 到 4 个元素.

当然,这是一个缺点,但由于您知道列数,因此您可以轻松设置这些空元素,并且不需要任何 JavaScript.

为了让它更灵活,这里有一个关于 CSS 变量的想法:

.flex-container {显示:弹性;flex-wrap: 包裹;边框:1px 实心;--m: 10px;--n: 5;--宽度:150px;}.flex-item {背景:番茄;最小宽度:var(--width);弹性增长:1;宽度: calc(100%/var(--n) - 2*var(--m));高度:50px;边距:var(--m);box-sizing: 边框框;}.flex-容器跨度{显示:内容;/* 每个跨度会给我们 2 个元素 */}.flex-container 跨度:之前,.flex-container 跨度:之后,.flex-container:之前,.flex 容器:后{内容: "";最小宽度:var(--width);弹性增长:1;宽度: calc(100%/var(--n) - 2*var(--m));边距:0 var(--m);订单:1;/* 我们确保它们在最后 */}

<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><!-- 很多元素!!--><span></span><span></span><span></span><span></span><span></span><span></span><span></span>

<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><!-- 很多元素!!--><span></span><span></span><span></span><span></span><span></span><span></span><span></span>

<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><!-- 很多元素!!--><span></span><span></span><span></span><span></span><span></span><span></span><span></span>

我使用 display:contents 可以设置 N 个空元素,以后会被认为是 2*N,这样可以减少代码.

如果您有 7 列,我们将只需要 6 个额外的元素.我们可以使用这两个伪元素然后只用2个空元素来覆盖剩下的4个.

Is it possible to define a grid with a maximum number of columns, but allow elements to wrap onto new rows when the screen width changes?

I have implemented classes that allow rows to wrap onto new rows, but there is no maximum number of columns.

Here is a CodePen of one method using Flexbox:

CSS:

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

Another method is to use a grid:

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


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

I want a fairly generic solution to this. Is what I want to achieve possible without JavaScript or media queries?

解决方案

With CSS grid you can consider the use of max(width, 100%/N) where N is the maximum number of columns. If the width of the container increases, 100%/N will for sure be bigger than width, thus we won't have more than N elements per row.

.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>

With gaps:

.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>


With flexbox, you can simply set a max-width to the container since your elements have a fixed 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>

The only drawback is that you need to know the width of your elements and their margin to correctly set the max-width.

If you want your elements to expand and cover all the width, you can use a trick with min-width like below:

.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>

Here also you need to consider the margin. You can easily make this more flexible using CSS variables:

.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>

You can also consider flex-grow if you want your element to always expand (even when there is a wrap), but you may face the issue of the last row that you need to fix with some hacks:

.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>

In the example below, we made the number of columns to be 5 so we will need at least 4 empty elements to fix the issue in case we will have one to 4 elements in the last row.

Of course, this is a drawback, but since you know the number of columns you can easily set those empty elements and you won't need any JavaScript.

To make it more flexible, here is an idea with CSS variables:

.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>

I used display: contents to be able to set N empty elements that will later be considered as 2*N which can reduce the code.

If you will have 7 columns, we will only need 6 extra elements. We can use the two pseudo elements then only 2 empty element to cover the remaining 4.

这篇关于CSS 网格 - 没有媒体查询的最大列数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆