如何制作一个具有棋盘格纹理的响应式网格?

6
我有一个响应式网格布局,根据窗口宽度可以有任意数量的列。 我想要让这个网格呈现棋盘格样式,所以我使用了 "odd" 和 "even" 选择器来着色网格单元格。 但仅当列数为奇数时才有效。当列数为偶数时,它将变成条纹状。 是否有CSS属性/选择器来解决此问题,或者更好的方法? 以下是我的项目简化代码,显示了问题:

.grid {
  display: grid;
  counter-reset: spans;
  grid-template-columns: repeat(var(--cols), 1fr);
  grid-gap: 1px;
}

.grid > * {
  counter-increment: spans;
  text-align: center;
  padding: 10px 0;
  color: #fff;
}

.grid > *::after {
  content: counter(spans);
}

/* Coloring */
.grid > *:nth-child(odd) {
  background-color: #789;
}

.grid > *:not(:nth-child(odd)) {
  background-color: #567;
}
<h2>Works when columns are odd</h2>
<div class="grid" style="--cols: 5;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<h2>Doesn't work while even</h2>
<div class="grid" style="--cols: 4;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>


没有 JavaScript 是不可能实现的。你正在给每个第二个 span 上色,想知道为什么这样做。 - dmuensterer
1
那么“even”变体应该是什么样子的呢?如果它应该是棋盘式的,那么必须有2个浅灰色单元格相互跟随,因此每一行都必须以不同的图案开始? - empiric
这是一个简单的数学问题,我猜用偶数不可能实现。 - Abhishek Pandey
1
@AbhishekPandey 如果你有兴趣,我提供了一个解决方案的想法 - Temani Afif
如果网格布局中有像 :nth-row:nth-column 这样的选择器就好了 :/ - Hao Wu
显示剩余5条评论
1个回答

3

如果您知道行数或至少知道它们的最大值,您可以使用渐变和多个背景轻松实现此目标。唯一的缺点是着色将在容器上进行,因此您也可以将空单元格着色。

.grid {
  display: grid;
  margin:10px 0;
  counter-reset: spans;
  grid-template-columns: repeat(var(--cols), 1fr);
  grid-auto-rows: 40px;
  --grad:repeating-linear-gradient(to right,red 0 calc(50% / var(--cols)),blue calc(50% / var(--cols))  calc(100% / var(--cols)));
  background:
    var(--grad),
    var(--grad),
    var(--grad),
    var(--grad),
    var(--grad);
  background-size:200% 40px;
  background-position: 
    0                        calc(0*40px),
    calc(100% / var(--cols)) calc(1*40px),
    0                        calc(2*40px),
    calc(100% / var(--cols)) calc(3*40px),
    0                        calc(4*40px);
  background-repeat:no-repeat;
}

.grid > * {
  counter-increment: spans;
  text-align: center;
  padding: 10px 0;
  color: #fff;
}

.grid > *::after {
  content: counter(spans);
}
<div class="grid" style="--cols: 5;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="grid" style="--cols: 4;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="grid" style="--cols: 8;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

为了避免空单元格的着色,我们可以考虑使用一个伪元素的hack,但不使用透明度:

.grid {
  display: grid;
  counter-reset: spans;
  margin:10px 0;
  grid-template-columns: repeat(var(--cols), 1fr);
  grid-auto-rows: 40px;
  --grad:repeating-linear-gradient(to right,red 0 calc(50% / var(--cols)),blue calc(50% / var(--cols))  calc(100% / var(--cols)));
  background:
    var(--grad),
    var(--grad),
    var(--grad),
    var(--grad),
    var(--grad);
  background-size:200% 40px;
  background-position: 
    0                        calc(0*40px),
    calc(100% / var(--cols)) calc(1*40px),
    0                        calc(2*40px),
    calc(100% / var(--cols)) calc(3*40px),
    0                        calc(4*40px);
  background-repeat:no-repeat;
  overflow:hidden;
}

.grid > * {
  counter-increment: spans;
  text-align: center;
  padding: 10px 0;
  color: #fff;
  position:relative;
}

.grid > *::after {
  content: counter(spans);
}
.grid > *:last-child::before {
  content:"";
  position:absolute;
  top:0;
  bottom:0;
  left:100%;
  width:100vw;
  background:#fff;
}
<div class="grid" style="--cols: 5;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="grid" style="--cols: 4;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="grid" style="--cols: 8;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

为了模拟空隙,您可以考虑在网格项上使用outline(仍然没有透明度):

.grid {
  display: grid;
  counter-reset: spans;
  margin:10px 0;
  grid-template-columns: repeat(var(--cols), 1fr);
  grid-auto-rows: 40px;
  --grad:repeating-linear-gradient(to right,red 0 calc(50% / var(--cols)),blue calc(50% / var(--cols))  calc(100% / var(--cols)));
  background:
    var(--grad),
    var(--grad),
    var(--grad),
    var(--grad),
    var(--grad);
  background-size:200% 40px;
  background-position: 
    0                        calc(0*40px),
    calc(100% / var(--cols)) calc(1*40px),
    0                        calc(2*40px),
    calc(100% / var(--cols)) calc(3*40px),
    0                        calc(4*40px);
  background-repeat:no-repeat;
  overflow:hidden;
}

.grid > * {
  counter-increment: spans;
  text-align: center;
  padding: 10px 0;
  color: #fff;
  position:relative;
  outline:1px solid #fff;
}

.grid > *::after {
  content: counter(spans);
}
.grid > *:last-child::before {
  content:"";
  position:absolute;
  top:0;
  bottom:0;
  left:100%;
  width:100vw;
  background:#fff;
}
<div class="grid" style="--cols: 5;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="grid" style="--cols: 4;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="grid" style="--cols: 8;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

