CSS Art Tutorial: Create the Flushed Emoji With Only 3 Classes! 😳

Eleftheria Batsou
10 min readMar 11, 2023

--

In this article, I’m describing how to create the flush emoji with only 3 HTML classes. 😳

The emoji will have a head, eyes, cheeks, and a mouth. In the end, we’ll add some animations for the eyes too!

Tools and resources:

You’ll learn:

  • How to create circles
  • How to use inner and outer shadow-ban
  • How to write pseudo-classes, and specifically we’ll use ::before, ::after and :hover
  • How to write a hover condition for a before & after pseudo-class
  • How to add simple animations

For practice, you can:

  • Add brows to this emoji
  • Create a new, different emoji

The final result:

And this image is my inspiration.

Note: If you’re curious about what CSS art is, in this article I have a short explanation.

Why did I choose the flushed emoji?

The flush emoji is one of my favorite emojis, I use it a lot and sometimes I even feel my face looks like it. So I thought “why not coding it?!” 😅

The flushed emoji is used for surprise, confusion, or even embarrassment.

Ok, let’s start!

The base 🖼️

The html code is very simple.

<div class="container">

</div>

I’ll start with creating the background in CSS. To do so, I’ll use the body.

/*  CSS Custom Properties */
:root { --bg-color: pink }

body {
background-color: var(--bg-color);
height: 100vh;
display: grid;
place-items: center;
margin: 0;
}

Here is what I did:

  • The first line sets the background color of the entire page to a variable named --bg-color. Variables in CSS are declared using the var() function and can be used to store values that will be reused throughout the stylesheet. In this case, the variable is used to set the background color of the entire page.
  • The second line sets the height of the body element to 100% of the viewport height using the vh unit (1vh is equal to 1% of the height of the viewport).
  • The third line sets the display property of the body element to grid. This tells the browser to lay out the child elements of the body element as a grid.
  • The fourth line sets the place-items property of the grid container to center. This tells the browser to align the grid items along the horizontal and vertical center of the grid container.
  • The fifth line sets the margin of the body element to 0, this will remove any default margin that the browser may have added to the body

After the body, I have the .container

.container { display: flex; justify-content: center; position: relative; }

This block of code is a class selector for an element with the class .container.

  • The first line sets the display property of the .container element to flex. This tells the browser to lay out the child elements of the .container element as a flex container.
  • The second line sets the justify-content property of the flex container to center. This tells the browser to align the flex items along the horizontal center of the flex container.
  • The third line sets the position property of the .container element to relative. This allows you to position the container relatively to its initial position, for example, you can use top, right, bottom, left properties to move it around.

Note: body and container are 2 classes I love to use as templates. I usually copy-paste them from previous projects. 😉

Create the head 🫥

Let’s start our CSS art by creating a round head.

<div class="container">
<div class="head">

</div>
</div>

We will create:

  1. a circle
  2. add color to it
  3. position it relative
.head {
/* create a circle */
width: 300px;
height: 300px;
border-radius: 50%;

/* add some color so you can see it */
border: 6px solid #e9960f;
background: radial-gradient(circle, rgba(255,230,53,1) 0%, rgba(233,150,15,1) 100%);

box-shadow: 4px 4px 36px 24px rgba(244,126,28,0.7) inset;

/* we need the position 'relative' b/s we're going to have a few elements inside the head. The elements will be positioned "absolutely" in releationship with the parent class (which is .head) */
position: relative;

/* we also need these 3 lines for the elements that are coming inside the .head */
justify-content: center;
display:flex;
align-items: baseline;
}

For the background ⬇️, I used the cssgradient.io.

background: radial-gradient(circle, rgba(255,230,53,1) 0%, rgba(233,150,15,1) 100%);

For the inner box-shadow⬇️, I used cssgenerator.org

box-shadow: 4px 4px 36px 24px rgba(244,126,28,0.7) inset;

The box-shadow property applies a drop shadow effect to the .head element. The specific value used 4px 4px 36px 24px rgba(244,126,28,0.7) inset creates an inner shadow effect with the inset keyword.

The shadow is 4px horizontally and vertically from the element, with a blur radius of 36px and spread distance of 24px.

The color is rgba(244,126,28,0.7).

Reminder: The “a" value in rgba stands for "alpha" and it specifies the opacity of the color, with 0 being completely transparent and 1 being completely opaque.

Here is an image of the result:

Create the mouth 👄

To create the mouth, we will not add a new class, instead, we’ll use the pseudo-class ::before. Here is how the code looks:

.head::after {
content: "";
position: absolute;

/* add mouth */
width: 60px;
height: 16px;
background: #834905;
margin-top: 230px;
border-radius: 40%;
border: 1px solid black;
box-shadow: -1px 2px 4px 4px rgba(98,47,2,0.5) inset;
}

If you want to simplify your version you can remove the box-shadow.

Let’s examine the first two lines of .head::before:

.head::after{
content: "";
position: absolute;
}

This CSS code targets an element with the class of .head, and it uses the ::after pseudo-element to insert some content after the element (in our case this is going to be a shadow).

  • The content: "" property sets the content of the pseudo-element to an empty string, which means it will not display any content.
  • The position: absolute sets the position of the pseudo-element to be absolute, which means it will be positioned relative to the nearest positioned ancestor element instead of the viewport.

💡 Tip: Feel free to experiment with the colors and the sizes in width, height, margin-top, etc.

Here is an image of the result:

Create the eyes 👀

And now we have some cool stuff to explore! We’ll add the last two classes in HTML (one for left eye and one for the right eye):

<div class="container">
<div class="head">
<div class="left"></div>
<div class="right"></div>
</div>
</div>

