Pixel Art With CSS Box Shadow

The author
Stephen Castle3 years ago

The Challenge

There are many ways to draw pixel art in the browser. You could use a canvas element, or an SVG, or you could even lay out 128 DIVs and set each color individually. But what if you want to do it with a single HTML element, some CSS, and not a single thing else?

For example let's imagine we had an HTML file like this.

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="./src/styles.css" />
  </head>

  <body>
    <div id="canvas"></div>
  </body>
</html>

and some css like this

#canvas {
}

How could we draw complex pixel art without modifying the HTML and without adding any Javascript?

box-shadow to the Rescue

So it turns out you can do this with the CSS box-shadow property. Too discover how, we can look at the documentation for box-shadow on the Mozilla Developer Network. Box Shadow Documentation

First a reminder that box-shadows can take a bunch of different params, including blurs, an optional inset param, etc. But we only care about 3 of them for now. The x-offset, the y-offset, and the color. When written with just these three parameters, the box-shadow property looks like this.

/* A 3px x-offset a 6px y-offset and the color #fff with no blur */
box-shadow: 3px 6px #fff;

However, the feature of box-shadow that enables us to draw pixel art is pointed out in one of the examples on this page.

/* Any number of shadows, separated by commas */
box-shadow: 3px 3px red, -1em 0 0.4em olive;

We can draw ANY number of shadows separated by commas, each with their own x and y offset from the element they are shadowing, and they can each have their own color. So you can imagine if we have a square HTML element. We can make a square shadow of that element in any color we want, and there's our pixel.Sounds like enough to draw pixel art to me! Let's see the basic principle in action by drawing a single white pixel with the box-shadow applied to the canvas DIV element.

To explore how this first pixel was drawn look in the styles.css file. You will see something like this.

#canvas {
  height: 50px;
  width: 50px;
  margin: 50px 100px;
  box-shadow: 50px 0 white;
}

The height and width of the canvas DIV is being set to 50px by 50px. The size of the DIV is what determines the size of the pixels. This does not have to be 50, but it should be a square if you want your pixels to be a uniform size, they don't have to be that either though, get creative with it!

The margin is not important but we can add one just to give our art a little space to breathe by moving it away from the edge of the window. The real magic happens in the box-shadow property. By setting a 50px x-offset we are just moving the entire shadow out from under the DIV (which is also 50px) so you can see the whole square. That's it. We don't have any y-offset currently so it is set to 0, and the third value is the color.

From here we can take advantage of the knowledge that box-shadow can take as many shadow's as you want in a comma separated list and suddenly you're drawing pixel art.

#canvas {
  height: 50px;
  width: 50px;
  margin: 50px 100px;
  box-shadow: 50px 0 white, 100px 0 red, 50px 50px orange;
}

As long as you move shadows around in increments of the same size as the canvas element's height and width they will be placed neatly in a perfect little grid moving down and to the left of the canvas's position on the screen.

Drawing More Complex Art.

That's all the knowledge you need to start drawing complex and much more interesting art. It just takes time to manually type in the shadow positions for each pixel in your image. Here are a few designs I made using this technique with a lot more pixels. The two designs in this Code Sandbox are approximately 16X16 pixel sprites for a total of 256 pixels and box-shadow values.

If you change the class on the #canvas DIV in the above Code Sandbox to mushroom you see how easy it is to switch designs just by switching out the css styles. At this point you might be saying, "Wow that is almost too easy, the only annoying part is manually writing the css to position all of the pixels!" Well I totally agree, which is why while I was working on this tutorial I wrote a tiny CLI tool to take PNG files and convert them into classes just like those used here.

If you already have Node installed (Click Here If you Need Help Installing Node) on your computer and want to give it a try you can install it from npm by running

 npm install -g pixel-to-css

And once it's installed you use it by running

 pixel-to-css FILEPATH PIXELSIZE CLASSNAME

in your terminal, making sure to replace the uppercase names with the actual values you want to use. It SHOULD work on any .PNG file though I haven't tried images larger than 32X32 pixels.

For more information visit the NPM package page here. Pixel to CSS on NPM

If you do use the package to create some new Pixel Art CSS designs I'd love to see them, also please let me know in the GitHub issues if you have any feedback. I wrote it really quickly to help finish this blog post, so you might discover some bugs or maybe you'll have an idea for how to improve it. Either way I'd love to hear from you.