如果您想为间隙增加透明度,可以考虑使用由渐变定义的mask。为此,您需要使用一个额外的包装器:

.grid {
  display: grid;
  counter-reset: spans;
  grid-template-columns: repeat(var(--cols), 1fr);
  grid-auto-rows: 40px;
  --grad:repeating-linear-gradient(to right,red 0 calc(50% / var(--cols)),blue calc(50% / var(--cols))  calc(100% / var(--cols)));
  background:
    var(--grad),
    var(--grad),
    var(--grad),
    var(--grad),
    var(--grad);
  background-size:200% 40px;
  background-position: 
    0                        calc(0*40px),
    calc(100% / var(--cols)) calc(1*40px),
    0                        calc(2*40px),
    calc(100% / var(--cols)) calc(3*40px),
    0                        calc(4*40px);
  background-repeat:no-repeat;
  -webkit-mask:
    repeating-linear-gradient(to right,
      transparent 0 1px,#fff 1px calc(100% / var(--cols) - 1px),
      transparent calc(100% / var(--cols) - 1px) calc(100% / var(--cols)))
    center/calc(100% + 2px) 100%;  
  mask:
    repeating-linear-gradient(to right,
      transparent 0 1px,#fff 1px calc(100% / var(--cols) - 1px),
      transparent calc(100% / var(--cols) - 1px) calc(100% / var(--cols)))
    center/calc(100% + 2px) 100%;  
}
.wrapper {
  margin:30px 0;
  -webkit-mask:repeating-linear-gradient(to bottom,
      transparent 0 1px,#fff 1px calc(40px - 1px),
      transparent calc(40px - 1px) 40px)
    center/100% calc(100% + 2px);
  mask:repeating-linear-gradient(to bottom,
      transparent 0 1px,#fff 1px calc(40px - 1px),
      transparent calc(40px - 1px) 40px)
    center/100% calc(100% + 2px);
}

.grid > * {
  counter-increment: spans;
  text-align: center;
  padding: 10px 0;
  color: #fff;
  position:relative;
}

.grid > *::after {
  content: counter(spans);
}


body {
  background:yellow;
}
<div class="wrapper">
<div class="grid" style="--cols: 5;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>
</div>

<div class="wrapper">
<div class="grid" style="--cols: 4;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>
</div>

<div class="wrapper">
<div class="grid" style="--cols: 8;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

</div>

使用“mask-composite”我们不需要额外的图层。

.grid {
  display: grid;
  counter-reset: spans;
  margin:30px 0;
  grid-template-columns: repeat(var(--cols), 1fr);
  grid-auto-rows: 40px;
  --grad:repeating-linear-gradient(to right,red 0 calc(50% / var(--cols)),blue calc(50% / var(--cols))  calc(100% / var(--cols)));
  background:
    var(--grad),
    var(--grad),
    var(--grad),
    var(--grad),
    var(--grad);
  background-size:200% 40px;
  background-position: 
    0                        calc(0*40px),
    calc(100% / var(--cols)) calc(1*40px),
    0                        calc(2*40px),
    calc(100% / var(--cols)) calc(3*40px),
    0                        calc(4*40px);
  background-repeat:no-repeat;
  -webkit-mask:
    repeating-linear-gradient(to right,
      transparent 0 1px,#fff 1px calc(100% / var(--cols) - 1px),
      transparent calc(100% / var(--cols) - 1px) calc(100% / var(--cols)))
    center/calc(100% + 2px) 100%,
    repeating-linear-gradient(to bottom,
      transparent 0 1px,#fff 1px calc(40px - 1px),
      transparent calc(40px - 1px) 40px)
    center/100% calc(100% + 2px);  
  mask:
    repeating-linear-gradient(to right,
      transparent 0 1px,#fff 1px calc(100% / var(--cols) - 1px),
      transparent calc(100% / var(--cols) - 1px) calc(100% / var(--cols)))
    center/calc(100% + 2px) 100%,
    repeating-linear-gradient(to bottom,
      transparent 0 1px,#fff 1px calc(40px - 1px),
      transparent calc(40px - 1px) 40px)
    center/100% calc(100% + 2px);  
    
    -webkit-mask-composite:destination-in;
    mask-composite:intersect;
}


.grid > * {
  counter-increment: spans;
  text-align: center;
  padding: 10px 0;
  color: #fff;
  position:relative;
}

.grid > *::after {
  content: counter(spans);
}


body {
  background:yellow;
}
<div class="grid" style="--cols: 5;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="grid" style="--cols: 4;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>

<div class="grid" style="--cols: 8;">
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
  <span></span>
</div>


这比我想象的要复杂得多,但它确实有效!虽然我也想为不同的检查器更改其他属性(如 colorborder 等),但目前似乎无法仅通过 CSS 轻松完成。非常感谢您提供的解决方案!您有我的尊重。 - Hao Wu
@HaoWu 如果您想要为文本和边框着色等,我们可以使代码更加复杂,但它将比实际的更加复杂 :) 如果您想要,我可以稍后尝试添加它。 - Temani Afif
也许我应该使用类似 [col="4"]:nth-child(4n), [col="4"]:nth-child(4n+1) 的东西。但需要为每个偶数分配:/ 使用scss循环会更好。 - Hao Wu
@HaoWu 是的,你可以这样做,但是你会有很多选择器,但如果最大列数不大,我想应该没问题。 - Temani Afif
@TemaniAfif 除了颜色搭配,其他都看起来不错,我的眼睛有点疼 :D - Abhishek Pandey
1
@AbhishekPandey 是的,我想确保没有人会错过这些颜色 ;) - Temani Afif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接