Normally I only do time-lapses of me coding and doing CSS Art. This time I shared a video with comments and descriptions of what I was doing:
And if you prefer to read, here's a summary of the process (a simplified version of the video)
Drawing
I always start the CSS drawings by setting an element that will serve as canvas (not to be confused with the <canvas>
element). In it, I always set the following properties:
width
andheight
: the size of the drawing.font-size
: so I can use the em unit and easily change units if I want to.position
: to relative so I can position elements within the element.- In this top element, I also place custom properties with the colors that I will use in the drawing. Again, it makes it easier to update things later.
- Also, I set some rules so all the children of the container will have an absolute position (including their pseudo-elemenets.)
The CSS looks like this:
article {
font-size: 1vmin;
width: 80em;
aspect-ratio: 1;
position: relative;
*, *::before, *::after {
position: absolute;
box-sizing: border-box;
}
}
Then I can start drawing the elements.
Head
I always start drawing the character's head. I guess that's my process, but it helps me setting things in perspective.
In this case, the head is an oval. You can create that shape by setting different values for horizontal and vertical radii (separating them with a slash, /
). This is a value that works well in general:
border-radius: 100% / 120% 120% 80% 80%;
Eyes
I wanted to give the drawing a kawaii style, and that meant big rounded eyes with bright sparkles. One circle for each eye, then the pupil and light circles could be easily achieved with radial gradients.
One trick: hard stops in gradients look too "harsh" to pixelated and sharp. Instead of starting a color at the same value of the previous color stop, you can add one pixel using calc() and make the transition between colors a lot smoother (and nicer):
/* sharp/pixelated transition between colors */
background: radial-gradient(black 50%, white 0);
/* smooth transition between colors */
background: radial-gradient(black 50%, white calc(50% + 1px));
Nose
The nose is a simple ellipse. I made it pink to add a little bit of color contrast and to match the ears.
Ears
The ears are an eye shape with softer corners:
border-radius: 5% 90%;
Add a border with the fur color, and a background with the skin color and it's done. Using a custom property makes it simple to separate both ears the same distance from the edges.
Body
For the body, I used the egg/bell shape again (really versatile for drawing). centered it horizontally and to the bottom, and done! You may notice that many of the body parts are like that: applied shape XYZ, positioned it within the container, and moved to the next element. If you learn how to create CSS shapes, things become "easy."
Legs
The legs were a bit trickier. I initially started with two separate elements, one for each leg... but ended up dropping the idea because it was a bit painful handling both.
Instead, I went with a single element that span the width of both legs, and played a little bit with the horizontal and vertical border-radius until I found some values that I liked:
border-radius: 8em 8em 100% 100% / 10em 10em 16em 16em;
You may have noticed that this border radius is flatter at the top and more curved at the bottom. Lazy me chose to flip the element (using the property scale: 1 -1
) instead of changing the value.
Arms
The arms are just empty elements with white borders. Simple, direct, and easy to create. Not everything needs to be a fancy shape.
Tail
The tail was a mess. I used an element with a border in a single side, but that ended with a tail ending in a straight line. So I used the ::before
pseudo-element to place it at the end of the border and make it round.
While I would like to say that I used some mathematical function to calculate the position (their certainly is one, probably using the CSS trigonometrical functions), I must admit that I positioned the tip of the tail guestimating and following a trial-and-error process.
Shadow
Finally, I added a shadow below the body. Nothing fancy, an arc using border-radius. Probably a neat one to remember:
/* arc, produces a semicircle for aspect-ratios = 2 */
border-radius: 50% / 100% 100% 0 0;
Here's a live demo with the drawing so far:
Animation
I was going to describe each animation independently, but the article is already long enough... and all the animations are basically the same:
- Setting a
transform-origin
: that way the movement doesn't happen from the center of the shape but from wherever I want (e.g. I don't want the head to tilt from the center-center but from the bottom-center, so it looks like the cat is moving the neck) - Defining the
@keyframes
with the transforms and movements that I wanted: head tilting, tail swinging, eyes blinking...
I don't consider myself a CSS animation expert (far from that). I barely do small things. But if I had to recommend something that would be: do not use the same durations and timing functions for all the animations. It looks unnatural. Add diversity.
Here's a demo with the animated drawing: