Responsive checkerboard grid in CSS?
Asked Answered
N

2

6

This snippet contains a responsive grid. As you change the screen width the number of columns varies automatically. Sometimes there is an even number of columns, sometimes there is an odd number. When there is an odd number of columns, the cells alternate colours like a checkerboard, but when there is an even number of columns, they do not. Is there any way to achieve the checkerboard effect for even numbers of columns as well as odd numbers? Does it require Javascript, or can it be done using CSS alone?

body {
  margin: 0;
}
.checkers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8em, 1fr)); 
  padding: 1em;
  gap: 1em;
}
.checkers>div {
  background-color: red;
  aspect-ratio: 1/1;
}
.checkers>div:nth-child(even) {
  background-color: blue;
}
<div class="checkers">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
 </div>
Nitro answered 8/12, 2022 at 23:12 Comment(2)
Tricky. I think the simplest CSS solution would keep the layout with an odd number of columns at all times using media queries. Otherwise, JS.Proof
Until ::nth-row is supported some day, there is no great CSS solution for this.Beldam
C
1

If you can omit the use of 1fr and consider fixed width elements, you can do this using some background trick:

.checkers {
  display: grid;
  grid-template-columns: repeat(auto-fit, 8em);
  padding: 1em;
  gap: 1em;
  position: relative; /* Relative on the main container */
  z-index:0;
}

.checkers > div {  
  aspect-ratio: 1;
  clip-path: inset(0); /* clip the pseudo element to element*/
}
.checkers > div:before {
  content:"";
  position: absolute;
  z-index:-1;
  inset: 1em; /* same as padding */
  /* create a checkboard pattern using gradient
     18em = (8em + 1em[gap])*2
  */
  background: repeating-conic-gradient(red 0 25%,blue 0 50%) 0 0/18em 18em;
}

body {
 margin: 0;
 background: pink;
 counter-reset: num;
}
.checkers div:after {
 content: counter(num);
 counter-increment: num;
 color:#fff;
 font-weight:900;
 font-size: 25px;
}
<div class="checkers">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>
Corabella answered 10/12, 2022 at 8:42 Comment(2)
Wow, that's a great background trick, I never knew you could repeat gradients like that.Nitro
This is an awesome solution, however it would be a much better SO answer if you were to explain what is going on with the "background trick" how does this work?Paletot
P
-1

As far as I can tell, this cannot be done for an even number of columns. What you can do is ensure there is always an odd number of columns. You will need to explicitly set an odd number of columns for grid-template-columns, which can be adjusted with media queries.

In this snippet I have borrowed the breakpoints from Bootstrap as a starting point. I have initially set the grid to have 3 columns minimum (grid-template-columns: repeat(3, 1fr);), then increment by 2 (next odd number) at each breakpoint up to 13 columns:

body {
  margin: 0;
}

.checkers {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  padding: 1em;
  gap: 1em;
  overflow: hidden;
}

.checkers>div {
  background-color: red;
  aspect-ratio: 1/1;
}

.checkers>div:nth-child(even) {
  background-color: blue;
}

@media (min-width: 576px) {
  .checkers {
    grid-template-columns: repeat(5, 1fr);
  }
}

@media (min-width: 768px) {
  .checkers {
    grid-template-columns: repeat(7, 1fr);
  }
}

@media (min-width: 992px) {
  .checkers {
    grid-template-columns: repeat(9, 1fr);
  }
}

@media (min-width: 1200px) {
  .checkers {
    grid-template-columns: repeat(11, 1fr);
  }
}

@media (min-width: 1400px) {
  .checkers {
    grid-template-columns: repeat(13, 1fr);
  }
}
<div class="checkers">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

You can adjust the breakpoint sizes to be multiples of your grid square sizes to get it dialed in to your liking.

Paletot answered 9/12, 2022 at 20:57 Comment(2)
This is certainly a workaround worth considering, however if I were to use it I would dispense with the minmax expression. grid-template-columns: repeat(5, 1fr);Nitro
@BrettDonald done, yes that's much better. I'm not really that familiar with all the CSS you are using just found the key part to change without altering what you had too much.Paletot

© 2022 - 2024 — McMap. All rights reserved.