More interesting though is the CSS code. I will start by writing the 2 classes .left and .right where I basically create a circle with some color and a border.

.left, .right {
background: white;
border-radius: 50%;
border: 1px solid rgba(0, 0, 0, 0.7);
width: 110px;
height: 110px;
position: absolute;
margin-top: 80px;
/* the eyes are centered b/s of the last 3 lines in the .head */

So far so good! Eyes are ready but we’re definitely not done! In this phase, the eyes are on top of each other. We need to separate them, and here is how it’s done:

.left {
margin-left: -150px;
}
.right {
margin-left: 150px;
}

Perfect!

To make them look even better I’ll add an inner shadow using the .left::before and .right::before pseudo-classes:

.left::before, .right::before {
content: "";
position: absolute;

/* add the inner shadow (the shadow inside the eyes) */
width: 110px;
height: 110px;
border-radius: 50%;
box-shadow: 1px 2px 8px 8px rgba(144,127,87,0.8) inset;
}

Note: If you wanted to simply your version of emoji, you could add the box-shadow to the .left and .right classes, and not use the pseudo-classes at all.

The pupils:

In the eyes, we need to add the pupils… The pupils will be black circles (we’ll do this inside the eyes, which for us these are the classes .left and .right):

So firstly, I need to add this block of code in the classes .left and .right:

.left, .right {
...

/* we also need the 3 lines b/s we are going to add the pupils inside the class .left, .right */
display: flex;
justify-content: center;
align-items: center;
}

Then, I’ll create the pseudo-classes .left::after and .right::after :

.left::after, .right::after {
content: "";
position: absolute;

/* Create the pupils */
width: 40px;
height: 40px;
background: black;
border-radius: 50%;
}

Yes! Eyes are completed!

Here is an image of the result:

Create the cheeks 🌸

To make the emoji look even better, we all the cheeks. This is fairly simply as we don’t need any new classes or many lines of code.

The cheeks will actually be a shadow!

Let’s return to the .left and .right classes, here is what we need to add:

  /* add cheeks as an outer shadow (the shadow outside the eyes)  */
box-shadow: 0px 50px 19px -4px rgba(242,122,24,0.9);

Here is an image of the result:

And actually, we’re done with creating a basic flushed emoji!

You can experiment by adding eyebrows, changing the colors, the sizes, and more!

Bonus: Add animation to the eyes

If you want something extra in your CSS art why not add adding an animation?! I decided to use an animation for the eyes.

There’re two things we are going to do:

  1. Animation for the pupils when the CSS loads
  2. Animation when you hover into the eyes

We don’t need any extra classes on the HTML part. We’ll just add a few lines in the CSS part.

Let’s start with case no.1 — Animation for the pupils when the CSS loads.

The pupils are done with the pseudo-classes .left::afterand.right::after so here is where we'll the code:

.left::after, .right::after {
content: "";
position: absolute;

/* Create the pupils */
width: 40px;
height: 40px;
background: black;
border-radius: 50%;

animation: zoom-in-zoom-out 1s ease 4;
}

In the last line, I’m adding an animation with the name zoom-in-zoom-out with a duration of 1s, an easing effect of ease, and 4 iterations.

💡 Tip: You can find many more animations in animista.net

I’ll continue by defining the animation:

@keyframes zoom-in-zoom-out {
0% {
transform: scale(1, 1);
}
50% {
transform: scale(1.5, 1.5);
}
100% {
transform: scale(1, 1);
}
}

This block of code creates a keyframe animation named zoom-in-zoom-out.

It has three stages:

  • 0% of the animation: the transform property is set to scale(1, 1), meaning that the element will be scaled normally with no change in size.
  • 50% of the animation: the transform property is set to scale(1.5, 1.5), meaning that the element will be scaled to 150% of its original size along both the X and Y axis.
  • 100% of the animation: the transform property is set to scale(1, 1) again, so the element will return to its normal size at the end of the animation.

The animation property will use the keyframe animation, and will run for 1 second with an ease-out effect, repeating 4 times.

💡 Tip: To see this effect, reload your page!

Now, let’s go to case no.2 — Animation when you hover into the eyes.

We’ll cover this case with just one line of CSS code. Here it goes:

.left:hover, .right:hover { animation: zoom-in-zoom-out 1s ease 2; }

Now everytime you hover the left or right eye you will see the animation as defined in zoom-in-zoom-out, with a duration of 1 second, an easing effect of "ease" and 2 iterations.

💡 Tip: To see this effect, hover with your mouse over the eyes!

Sum up💫

In this article, I described how to create an emoji using only CSS and HTML. More specifically, we created the emoji with just 3 classes (.head, .leftand .right). We used the pseudo-classes ::before and ::after to achieve things such as the mouth, the pupils, etc. Many of the emoji's characteristics, such as the cheeks, have been created with inner or outer shadows. Last but not least, there is an enlarged effect (animation) in the eyes.

If you have any questions feel free to ask them in the comments!

Before you start creating something similar, it’d be good to know how:

  • positions work (mainly position absolute, relative)
  • some basic flex-box properties work
  • to play around with box-shadow
  • to use the ::before and ::after
  • Extra: animations

Feel free to tag me if you try something similar. I’d love to see your art!

Thank you for reading! Find the code on Codepen.

👋 Hello, I’m Eleftheria, developer & public speaker.

🥰 If you liked this article consider sharing it.

Originally published at https://blog.eleftheriabatsou.com.

--

--

Eleftheria Batsou

Hi, I’m a community manager and an app developer/UX researcher by passion. I love learning, teaching and sharing. My passions are tech, UX, arts & working out.