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>
Building a Responsive Grid-View First ensure that all HTML elements have the box-sizing property set to border-box . This makes sure that the padding and border are included in the total width and height of the elements. Read more about the box-sizing property in our CSS Box Sizing chapter.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With