How do I make a responsive grid with a checkered pattern?

北城以北 提交于 2020-12-29 12:56:21

问题


I have a responsive grid layout. There can be any number of columns depending on the window width.

I am trying to make the grid have a checkered pattern, so I use the odd and even selectors to color the grid cells.

But it only works when the number of columns is odd. When the number of columns is even, it becomes a striped pattern.

Is there a CSS property/selector to solve this, or a better way to do it?

Here's the simplified code of my project showing the problem:

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

回答1:


If you know the number of rows or you know at least their max value you can easily achieve this using gradient and multiple background. The only drawback is that the coloration will be on the container so you can have empty cells colored too.

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

To avoid the coloration of the empty cells we can consider a hack using pseudo element but without transparency:

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

To simulate the gaps you can consider outline on the grid items (still without transparency):

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

If you want to have transparency for the gaps you can consider mask that you define with gradient. You will need an extra wrapper for this:

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

Using mask-composite we don't need an extra layer

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


来源:https://stackoverflow.com/questions/57551296/how-do-i-make-a-responsive-grid-with-a-checkered-pattern

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!