On one hand, creating simple checkered backgrounds with CSS is easy. On the other hand, though, unless we are one of the CSS-gradient-ninjas, we are kind of stuck with basic patterns.
At least that’s what I thought while staring at the checkered background on my screen and trying to round those corners of the squares just a little…until I remembered my favorite bullet point glyph — ✦
— and figured that if only I could place it over every intersection in the pattern, I’ll surely get the design I want.
Turns out it’s possible! Here’s the proof.
Let’s start with the basic pattern:
<div></div>
div {
background:
repeating-linear-gradient(
to right, transparent,
transparent 50px,
white 50px,
white 55px
),
repeating-linear-gradient(
to bottom, transparent,
transparent 50px,
white 50px,
white 55px
),
linear-gradient(45deg, pink, skyblue);
/* more styles */
}
What that gives us is a repeating background of squares that go from pink to blue with 5px
white gaps between them. Each square is fifty pixels wide and transparent. This is created using repeating-linear-gradient
, which creates a linear gradient image where the gradient repeats throughout the containing area.
In other words, the first gradient in that sequence creates white horizontal stripes and the second gradient creates white vertical stripes. Layered together, they form the checkered pattern, and the third gradient fills in the rest of the space.
Now we add the star glyph I mentioned earlier, on top of the background pattern. We can do that by including it on the same background
property as the gradients while using an encoded SVG for the shape:
div {
background:
repeat left -17px top -22px/55px 55px
url("data:image/svg+xml,
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 35px 35px'>
<foreignObject width='35px' height='35px'>
<div xmlns='http://www.w3.org/1999/xhtml' style='color: white; font-size: 35px'>✦</div>
</foreignObject>
</svg>"
),
repeating-linear-gradient(
to right, transparent,
transparent 50px,
white 50px,
white 55px
),
repeating-linear-gradient(
to bottom, transparent,
transparent 50px,
white 50px,
white 55px
),
linear-gradient(45deg, pink, skyblue);
/* more style */
}
Let’s break that down. The first keyword, repeat
, denotes that this is a repeating background image. Followed by that is the position and size of each repeating unit, respectively (left -17px top -22px/55px 55px
). This offset position is based on the glyph and pattern’s size. You’ll see below how the glyph size is given. The offset is added to re-position the repeating glyph exactly over each intersection in the checkered pattern.
The SVG has an HTML <div>
carrying the glyph. Notice that I declared a font-size
on it. That ultimately determines the border radius of the squares in the checkerboard pattern — the bigger the glyph, the more rounded the squares. The unrolled SVG from the data URL looks like this:
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 35px 35px'>
<foreignObject width='35px' height='35px'>
<div xmlns='http://www.w3.org/1999/xhtml' style='color:white;font-size:35px'>✦</div>
</foreignObject>
</svg>
Now that a CSS pattern is established, let’s add a :hover
effect where the glyph is removed and the white lines are made slightly translucent by using rgb()
color values with alpha transparency.
div:hover {
background:
repeating-linear-gradient(
to right, transparent,
transparent 50px,
rgb(255 255 255 / 0.5) 50px,
rgb(255 255 255 / 0.5) 55px
),
repeating-linear-gradient(
to bottom, transparent,
transparent 50px,
rgb(255 255 255 / 0.5) 50px,
rgb(255 255 255 / 0.5) 55px
),
linear-gradient(45deg, pink, skyblue);
box-shadow: 10px 10px 20px pink;
}
There we go! Now, not only do we have our rounded corners, but we also have more control control over the pattern for effects like this:
Again, this whole exercise was an attempt to get a grid of squares in a checkerboard pattern that supports rounded corners, a background gradient that serves as an overlay across the pattern, and interactive styles. I think this accomplishes the task quite well, but I’m also interested in how you might’ve approached it. Let me know in the comments!
I would use mask and multiple gradient to achieve this. The syntax can be a bit verbose but with CSS variables we can shorten it plus we can easily adjust everything (the size, the gap, the radius)
Clever! It looks like the glyph may be rendering slightly off. In Chrome 105 and Firefox 104 the glyphs appear to be 5-10px lower than intended.
✦ is a red herring here that has ruined what would have been perfectly good approach.
You shouldn’t use text, just a
path
. Text opens you up to rendering inconsistencies since you can’t control the font that will be used. The examples shown look terrible for me because I have different metrics to what the author designed it for.(Also there was no cause to get clever with
foreignObject
;text
is quite up to the task, and the wholeforeignObject
/div
dance would have been something like<text font-size='35' fill='white' y='30'>✦</text>
.)You could then also consider shoving more and more of the fanciness into the SVG. SVG supports patterns, gradients, &c. even more powerful than CSS.
I expect the author of this article was only giving one way of achieving the pattern. If anyone has another way I would expect to see some constructive criticism and not a slaying of the method used. Simply giving your own version and the reasons why would be enough