
> Pixel art is a form of digital art created through a computer using raster graphics editing programs, where images are edited at the pixel level. - [Wikipedia](https://en.wikipedia.org/wiki/Pixel_art)

I've always liked **pixel art**, I'm fascinated that with so little information we can recognize objects and characters. Many people think that because it's with "little squares" (aka pixels) it's a very easy drawing technique, nothing could be further from the truth, I think the difficulty is proportional to the appearance of simplicity.

## Motivation

![Pixel Art](https://res.cloudinary.com/nucliweb/image/upload/c_scale,dpr_auto,f_auto,q_auto,w_896/v1578249920/joanleon.dev/assets/css-pixel-art/pixelart.png)

Some time ago I wanted to play with pixel art, I think the best way to start something new is to ~~copy~~ be inspired by references that aren't very complex. At the same time I wanted to do it with CSS, I always want to show that, even though it's not a programming language _(as our friend [Carlos Villuendas](https://twitter.com/carlosvillu) always reminds us)_, you can do real wonders with it... I'll dedicate a post to talk about [&#x3C; css-doodle /&#x3E;](https://css-doodle.com/) 😊

## In the Shadow of CSS

One of the CSS properties we've had available for a long time is `box-shadow`, widely used to highlight elements and give a sense of depth or relief.

![Example of box-shadow on MDN](https://res.cloudinary.com/nucliweb/image/upload/c_scale,dpr_auto,f_auto,q_auto,w_896/v1578249920/joanleon.dev/assets/css-pixel-art/developer.mozilla.org_en-US_docs_Web_CSS_box-shadow.png)

The **box-shadow** syntax has several options, I invite you to take a look at the documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow). If you have any questions, remember that I have an [AMA](https://github.com/nucliweb/ama) _(Ask Me Anything)_ repository where you can send me your questions.

Let's focus on the syntax that will allow us to create pixelated art.

If we look at the property definition, it tells us:

> The CSS box-shadow property adds shadow effects around an element's frame. You can set multiple effects separated by commas. A box shadow is described by X and Y offsets relative to the element, blur and spread radius, and color.

The part that interests us most is **You can set multiple effects separated by commas**. This will allow us to define each of the pixels of our character.

In our HTML file we only need one HTML element with a class to apply the CSS magic.

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>CSS Pixel Art</title>
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <div class="pixel-art"></div>
  </body>
</html>
```

Now let's add the necessary CSS to paint some pixels.

```scss
.pixel-art {
  width: 1px;
  height: 1px;
  margin: 50px;
  transform: scale(20);
  box-shadow: 1px 0 red, 2px 0 green, 3px 0 blue;
}
```

##### Let's analyze this code line by line

1. Since we're going to work at the pixel level, the first thing we do is define a size of 1px x 1px for our HTML element.
2. With the margin property, we're simply positioning it 50px from the 0,0 coordinate of the body.
3. This property is important, when painting at pixel size, we scale the element to be able to display it at a more appropriate size, in this case we're scaling the element 20 times.
4. Finally, we define the property that gives us the magic to create our pixel art work.

##### Let's see it in action

<iframe
  height="265"
  style="width: 100%;"
  scrolling="no"
  title="pixel-art.00"
  src="https://codepen.io/nucliweb/embed/rNapgdM?height=265&theme-id=dark&default-tab=css,result"
  frameborder="no"
  allowtransparency="true"
  allowfullscreen="true"
>
  See the Pen <a href="https://codepen.io/nucliweb/pen/rNapgdM">pixel-art.00</a>{" "}
  by Joan Leon (<a href="https://codepen.io/nucliweb">@nucliweb</a>) on{" "}
  <a href="https://codepen.io">CodePen</a>.
</iframe>

What we can see are three (sad) pixels, one next to the other 😅. But with just this simple example I'm sure you already see the "simplicity" of what we have to do to draw our pixel drawings.

##### Let's create another more illustrative example.

<iframe
  height="500"
  style="width: 100%;"
  scrolling="no"
  title="pixel-art.01"
  src="https://codepen.io/nucliweb/embed/BayJePE?height=500&theme-id=dark&default-tab=css,result"
  frameborder="no"
  allowtransparency="true"
  allowfullscreen="true"
>
  See the Pen <a href="https://codepen.io/nucliweb/pen/BayJePE">pixel-art.01</a>{" "}
  by Joan Leon (<a href="https://codepen.io/nucliweb">@nucliweb</a>) on{" "}
  <a href="https://codepen.io">CodePen</a>.
</iframe>

In this other example you can see that the element size is `4px` and the scale multiplier is 5 with `scale(5)`, we'll see the reason later 😊. What's interesting is that with a few shadow values in our CSS we've achieved a **Pixel Art** version of the blog logo.

## At Pixel Level

If we analyze up close (at pixel level) any pixel art work, we can see that it's a matrix of pixels, where each of those pixels has the information of the color it's represented with.

![Lemming at pixel level](https://res.cloudinary.com/nucliweb/image/upload/c_scale,dpr_auto,f_auto,q_auto,w_896/v1578249920/joanleon.dev/assets/css-pixel-art/lemming-pixels.png)

The previous image would look like this in a matrix where we're defining the hexadecimal color of each of the pixels. We omit the "padding" pixels we've left to improve image readability, so we'll have a 10 x 10 matrix.

```scss
#000000,#000000,#000000,#000000,#00b0b0,#00b0b0,#000000,#000000,#000000,#000000,
#000000,#000000,#000000,#00b0b0,#00b0b0,#00b0b0,#00b0b0,#000000,#000000,#000000,
#000000,#000000,#000000,#00b0b0,#f0d0d0,#f0d0d0,#00b0b0,#000000,#000000,#000000,
#f0d0d0,#000000,#000000,#000000,#f0d0d0,#f0d0d0,#000000,#000000,#000000,#f0d0d0,
#f0d0d0,#f0d0d0,#f0d0d0,#f0d0d0,#4040e0,#4040e0,#f0d0d0,#f0d0d0,#f0d0d0,#f0d0d0,
#000000,#000000,#000000,#000000,#4040e0,#4040e0,#000000,#000000,#000000,#000000,
#000000,#000000,#000000,#000000,#4040e0,#4040e0,#000000,#000000,#000000,#000000,
#000000,#000000,#000000,#4040e0,#4040e0,#4040e0,#4040e0,#000000,#000000,#000000,
#000000,#000000,#000000,#4040e0,#000000,#000000,#4040e0,#000000,#000000,#000000,
#000000,#000000,#f0d0d0,#f0d0d0,#000000,#000000,#f0d0d0,#f0d0d0,#000000,#000000;
```

Like cross-stitch, we simply define a color for each of the points we want to paint.

## Supercharged CSS

As you might be imagining, achieving more complex drawings can take us a lot of work, and that's true. That's why we're going to rely on [Sass](https://sass-lang.com/) to facilitate the generation of our pixel art creations.

<iframe
  height="382"
  style="width: 100%;"
  scrolling="no"
  title="Lemming Blocker"
  src="https://codepen.io/nucliweb/embed/mdyxroR?height=382&theme-id=dark&default-tab=css,result"
  frameborder="no"
  allowtransparency="true"
  allowfullscreen="true"
>
  See the Pen{" "}
  <a href="https://codepen.io/nucliweb/pen/mdyxroR">Lemming Blocker</a> by Joan
  Leon (<a href="https://codepen.io/nucliweb">@nucliweb</a>) on{" "}
  <a href="https://codepen.io">CodePen</a>.
</iframe>

##### Let's analyze step by step what we're doing

We define in variables the different colors we need to create our drawing. We also define a variable with the grid dimension.

```scss
$hair: #00b0b0;
$skin: #f0d0d0;
$clothes: #4040e0;
$grid: 10;
```

Then, we use a Sass [Maps](https://sass-lang.com/documentation/values/maps) to be able to use the map index keys, this will make it easier for us to create the matrix.

```scss
$colors: (
  1: $hair,
  2: $skin,
  3: $clothes,
);
```

The next step is to define the matrix with the colors of our drawing. We'll do it with each of the keys from the Maps we just created, we'll use `1` to reference the `$hair` variable, which in turn is the hexadecimal value `#00b0b0`, the hair color.

```scss
// Lemming Blocker -------------------
$lemming-blocker: 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
  0, 0, 1, 2, 2, 1, 0, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 3, 3, 2,
  2, 2, 2, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0,
  3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 0,
  0;
```

> It's hard to appreciate, but right now we have a 10 x 10 matrix just like the one we saw a bit above, with the red grid to see the pixels, with a numeric value for each of the colors. For Sass this is a list, so we can iterate over it. Technically it's a single line, here we see it in grid mode to facilitate editing.

You'll have seen that for the black color we've used the value `0`, which we don't have defined in our Maps, now we'll see how we're going to use it.

##### Let's start with programming

Sass provides us, as they define, an extension language for CSS. It's a CSS preprocessor with syntax that offers us functions, lists, maps or loops among others.

The following code contains the "magic" necessary to paint all the pixels needed to draw the lemming.

```scss
@function pixeart($lemming-list, $shadow-count: $grid) {
  $shadows: ();
  $row: 0;
  $col: 1;

  @for $i from 1 through length($lemming-list) {
    @if (nth($lemming-list, $i) > 0) {
      $shadows: append(
        $shadows,
        ($col * 1px) ($row * 1px) 0 map-get($colors, nth($lemming-list, $i)),
        "comma"
      );
    }

    @if ($i % $grid == 0) {
      $row: $row + 1;
      $col: 0;
    }

    $col: $col + 1;
  }

  @return $shadows;
}
```

##### Let's analyze this Sass code

The `pixelart` function accepts two parameters, the first is a list and the second the grid dimension, where we define a default value in case we don't receive one.

At the beginning of the function body we define an empty list with `$shadow`, as well as the initial value for rows and columns in `$row` and `$col`.

In the next block we have a `@for` to iterate each of the elements of the list (with our matrix) that we received as argument `$leming-list`.

In the first `@if`, where we check if we still have elements from the list, what we're doing is adding an element to the `@shadows` list with _append_. We're passing 3 parameters to append: the list to which we want to add the element, the element content and the separator, in this case `'comma'`, a Sass reserved word to represent the **,** character. Going into detail of the element value we're adding we see `($col * 1px) ($row * 1px) 0 map-get($colors,nth($lemming-list,$i))`.

- **($col \* 1px)**, is the **X** position relative to the HTML element.
- **($row \* 1px)**, is the **Y** position relative to the HTML element.
- **0**, is the value indicating the shadow gradient, we want it to be a solid shadow.
- **map-get($colors,nth($lemming-list,$i))**, with the Sass `map-get` function we're getting the value from the color matrix according to position `$i` of our iteration.

In the second `@if`, we simply check if we've reached the maximum number of columns, 10 in this example, and if so we pass the column value to **0** and add one to the rows `$row`

Finally, we return the content of `$shadows` with `@return $shadows`.

##### Call from CSS

Now that we have our function available, we can use it in CSS with `pixelart($lemming-blocker)`, as we can see on line 7.

```scss
.lemming--blocker {
  width: 1px;
  height: 1px;
  margin: 100px;
  transform: scale(10);

  box-shadow: pixelart($lemming-blocker);
}
```

## Giving Life to Shadows

Now that we have our lemming in pixel art, let's give it life thanks to CSS animation.

> As you may know, an animation is the illusion of movement when viewing a sequence of images at a certain speed. This type of images in many 2D games are sprites, so I searched for **Lemmings sprite animation** and found this [image](http://pages.cs.wisc.edu/~zeppenfe/files/lemmings/lemming_anim.png). This allowed me to see the sequence of images to make the animation.

<iframe
  height="500"
  style="width: 100%;"
  scrolling="no"
  title="Lemmings"
  src="https://codepen.io/nucliweb/embed/doJXwM?height=500&theme-id=dark&default-tab=css,result"
  frameborder="no"
  allowtransparency="true"
  allowfullscreen="true"
>
  See the Pen <a href="https://codepen.io/nucliweb/pen/doJXwM">Lemmings</a> by
  Joan Leon (<a href="https://codepen.io/nucliweb">@nucliweb</a>) on{" "}
  <a href="https://codepen.io">CodePen</a>.
</iframe>

The lemming on the left has only 2 frames, so with two matrices we already have the animation solved.

```scss
.lemming--blocker {
  width: 1px;
  height: 1px;
  margin: 100px;

  transform: scale(10);

  animation: blocker 0.65s step-start infinite;
  box-shadow: lemming($lemming-blocker-1);
}

@keyframes blocker {
  50% {
    box-shadow: lemming($lemming-blocker-2);
  }
}
```

To achieve the walking effect of the lemming on the right, it requires 8 frames, so we have to define 8 matrices (take a look at the **Codepen** code).

Assigning the animation doesn't have much mystery, we'll do it just as we do in any CSS animation with `@keyframes`.

```scss
.lemming--walker {
  width: 1px;
  height: 1px;
  margin: 100px;

  transform: scale(10);

  animation: walker 0.65s step-start infinite;
  box-shadow: lemming($lemming-walker-1);
}

@keyframes walker {
  12% {
    box-shadow: lemming($lemming-walker-2);
  }
  25% {
    box-shadow: lemming($lemming-walker-3);
  }
  37% {
    box-shadow: lemming($lemming-walker-4);
  }
  50% {
    box-shadow: lemming($lemming-walker-5);
  }
  62% {
    box-shadow: lemming($lemming-walker-6);
  }
  75% {
    box-shadow: lemming($lemming-walker-7);
  }
  87% {
    box-shadow: lemming($lemming-walker-8);
  }
}
```

## Matrix Is Not for Me

At this point you're probably thinking: _Having to make an **n x n** matrix of each image, and multiply it by the number of frames needed if I want to make an animation, seriously Joan, you're crazy._

This type of exercise helps us practice and learn, but depending on what you want to do it's clear that it's a very ~~tedious~~ artisanal way of doing it. That's why I'm sharing the following resource with you.

##### CSS Sprite Animator

<img
  src="https://res.cloudinary.com/nucliweb/image/upload/v1578696284/joanleon.dev/assets/css-pixel-art/CSS-Sprite-Animator.gif"
  style="max-width: 100%; margin: 0 auto; display: block;"
  alt="CSS Sprite Animator"
  title="CSS Sprite Animator"
/>

It's an application developed by [Paul Karlik](https://twitter.com/pjkarlik), you can find it [here](http://css-sprite-animator.surge.sh/) and the repository with the source code [here](https://github.com/pjkarlik/css-sprite-animatior).

It has an intuitive and simple interface. As soon as we add more than one frame, in the upper right corner, we can see a preview of the animation.

The blog logo in pixel art we saw earlier is made with this editor, which is using multiples of 4 in pixel generation. I got motivated and also created the animation of the lemming when it's falling.

<img
  src="https://res.cloudinary.com/nucliweb/image/upload/v1578696742/joanleon.dev/assets/css-pixel-art/lemming-falling.gif"
  style="max-width: 100%; margin: 0 auto; display: block;"
  alt="Lemming Falling"
  title="Lemming Falling"
/>

The application is also generating the necessary CSS code for the `box-shadow` property. It has an export function that generates an array of objects with the necessary values.

```js
[
  [
    {"x":0,"y":0,"color":"transparent"},
    {"x":1,"y":0,"color":"transparent"},
    ...
  ],
  [ ... ]
]
```

## Curio<span style="color:#3fa9f5;">css</span>ities

We've defined the animations with a value of `step-start` for the [animation-timing-function](https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timing-function) property. With **step-start** we're defining that the browser doesn't generate any interpolation between one frame and the next. The default value of this property is `ease` which leaves the browser responsible for calculating an interpolation between frames, and in this case we don't achieve the desired effect, but it does make for a curious animation 😊.

<img
  src="https://res.cloudinary.com/nucliweb/image/upload/v1578697955/joanleon.dev/assets/css-pixel-art/lemmings-ease.gif"
  style="max-width: 100%; margin: 0 auto; display: block;"
  alt="Lemming ease"
  title="Lemming ease"
/>

## Other Examples

In my [Codepen](https://codepen.io/nucliweb) account you'll find this and other examples, some of them are made with [p5.js](https://p5js.org/) _(we'll talk about this library at some point)_, but the base is the same, using a matrix to generate the pixel art drawing.
