Checkered pattern for loading images, revisited

This past week, I decided to continue backfilling my blog with posts that I found on the 2013 version of my website. In doing so, I rediscovered an old post about using Photoshop’s checkered canvas for loading images.


I still love the idea, and actually still use the checkered icon for my favicon almost 10 years later, but what I don’t love is 25-year-old-me’s implementation for making this work—a repeating background image using a PNG.

img {
  background: url(/assets/checker.png);

It’s like finding out that all of the magician’s cards were your card. Sure, I give myself younger self some credit for a dead simple solution, but the 33-year-old me is irked by three things—the use of an image to create a shape, the image being a PNG instead of a vector, and the fact that it makes a request. As soon as I saw how I coded this, I felt like I could improve upon the idea and bring it up-to-date with the modern web.

First, I can’t use an image—where’s the fun in that? It’d be easy enough to use an SVG data URI, but that’s still not impressive. I did remember coming across a CSS trick where linear-gradient could be used to fake a checkered pattern. Similar to the CSS trick where you use transparent borders to create triangle, this one produces a repeating pattern of triangles that combine to make the checkered pattern.

The trick starts by angling the gradient at 45 degrees and removing its fade by setting both percentages to the same value.

The linear-gradient is only half of the trick, though. This approach takes more shape once you set the background-size to a square, so the linear-gradient appears as a grid of triangles.

By adding more linear gradients and adjusting their angles and percentages, the checkerboard really starts to come together. And to ensure the colors don’t overlap each other, the alternate color needs to be set to transparent.

The final piece of the puzzle is shifting the background-position in various directions to “assemble” the checkers using the triangles.

By animating the background positions, it’s much easier to see how the triangles combine to make the checkered pattern. The really cool part is that you can experiment with the background positions to make all sorts of different patterns.

Tweaking this solution to match the look of the Photoshop canvas results in a significant upgrade over my last approach (of simply loading a PNG). Now, I have a solution that’s a scalable vector, lets me adjust the colors and sizing, and doesn’t make a request.

While I do prefer the linear-gradient approach, I still think there’s more room for improvement. I’ve been addicted to CSS variables lately, and in this case, there’s an opportunity to extract a few of the values, so I’m left with only a single property to tweak. The background-position and background-size properties in particular can actually be whittled down to one variable—the size of the checker square.

From here, I can do the same with the colors and extract them into CSS variables. This again makes it easier to tweak the pattern because I only need to modify one value to update all of gradients/triangles at once. And, by extracting these values into variables that I can keep together at the top, I’m essentially creating an “API” for the CSS that makes up the checkered pattern.

While I was at it, I also added a --checkerAltColor variable for changing the alternate checker color. Since the linear-gradient requires the transparent value for the triangle trick, I can simply set the background-color to the alternate color.

When you reference a CSS variable, you can also specify a fallback color, in case the variable doesn’t exist. Ever since learning about fallbacks, I’ve actually found them to be useful as a debugging tool. If I assign different colors to the fallback values of each linear-gradient color, I can leave --checkerColor blank to let the debug colors come through. Then, as soon as I specify a real color for the --checkerColor variable, that color takes priority and hides the debug colors.

Now that I have my CSS working as expected, I can wrap it all up to use on my website. Below is the final CSS code, including a slight tweak on the checker color to use gainsboro, which is slightly lighter than lightgrey, but not as straight-forward when explaining the trick.

As for implementing the CSS, I initially applied the code to img tags and called it a day, but immediately realized an issue—transparent images, like the SVG logos on my homepage. It did look kind of cool, but definitely not the style I’m aiming for, so I added an additional measure to remove the checkered pattern once the image finishes loading.

<img onload="this.dataset.jsLoaded = ''">

With the onload attribute on the img tag, I’m able to add a data-js-loaded attribute to the element to indicate that the image finished loading. (The “js” prefix is simply a personal preference to indicate that JavaScript is involved)

img:not([data-js-loaded]) {
  /* checkered background code */

From here, I simply hide the checkered pattern when the data attribute is present. This works incredibly well for the img tag, but I also realized I could use the checkered pattern for video and iframe tags, too. Admittedly, I rarely use the onload attribute these days, but I was delighted to find out that these tags also support it. This means I can have the same checkered pattern behavior across all of my assets.

And with that, I can put this recent obsession to rest. I do love the exercise of revisiting old code snippets and modernizing them based on what I’ve learned over the past few years (or decade), and I don’t think this will be the last time I mess around with this trick in particular. At one point, I accidentally created several really fun patterns that I could easily see myself using. Maybe I’ll step outside of my comfort zone and introduce a bit of chaos onto the website. Until then, I hope you enjoyed reading this as much as I did exploring it!