How to create pure CSS illustrations and animate them - Part 1
Tags: css, purecss, animation, illustration
Published: 2018-09-04 11:19:40

---
title: How to create pure CSS illustrations and animate them - Part 1
published: true
description: A guide to create pure CSS illustrations and animate them
tags: CSS, pureCSS, animation, illustration
cover_image: https://thepracticaldev.s3.amazonaws.com/i/0u67lvhvwl4wvahg4uw3.jpg
---

I've always had a great interest in design, illustrations and colour palettes, but having spent the last few years focusing on becoming a better front-end developer, I've been left with little time to practice my creative skills. When I was first introduced to CSS images, I couldn't wait to give it a try. At last I could play around with shapes and colors, and explore and develop my creativity while coding!


####But first, what is a pure CSS image?
A pure CSS image is an illustration that has been built with HTML and CSS. It excludes the use of image file imports, or code generated by exporting graphics in illustration software. In other words, it's an image that has been entirely manually coded in a code editor, using HTML and CSS only.

The principle is simple: with HTML, you can create as many divs as you like, which will each represent the basic shape of a component of the final image. With CSS properties such as gradients, transform, border-radius, shadows and so on, you can transform these basic shapes and arrange them into a nice illustration.
 

####Why CSS images?
But what’s even the point of CSS images, you ask? CSS is primarily meant to style web pages after all, and there are more adapted and efficient tools to produce quality and lightweight graphics for web design (think SVG). Indeed, not only does using CSS for illustration have some design limitations, the result can be overly complex, time consuming and face some major cross browser/device issues.

So there is definitely a place and time for CSS images. However, creating CSS Illustrations is a great way to get better at CSS and to be introduced to new tools and concepts, such as animations, preprocessors or more obscure CSS properties. I feel my CSS skills have skyrocketed ever since I started coding CSS images, and I have become much more familiar with concepts I didn't know much about, like the wide variety of CSS selectors, 3D transforms and keyframes animations.
 

####Who is it for?
CSS illustrations are great for:
* Illustrators or designers hoping to use their designing skills to learn, or get more confident with html/css
* Front-end developers hoping to work on their creativity and develop a good eye for design
* Anyone wanting to have a bit of fun while strengthening their CSS skills
* Anyone hoping to connect with a community, inspire and be inspired
* Or anyone up for a good challenge 

In this series, we'll learn how to create three CSS illustrations, ranging from simple to complex. We'll learn the basics of CSS animations and how to use them to animate our illustrations. Along the way, we'll find out what concepts, tools and techniques can help speed up our workflow. 

