CSS Pixel Art
Tags: css, pixelart, pixel, animation
Published: 2020-09-17 17:50:21

---
title: CSS Pixel Art
published: true
description: El Pixel Art es una técnica de diseño que se sigue utilizando como recurso en muchos video juegos. Con CSS podemos utilizar esta técnica de una manera muy sencilla.
tags: css, pixelart, pixel, animation
canonical_url: https://joanleon.dev/css-pixel-art
//cover_image: https://direct_url_to_image.jpg
---


> El pixel art o arte de píxel es una forma de arte digital, creada a través de una computadora mediante el uso de programas de edición de gráficos rasterizados, donde las imágenes son editadas al nivel del píxel. - [Wikipedia](https://es.wikipedia.org/wiki/Pixel_art)

Siempre me ha gustado el **pixel art**, me fascina que con tan poca información podamos reconocer objetos y personajes. Mucha gente cree que al ser con "cuadraditos" (aka pixels) es una técnica de dibujo muy fácil, nada más lejos de la realidad, creo que la dificultad es proporcional a la apariencia de sencillez.

## Motivación

![Pixel Art](https://joanleon.dev/static/f6064d56373cda188e20b6b079865311/30744/pixelart.png)

Hace un tiempo quise jugar con el pixel art, creo que la mejor manera de empezar algo nuevo es ~~copiar~~ inspirarse en referencias que no sean muy complejas. Al mismo tiempo lo quería hacer con CSS, siempre quiero mostrar que, aun no siendo un lenguaje de programación *(como siempre nos recuerda nuestro amigo [Carlos Villuendas](https://twitter.com/carlosvillu))*, se pueden hacer auténticas maravillas con él... ya dedicaré un post a hablar de [&#x3C; css-doodle /&#x3E;](https://css-doodle.com/) 😊

## A la sombra de CSS

Una de la propiedades CSS que tenemos disponible desde hace mucho tiempo es `box-shadow`, muy utilizada para resaltar elementos y dar sensación de profundidad o relieve.

![Ejemplo de box-shadow en MDN](https://joanleon.dev/static/9282f470e0a1c081b1ebd1e4c1751bb6/30744/developer.mozilla.org_en-US_docs_Web_CSS_box-shadow.png)

La sintaxis de **box-shadow** tiene varias opciones, os invito a echar un vistazo a la documentación en [MDN](https://developer.mozilla.org/es/docs/Web/CSS/box-shadow). Si tenéis alguna duda, recordad que tengo un repositorio [AMA](https://github.com/nucliweb/ama) *(Ask Me Anything)* donde podéis hacerme llegar vuestras consultas.

Vamos a centrarnos en las sintaxis que nos permitirá crear arte pixelado.

Si nos fijamos en la definición de la propiedad, nos dice:

> La propiedad CSS box-shadow  añade efectos de sombra alrededor del marco de un elemento. Se pueden definir múltiples efectos separados por comas. La caja de la sombra se describe por los desplazamientos en X e Y, los radios de desenfoque y dispersión, y el color relativos al elemento.

La parte que más nos interesa es la de **Se pueden definir múltiples efectos separados por comas**. Esto nos va a permitir definir cada uno de los píxeles de nuestro personaje.

En nuestro archivo HTML solo necesitamos un elemento HTML con una clase para aplicarle la magia del CSS.

```html
<!DOCTYPE html>
<html lang="es">
<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>
```

Ahora vamos a añadir el CSS necesario para pintar algunos píxeles.

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

##### Analicemos línea a línea este código

1. Como vamos a trabajar a nivel de píxel, lo primero que hacemos es definir un tamaño de 1px x 1px nuestro elemento HTML.
2. Con la propiedad margin, simplemente lo estamos posicionando a 50px de la coordenada 0,0 del body.
3. Esta propiedad es importante, al pintar a un tamaño de píxeles, escalamos el elemento para poder mostrarlo a un tamaño más adecuado, en este caso estamos escalando el elemento 20 veces.
4. Por último, definimos la propiedad que nos aporta la magia para conseguir crear nuestra obra en pixel art.

##### Vamos a verlo en funcionamiento

<div style="margin-bottom: 2em" />

{% codepen https://codepen.io/claireparker/pen/rNapgdM %}

<div style="margin-bottom: 2em" />

Lo que podemos ver son tres (tristes) píxeles, uno al lado del otro 😅. Pero con solo este simple ejemplo seguro que ya ves la "simplicidad" de lo que tenemos que hacer para dibujar nuestros dibujos con píxeles.

##### Crearemos otro ejemplo más ilustrativo.

<div style="margin-bottom: 2em" />

{% codepen https://codepen.io/claireparker/pen/BayJePE %}

<div style="margin-bottom: 2em" />

En este otro ejemplo podéis ver que el tamaño del elemento es de `4px` y el multiplicador de escala de 5 con `scale(5)`, más tarde veremos el motivo 😊. Lo interesante es que con unos cuantos valores de sombra en nuestro CSS hemos conseguido una versión **Pixel Art** del logo del blog.

## A nivel de pixel

Si analizamos de cerca (a nivel de pixel) cualquier obra de pixel art, podremos ver que se trata de una matriz de píxeles, donde cada uno de esos píxeles tiene la información del color con el que es representado.

![Lemming a nivel de pixel](https://joanleon.dev/static/b870fed83156c06aff7d60c42f8e63e4/30744/lemming-pixels.png)

La imagen anterior se vería de la siguiente manera en una matriz donde estemos definiendo el color hexadecimal de cada uno de los píxeles. Obviamos los píxeles de "padding" que hemos dejado para mejorar la lectura de la imagen, así que tendremos una matriz de 10 x 10.

```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;
```

Como si se tratase de punto de cruz, simplemente definimos un color por cada uno de los puntos que queremos pintar.

## CSS vitaminado

Como estaréis imaginando, conseguir dibujos más complejos nos puede llevar mucho trabajo, y así es. Es por eso que nos vamos a apoyar en [Sass](https://sass-lang.com/) para facilitar la generación de nuestras creaciones en pixel art.

<div style="margin-bottom: 2em" />

{% codepen https://codepen.io/claireparker/pen/mdyxroR %}

<div style="margin-bottom: 2em" />

##### Analicemos paso a paso lo que estamos haciendo

Definimos en variables los diferentes colores que necesitamos para crear nuestro dibujo. También definimos una variable con la dimensión de la cuadrícula.

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

Después, utilizamos un [Maps](https://sass-lang.com/documentation/values/maps) de Sass para poder utilizar las claves de índice del mapa, eso nos facilitará crear la matriz.

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

El siguiente paso es definir la matriz con los colores de nuestro dibujo. Lo haremos con cada una de las claves del Maps que acabamos de crear, utilizaremos `1` para hacer referencia a la variable `$hair`, que a su vez es el valor hexadecimal `#00b0b0`, el color del pelo.

```scss:title=Matrix-Lemming-Blocker
// 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;
```

> Es difícil de apreciar, pero ahora mismo tenemos una matriz de 10 x 10 igual que la que hemos visto un poco más arriba, con la cuadrícula roja para ver los píxeles, con un valor numérico para cada uno de los colores. Para Sass esto es una lista, así podremos iterar sobre ella. Técnicamente es una sola línea, aquí la vemos en modo cuadrícula para facilitar la edición.

Habrás visto que para el color negro hemos utilizado el valor `0`, el cual no tenemos definido en nuestro Maps, ahora veremos cómo lo vamos a utilizar.

##### Empecemos con la programación

Sass nos provee, como definen, un lenguaje de extensión para CSS. Se trata de un preprocesador CSS con una sintaxis que nos ofrece funciones, listas, maps o bucles entre otros.

El siguiente código contiene la "magia" necesaria para pintar todos los píxeles necesarios para dibujar el 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;
}
```
<div style="margin-bottom: 2em" />

##### Analicemos este código en Sass

La función `pixelart` acepta dos parámetros, el primero es una lista y el segundo la dimensión de la retícula, donde definimos un valor por defecto en el caso de no recibir ninguno.

Al inicio del cuerpo de la función definimos una lista vacía con `$shadow`, así como el valor inicial para las filas y columnas en `$row` y `$col`.

En el siguiente bloque tenemos un `@for` para iterar cada uno de los elementos de la lista (con nuestra matriz) que hemos recibido como argumento `$leming-list`.

En el primer `@if`, donde comprobamos si seguimos teniendo elementos de la lista, lo que estamos haciendo es añadir un elemento a la lista `@shadows` con *addend*. A append le estamos pasando 3 parámetros: la lista a la que queremos añadir el elemento, el contenido del elemento y el separador, en este caso `'coma'`, una palabra reservada de Sass para representar el carácter **,**. Entrando en detalle del valor del elemento que estamos añadiendo vemos `($col * 1px) ($row * 1px) 0 map-get($colors,nth($lemming-list,$i))`.

  - **($col * 1px)**, es la posición **X** respecto al elemento HTML.
  - **($row * 1px)**, es la posición **Y** respecto al elemento HTML.
  - **0**, es el valor que indica el degradado de sombra, nos interesa que sea un sombra sólida.
  - **map-get($colors,nth($lemming-list,$i))**, con la función `map-get` de Sass estamos cogiendo el valor de la matriz de colores según la posición `$i` de nuestra iteración.

En el segundo `@if`, simplemente comprobamos si ya hemos llegado al máximo de columnas, 10 en este ejemplo, y si es así pasamos el valor de columna a **0** y sumamos una a las filas `$row`

Por último, devolvemos el contenido de `$shadows` con `@return $shadows`.

##### Llamada desde CSS

Ahora que tenemos disponible nuestra función, la podemos utilizar en CSS con `pixelart($lemming-blocker)`, como podemos ver en la línea 7.

```scss
.lemming--blocker {
  width: 1px;
  height: 1px;
  margin: 100px;
  transform: scale(10);
  
  box-shadow: pixelart($lemming-blocker);
}
```
<div style="margin-bottom: 2em" />

## Dando vida a las sombras

Ahora que ya tenemos nuestro lemming en pixel art, vamos a darle vida gracias a la animación CSS.

> Como ya sabréis, una animación es la ilusión de movimiento al ver una secuencia de imágenes a cierta velocidad. Este tipo de imágenes en muchos juegos 2D son sprites, así que busqué **Lemmings sprite animation** y dí con esta [imagen](http://pages.cs.wisc.edu/~zeppenfe/files/lemmings/lemming_anim.png). Eso me permitió poder ver la secuencia de imágenes para hacer la animación.

<div style="margin-bottom: 2em" />

{% codepen https://codepen.io/claireparker/pen/doJXwM %}

<div style="margin-bottom: 2em" />

El lemming de la izquierda tiene solo 2 fotogramas, así que con dos matrices ya tenemos la animación resuelta.

```scss
.lemming--blocker {
  width: 1px;
  height: 1px;
  margin: 100px;
  
  transform: scale(10);
  
  animation: blocker .65s step-start infinite;
  box-shadow: lemming($lemming-blocker-1);
}

@keyframes blocker {
  50%  { box-shadow: lemming($lemming-blocker-2); }
}
```
<div style="margin-bottom: 2em" />

Para conseguir el efecto de andar del lemming de la derecha, requiere de  8 fotogramas, por lo que tenemos que definir 8 matrices (echad un vistazo al código de **Codepen**). 

La asignación de la animación no tiene mucho misterio, la haremos tal y como lo hacemos en cualquier animación CSS con `@keyframes`.

```scss
.lemming--walker {
  width: 1px;
  height: 1px;
  margin: 100px;
  
  transform: scale(10);
  
  animation: walker .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); }
}
```
<div style="margin-bottom: 2em" />

## Matrix no es para mí

Llegados a este punto estarás pensando: *Tener que hacer una matriz de **n x n** de cada imagen, y multiplicarlo por el número de fotogramas necesario si quiero hacer una animación, en serio Joan, estás flipando.*

Este tipo de ejercicios nos sirve para practicar y aprender, pero según lo que quieras hacer está claro que es una forma muy ~~tediosa~~ artesana de hacerlo. Es por eso que te comparto el siguiente recurso.

##### 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" />

Se trata de una aplicación desarrollada por [Paul Karlik](https://twitter.com/pjkarlik), podéis encontrarla [aquí](http://css-sprite-animator.surge.sh/) y el repositorio con el código fuente [aquí](https://github.com/pjkarlik/css-sprite-animatior).

Tiene una interfaz intuitiva y simple. En el momento que añadimos más de un fotograma, en la parte superior derecha, podemos ver una previsualización de la animación.

El logo del blog en pixel art que hemos visto antes, está hecho con este editor, que está utilizando múltiples de 4 en la generación de los píxeles. Me he animado y también he creado la animación del lemming cuando está cayendo.

<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" />

<div style="margin-bottom: 2em" />

La aplicación también está generando el código CSS necesario para la propiedad `box-shadow`. Tiene una función de exportación que genera un array de objetos con los valores necesarios.

```js:title=Ejemplo-de-exportación
[
  [
    {"x":0,"y":0,"color":"transparent"},
    {"x":1,"y":0,"color":"transparent"},
    ...
  ],
  [ ... ]
]
```
<div style="margin-bottom: 2em" />

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

Las animaciones las hemos definido con un valor de `step-start` para la propiedad [animation-timing-function](https://developer.mozilla.org/es/docs/Web/CSS/animation-timing-function). Con **step-start** estamos definiendo que el navegador no genere ninguna interpolación entre un fotograma y el siguiente. El valor por defecto de esta propiedad es `ease` que deja al navegador la responsabilidad de calcular una interpolación entre fotogramas, y en este caso no conseguimos el efecto deseado, pero eso sí, la animación queda curiosa 😊.

<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" />
<div style="margin-bottom: 2em" />

## Otros ejemplos

En mi cuenta de [Codepen](https://codepen.io/nucliweb) encontraréis este y otros ejemplos, algunos de ellos están hechos con [p5.js](https://p5js.org/) _(ya hablaremos de esta librería en algún momento)_, pero la base es la misma, utilizar una matriz para generar el dibujo pixel art.

<div style="margin-bottom: 8em" />

#### Compartir, feedback y erratas

- Si te ha gustado el artículo, compártelo para llegar a más gente.
- Si tienes feedback que me pueda ayudar a mejorar, siéntete libre de pasarme un [DM](https://twitter.com/nucliweb).
- Si ves alguna errata o hay algo que no planteo bien, también agradezco las correcciones [DM](https://twitter.com/nucliweb).

<div style="margin-bottom: 4em" />

#### Sígueme en...

- **Twitter:** [@nucliweb](https://twitter.com/nucliweb)
- **YouTube:** [JoanLeon](https://www.youtube.com/c/JoanLeon)
- **Instagram:** [@nucliweb](https://www.instagram.com/nucliweb/)
- **GitHub:** [@nucliweb](https://github.com/nucliweb)