Drawing with CSS: Anime Character
Tags: css, html, webdev, art
Published: 2022-05-26 08:22:56

---
title: Drawing with CSS: Anime Character
published: true
description: How to draw a manga/anime character with CSS (with video!)
tags: css,html,webdev,art
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wnsjy5ha2hqbafgcsbu2.png
canonical_url: https://alvaromontoro.com/blog/68006/drawing-with-css-anime-character
---

Drawing in CSS is relaxing (at least for me) and an excellent way to practice CSS. Sometimes it's helpful to try new features that cannot always make it into production because not all browsers may support them.

In this article, I will explain how I drew the manga/anime drawing from the image above using HTML and CSS and dive into the creative process, getting into some detail about why I made some of the decisions and their pros and cons. At the end of the article, you will find a video with the whole process.

## The Drawing

The drawing started from scratch. No HTML, No CSS. Just a blank page. Initially, I didn't know what I would draw at all! But I had volume 2 of the manga Pluto next to me, so I decided to code something manga-related, getting some inspiration from the cover (e.g., for the nose and the mouth).

I like the result, but I'm biased. Here is a live demo of the drawing (you can see the [full version on CodePen](https://codepen.io/alvaromontoro/full/ExQbYbw)):

{% codepen https://codepen.io/alvaromontoro/pen/ExQbYbw %}

Let's see how different parts of the image came to life.

### Canvas

Don't worry. There's no place for `<canvas>` in CSS art. I like setting the root element of the drawing as a "canvas" and adding a grid at the beginning:

```css
.canvas {
  width: 80vmin;   /* so it's responsive */
  aspect-ratio: 1; /* so it's a square.  */
  background:
    repeating-linear-gradient(#0003 0 0.125%, #0000 0 0.9875%, #0003 0 10%),
    repeating-linear-gradient(90deg, #0003 0 0.125%, #0000 0 0.9875%, #0003 0 10%);
}
```

This code generates a background with a 10x10 grid. Each square is 10%, and knowing that helps me place the items later: count the number of squares and multiply by 10 to calculate the percentage needed in `top`, `left`, `width`, or `height`.

### Head/Face

The face breaks into three parts: the forehead, left, and right sides. For them, I used a single element (forehead), and then the `::before` (left) and `::after` (right) pseudo-elements for the sides.

I could have just done an egg shape, which is super easy to do in CSS with `border-radius` and different values for horizontal and vertical:

```css
.egg-shape {
  width: 80vmin;
  height: 80vmin;
  border-radius: 100% / 80% 80% 120% 120%;
  background: red;
}
```

Instead, I overcomplicated things a little. However, having three elements allowed for _sharper_ edges (e.g., the chin), and I wanted to try this approach as I always go the "egg-shape route." The result looks nice, but it might not have been worth it.

On the other hand, having different elements permitted some extra customization (like adding `transform` or inset shadows) that would have been more complicated if it was only one element. So not everything is bad.

### Mouth

The mouth is not a simple line. It is also conformed of three parts to give some "texture," so it's not just a flat thing. In this case, I did it by playing with the border widths, but I could have done it with clip-paths (it would have been a pain later with the pseudo-elements) or linear gradients (it would have been a pain later with the shadows). Browsers may display slightly differently, but it is a price I'll pay.

The object is later used to provide some lip shadow with `box-shadow`: one on top and another on the side.

### Ears

Both ears are the same. The trick to quickly flipping an element horizontally is to apply a `transform` of `scaleX(-1)` and _voilà_! It's done!

```css
.ear {
  /* code to draw the ear: border-radius, backgrounds... */
}

/* select the second ear and flip it */
.ear + .ear {
  transform: scaleX(-1);
}
```

Once that's done, to make them look slightly different, I rotated the second one at a slightly different angle and also pushed it a little bit farther (from the other side). Combined with the various elements from both sides, that gives the impression of having two different ears.

### Eyes

Drawing eyes is always tricky. They make or break the drawing, and the balance between one and the other is subtle. The eyes on this drawing are far from perfect, but they are Ok.

Each eye is two elements: a `div` (for the eye in itself) and one pseudo-class (for the pupil and iris). The eye will have an `overflow:hidden` so the pseudo-element doesn't extend beyond its scope.

The pupil and the iris are radial gradients, with more radial gradients for the light reflections and box-shadows to trace small lines on each eye side. However, after duplicating the eye and flipping the second one, there's something different left to do: to avoid having an unwanted symmetry that looks weird (light reflections coming from different directions), the pseudo-element of the second eye needs to be flipped too:

```css
.eye {
  /* eye styles */
}

.eye + .eye {
  transform: scaleX(-1); /* flip the eye */
}

.eye + .eye::before {
  transform: scaleX(-1); /* flip the iris in the second eye */
}
```

### Neck

The neck element is just going to be a container for its `::before` and `::after` pseudo-elements, which will be the sides of the neck.

Using `box-shadow`, the elements' shadow will be the colors of the neck, and it will provide some shadow. Using `transform` to rotate and skew, the shapes will be softer and look more like a cartoon neck than if I just had a rounded corner.

### Hair

The hair consists of eight times the same element with slight variations (in position and size, but sometimes also in the background). I initially used borders and box shadows to draw the bangs, but that was a problem when trying to make them look different (plus, it looks terrible in browsers other than Chrome). Another problem with this approach is that the top part of the hair bangs has an undesired black line on Chrome (it has some trouble at times with things like that.)
So I opted for box shadows and gradients to draw the hair:

```css
.bangs {
  width: 30%;
  height: 30%;
  border-radius: 0 0 100% 0;
  /* to draw the external border */
  box-shadow: inset -0.5vmin -0.25vmin; 
  /* the hair and internal border */
  background: radial-gradient(100% 170% at -10% 0, #0000 58.75%, #000 59% 60.25%, var(--hair-dark) 60.5%, var(--hair) 78%); 
}
```

Flipping the hair (remember the trick of `scaleX(-1)`) and rotating it makes it look different enough to be reusable… and that's what I did.

### Face Lines

There are multiple lines in the drawing: eyebrow, nose, chin, etc. The "simple" way would be to have an element for each line (or group of lines), but the drawing will end up with many parts.

Instead, I opted for reducing the number of lines to a minimum and to shapes that can be replicated with background images (gradients). Then with a single element that covers the whole face, I added those lines one by one as `radial-gradient` or `linear-gradient`.

## Accessibility

CSS art is not very accessible in general, but that doesn't mean that it doesn't have to be accessible. By adding a role of image and an `aria-label` with a description of the drawing, the drawing will be more accessible for assistive technology users.

```html
<article role="img" aria-label="....">
  ...
</article>
```

I opted for using an `<article>` because it is a self-contained element. Ideally, instead of using `aria-label` I should have used `aria-labelledby` and placed an `<h1>` or `<h2>` with the title/description.

In this other article, I explain [ways of making CSS art more accessible for everybody](https://alvaromontoro.com/blog/67979/creating-accessible-css-art).

## Live Coding Video

The whole process took around three hours, I sped the video by 2, so there's a 1.5 hours video showing how it is done step by step:

{% youtube SmxtzokF9Bw %}

If that's too long or too slow, there is also an [8x speed video](https://www.youtube.com/watch?v=kMN-Xd_dcR4) that only lasts around 20 minutes. 

---

If you like these videos or CSS art, check [my Youtube channel](https://www.youtube.com/c/AlvaroMontoroCSS)! I publish videos about CSS and live-coding of CSS art.