**Part 1: Learning basics and workflow tips with a CSS Smiley Face**
[Part 2: Intro to CSS animations with a CSS Polaroid](https://dev.to/agathacco/how-to-create-pure-css-illustrations-and-animate-them---part-2-1ao4) 
[Part 3: More advanced techniques with a CSS Lighthouse Scene](https://dev.to/agathacco/how-to-create-pure-css-illustrations-and-animate-them---part-3-3e8a)

While this tutorial series doesn't require any advanced knowledge of web development, I'm assuming you are familiar at least familiar with HTML and CSS.

A couple of suggestions before we begin: 

* Open a [CodePen](https://codepen.io/) account, if you don't have one already. It'll take away the pain of having to set up a project, especially since we'll be using CSS preprocessors and templating languages.
* Use either Chrome or Firefox, as other browsers have proven to be buggy  with CSS illustrations.

#Basics
Okay enough talk, let’s get started with our first CSS image! 

Here’s a circle:

```html
<div class="circle"></div>
```
```css
html,
body {
  height: 100%;
  width: 100%;
  overflow: hidden;
  padding: 0;
  margin:0;
}
body {
  background: #FEEE9D;
}
.circle {
  position: absolute;
  width: 300px;
  height: 300px;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  border-radius: 50%;
  background-color: #FBD671;
}
```
![](https://thepracticaldev.s3.amazonaws.com/i/vnfb7a57rwarv9ke8wp6.jpg)

Nothing impressive so far. 

We're going to add a few elements to turn this circle into a smiley face. The circle will be the head, and we can add eyes and a mouth:

```html
<div class="head">
  <div class="face">
    <div class="mouth"></div>
    <div class="eye-group">
      <div class="eye eye-left"></div>
      <div class="eye eye-right"></div>
    </div>
  </div>
</div>
```
```css
html,
body {
  height: 100%;
  width: 100%;
  overflow: hidden;
  padding: 0;
  margin: 0;
}
body {
  background: #FEEE9D;
}
* {
  position: absolute;
}
.head {
  width: 300px;
  height: 300px;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  border-radius: 50%;
  background-color: #FBD671;
}
.face {
  width: 150px;
  height: 170px;
  left: 75px;
  top: 75px;
}
.mouth {
  width: 100%;
  height: 75px;
  bottom: 0;
  left: 0;
  background-color: #20184E;
  border-radius: 10px 10px 150px 150px;
  border: 5px solid #20184E;
}
.eye-group {
  width: 150px;
  height: 50px;
  top: 10px;
  left: 0;
}
.eye {
  background-color: #20184E;
  width: 30px;
  height: 50px;
  border-radius: 50%;
}
.eye-left {
  left: 15px;
}
.eye-right {
  right: 15px;
}
```
![](https://thepracticaldev.s3.amazonaws.com/i/f6n87mht45wxvffnffjf.jpg)

Okay, let’s have a look at what’s going on here.
####Main container
We have a main container, in this case the `.head` element, that contains every other HTML elements. This is, as you would expect,  to center our illustration, and serve as a reference for the positioning of everything else. 
####Absolute positioning
All elements have the `position: absolute` property.  This allows, with the help of the top/right/bottom/left properties, to precisely position them relatively to their parent. It's important to note that absolute positioning removes elements from the natural flow of the page. It means that the position of an element with that property will not affect the position of other elements, and will not be affected by their position either. Assigning the `position: absolute` property to all elements by default will ensure they will all be independent from each other. More on  positioning [here](https://css-tricks.com/almanac/properties/p/position/).  
```css
* {
  position:absolute;
}
```
####Nesting
Following this logic, we use nesting  to group elements together. Observe the `.face` element. It is not an actual component of the image, but used only to group the eyes and the mouth together. Both `.mouth` and `.eye-group` 's position (and size, if we use % instead of px) will refer to  `.face`. If, for example,  we decide we want to reposition the face on the head later, we can do it at once instead of having to tweak the properties of both `.mouth` and `.eyes`. This is basic CSS logic and won't be new to you if you have experience in UI development. As a rule of thumb, nesting allows a clearer structure because it groups elements that belong together,  and make the illustration easier to manipulate.

####Stacking
Using absolute positioning allow us to have more control on the stacking order of the elements. Naturally, the stacking order follows the flow of the HTML elements. The first object will be at the bottom of the pile (at the far back), while the last one will be on top (closest to you). With the z-index property, we can change the position of each element in the pile and make them overlap how we want to, provided these elements belong to the same [stacking context](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context). The higher the value of z-index, the higher it'll be in the pile. 

>Stacking contexts are a bit tricky and don't always behave as you would expect them to. You can read more about what triggers the creation of a new stacking context [here](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context).

####Classes only
We only use CSS classes to target and style our HTML elements as we don't want to be bothered by [specificity](https://css-tricks.com/specifics-on-css-specificity/) issues.

---
Phew, that was a lot already. But these are very important concepts of CSS illustrations, and CSS in general. Once you are comfortable with positioning and stacking, your CSS skills will improve drastically.

Now that we have a basic understanding of how to position elements, let’s jazz up our smiley face a little. I want to add a few details like a tongue, pupils and a shadow.

The shadow is straightforward but adds a nice touch:

```css
.head {
  width: 100%;
  height: 100%;
  background-color: #FBD671;
  border-radius: 50%;
  box-shadow:inset -10px -10px 0px #EFBB42;
}
```

The tongue is a simple pink circle, but we only want to show part of it to create the illusion that it's inside the mouth. To do this, we  nest `.tongue`  in `.mouth`  and apply the `overflow: hidden` property to `.mouth.`

```html
<div class="head">
  <div class="face">
    <div class="mouth">
      <div class="tongue"></div>
    </div>
    <div class="eye-group">
      <div class="eye eye-left"></div>
      <div class="eye eye-right"></div>
    </div>
  </div>
</div>
```

```css
.mouth {
  width: 100%;
  height: 75px;
  background-color: #20184E;
  left: 0;
  bottom: 0;
  border-radius: 10px 10px 150px 150px;
  border: 5px solid #20184E;
  overflow:hidden;
}
.tongue {
  width: 100px;
  height: 80px;
  left: 25px;
  top: 30px;
  background-color: #F15962;
  border-radius: 50%;
}
```
<insert screenshot />

And we can add pupils with a simple oval inside our `.eye` elements.

```html
<div class="container">
  <div class="head">
    <div class="face">
      <div class="mouth">
        <div class="tongue"></div>
      </div>
      <div class="eye-group">
        <div class="eye eye-left">
          <div class="pupil"></div>
        </div>
        <div class="eye eye-right">
          <div class="pupil"></div>
        </div>
      </div>
    </div>
  </div>
</div>
```

```css
.pupil {
  width: 10px;
  height: 15px;
  top: 5px;
  background-color: #FBD671;
  border-radius: 50%;
}
```
It's looking much better already. 

![](https://thepracticaldev.s3.amazonaws.com/i/jg90tzx6lan2vx0wrudf.jpg)

#More advanced concepts
Now that we have built our first CSS image, let’s take a step back and look at how we can improve our code. While these steps aren't necessary at all to build CSS images, I find they greatly improve my workflow, and helped me getting much better at CSS in general.  

####CSS Preprocessors

If you are familiar with [CSS preprocessors](https://developer.mozilla.org/en-US/docs/Glossary/CSS_preprocessor) you know there’s a better way to do this. I won’t delve into how to set up a preprocessor as this is beyond  the scope of this article. Instead I strongly recommend you use [Codepen](https://codepen.io/), which has all preprocessors built in. You just have to select the one you want in the CSS settings and you’re all set.

I personally like to use [SASS/SCSS](https://sass-lang.com/), but feel free to use any of the options available.

The best known feature of preprocessors is the ability to use variables. Preprocessor variables work just like javascript ones. You declare them and assign them a value once, then you can use and reuse them throughout your code. This is a great tool as it avoids repetition and gives you a lot more flexibility. Let's implement a few variables in our CSS. A good use for variables is to define colors. 

A SCSS variable always starts with the $ sign:

```scss
$black: #20184E;
```

You can name it whatever you like, but it must start with $ and be assigned a valid CSS property. 

Then you can use it like so: 

```scss
background-color: $black;
```

You can see where this would come handy. If we later decide that we want to change this particular color, we only have to do it in one place and it will be reflected everywhere the variable is used in our code. Also when it comes to colors, it's a lot easier to remember the name of a variable you created than a RGB or HEX value. 

I've added my new color variables to the top of the code so we can find them easily. Declaring variables in the global scope (as opposed to declaring them in a selector) will make sure we can use them everywhere. 

```scss
$black: #20184E;
$head-color: #FBD671;
$background: #FEEE9D;
$tongue-color: #F15962;
```

Now we can change our css properties so they point to the variables instead of the hard coded HEX values.

Eg:

```scss
.mouth {
  width: 100%;
  height: 75px;
  bottom: 0;
  background-color: $black;
  border: 5px solid $black;
  border-radius: 10px 10px 150px 150px;
  overflow: hidden;
}
```

> CSS now has native variables that pretty much make the preprocessor ones unnecessary. However, preprocessors offer a lot more than variables and are still extremely useful in many other ways.

SCSS also comes with many helper functions, including [color functions](http://sass-lang.com/documentation/Sass/Script/Functions.html). These functions are quite powerful as they allow you to manipulate colors very easily. 

Let's have a look at the inset shadow applied to the head. Right now we are using a hard coded HEX value, which I've had to manually look up.  We are going to use the darken function to generate this value instead:

```scss
.head {
  border-radius: 50%;
  width: 100%;
  height: 100%;
  background-color: $head-color;
  box-shadow: inset -10px -10px 0px darken($head-color, 20%);
}
```

Basically, the function takes `$head-color` as a parameter then and increases the amount of darkness by 20%.  

I love using color functions because not only do they eliminate the need to resort to some design software  to generate colors, they also help with creating a more harmonious color palette for your illustration.

Another great feature of SASS is nesting. Nesting allows you to nest selectors within parent selectors in order to create shortcuts. It creates a better hierarchy and readability of your CSS, and avoids repeating selectors over and over. 

For example 

```scss
.pink {
  background-color: pink;
  .purple {
    background-color: purple;
  }

}
``` 
will be compiled to:

```css
.pink { 
  background-color: pink;
}
.pink .purple { 
  background-color: purple;
} 
```

SASS also offers the & selector, which basically refers to the parent selector. So

```scss
.pink {
  background-color: pink;
  &.purple{
    background-color: purple;
  }
}
```

will be compiled to:

```css
.pink { 
  background-color: pink;
}
.pink.purple { 
  background-color: purple;
} 
```

Using the & selector will not target child elements that have a class `.purple` like in the example above. It will target the parent element that has the classes `.pink` AND `.purple`.

> Beware of too much nesting as it can make your code overly complex and less readable, which would be the opposite of what we're aiming for. As a rule, I tend to go for a maximum of 3 levels of nesting.

With this in mind, let's implement nesting in our code. For example:

```scss
.eye-group {
  top: 10px;
  left: 0;
  width: 150px;
  height: 50px;
}
.eye {
  background-color: $black;
  width: 30px;
  height: 50px;
  border-radius: 100%;
}
.eye-left {
  left: 15px;
}
.eye-right {
  right: 15px;
}
``` 
becomes: 

```scss
.eye-group {
  top:10px;
  left:0;
  width: 150px;
  height: 50px;
  .eye {
    background-color: $black;
    width: 30px;
    height: 50px;
    border-radius: 100%;
    &.eye-left {
      left:15px;
    }
    &.eye-right {
      right:15px;
    }
  }  
}
```

Preprocessors are a great asset in building CSS images and will drastically speed up your workflow. They also offer more advanced options like function, loops, mixins etc. These will come in handy in more intricate illustrations, as we'll see in the last part of this series. 

####:before and :after
Until now, we’ve created a div for each shape in our smiley face. While this is totally fine, there is a way to reduce the number of HTML elements. This is where the pseudo-selectors `:before` and `:after` come in.

These [pseudo-selectors](https://css-tricks.com/almanac/selectors/a/after-and-before/) come automatically with any HTML element you create. So for any element in your HTML, you’ll be given two extra containers within which to add content. Although they are not initially present in the DOM, you can target them with the content property, like so:

```scss
.some-class:before, .some-class:after { 
  content: "";
}
```
This property can be used to insert content such as text or images. In CSS illustrations, we don't want any of that, but we still want to use the selector, which we can do by using empty quotes. While it might look like a unnecessary step, this is the property that will ensure these selectors are available, so make sure it's there.  A good way to not forget it, as well as avoiding repetition, is to assign it to all `:after` and `:before` elements by default: 

```scss
*:before, *:after {
  position: absolute;
  content: '';
}
```

As you would expect, `:before` and `:after` depend on their parent for size and positioning.

Let's look at how we can use these in our code.  Consider the `.mouth` element. It has a child: the `.tongue` element. We're going to replace the `.tongue` selector with an `:after` pseudo-selector:

```scss
.mouth {
  width: 100%;
  height: 75px;
  bottom: 0;
  background-color: $black;
  border: 5px solid $black;
  border-radius: 10px 10px 150px 150px;
  overflow: hidden;
  &:after {
    background-color: $tongue-color;
    width: 100px;
    height: 80px;
    border-radius: 50%;
    left:25px;
    top:30px;
  }
}
```
The same logic can be applied to replace the `.pupil` elements:

```scss
.eye-group {
  top: 10px;
  width: 150px;
  height: 50px;
  .eye {
    background-color: $black;
    width: 30px;
    height: 50px;
    border-radius: 100%;
    border: 5px solid $black;
    &:after {
      width: 10px;
      height: 15px;
      top: 5px;
      background-color: #FBD671;
      border-radius: 50%;
    }
    &.eye-left {
      left: 15px;
    }
    &.eye-right {
      right: 15px;
    }
  }
}
```

Now we can get rid of the `.tongue` and `.pupil` divs in the html:

```html
<div class="head">
  <div class="face">
    <div class="mouth"></div>
    <div class="eye-group">
      <div class="eye eye-left"></div>
      <div class="eye eye-right"></div>
    </div>
  </div>
</div>
```

While this isn’t absolutely necessary, I find this practice helps to keep my code cleaner, and avoids overcrowding my HTML. Again, only use pseudo-selector when it makes sense to do so. (eg: to create an element visually related to its parent container). 

####HTML templating language

Another step we can take to improve our code is to use an HTML templating language. I like to use [Pug](https://pugjs.org/api/getting-started.html),  which is also built in to the Codepen editor. 

Here’s how it works: Pug uses tag names to represent a full HTML element. For example, `<div></div>` will simply translate to `div` in Pug.  It uses indentation to represent nesting, recreating the tree structure of HTML.

In CSS images, it is recommended to use div elements only, and assign them a class to be able to easily target them. The way to represent a div with a class in Pug is as follows:

Normal html: 

````html
<div class="container"></div>
```

Pug:

```html
div.container
```

Or, because `div` is the default tag name, it can be omitted: 

```html
.container
```

I find this syntax to be much cleaner, and it allows me to focus on the class. Since I already know that all my elements are divs, I don't need any useless syntax polluting my code.

Let's convert our HTML to Pug:

```html
.head
  .face
    .mouth
    .eye-group
      .eye.eye-left
      .eye.eye-right
```

Much cleaner. 

Similarly to CSS preprocessors, there are many things you can do with Pug as it is powered by JavaScript: mixins, includes etc. When it comes to CSS images, one of the most powerful features is loops. We'll see a bit later how to use them.

Here's the final project in CodePen. You can see that none of our latest changes have affected the illustration at all.

{% codepen https://codepen.io/agathaco/pen/PdWYgp %}

Right, we’ve learned a lot already! How to create various shapes and assemble them into a cohesive illustration, how to use hacks to emulate more complex shapes, how to use preprocessors, templating languages and pseudo-selectors to improve our workflow and clean up our code. In the second part of this series, we'll practice these new concepts and build a CSS Polaroid. Then, we'll learn how to animate it.
 
[Part 2: Intro to CSS animations with a CSS Polaroid](https://dev.to/agathacco/how-to-create-pure-css-illustrations-and-animate-them---part-2-1ao4)