CSS Art – How to Make a Game Character – Super Mario

A plumber jumping in and out of pipes, throwing fireballs while rescuing a princess. Step-by-step article to create a world renowned game character.

CSS Art – How to Make a Game Character – Super Mario

Introduction

Nintendo’s Super Mario is probably one of the most recognizable video game character in the world. Generations of video game players adore this fun and unique game character.

In this article, we’ll be creating Super Mario with CSS. Here’s a quick list of the different CSS technologies we’ll be using in this article:

Visit our CSS Art articles if you’re unfamiliar with the above CSS technologies.

Preview

Super Mario
Super Mario

We will break down our image to these different parts:

  1. Hat
  2. Eyes
  3. Face
  4. Nose
  5. Mustache
  6. Mouth
  7. Sideburn
  8. Ears

Prerequisites

We don’t assume prior knowledge of CSS or HTML, but it helps if you have some familiarity with how they work. Jump over to this article if you require an HTML and CSS primer.

We assume that you have set up tools to create CSS art. If you haven’t, this article will show you how to set them up.

HTML Structure

Here’s the HTML code for our image.

<div class="container">
  <div class="character">
    <div class="hat"></div>
    <div class="hat-lip"></div>
    <div class="hat-logo"></div>
    <div class="face"></div>
    <div class="eye-brow-right"></div>
    <div class="eye-right"></div>
    <div class="eye-brow-left"></div>
    <div class="eye-left"></div>
    <div class="eye-highlight"></div>
    <div class="nose"></div>
    <div class="mustache"></div>
    <div class="mouth"></div>
    <div class="sideburn"></div>
    <div class="ear"></div>
  </div>

container is our outermost enclosure. This enables us to center the art and put a light gray border. The rest of divs represent each of Super Mario’s hat and facial parts.

It’s important to keep the HTML structure as is for each part to display properly.

Color Palette

Here’s the CSS code for the color palette, body and container div.

/**************************************/
/* Color, Body and Container Settings */
/**************************************/

/* Color palette using CSS custom properties (variables) */
:root {
  --white: #fefefe;
  --red: #fe0000;
  --dark-red: #b80000;
  --beige: #efcf86;
  --light-blue: #038dfb;
  --brown: #490900;
  --black: #000000;
}

/* Center shapes */
body {
  margin: 0;
  padding: 0;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
}

/* Set light gray border */
.container {
  width: 500px;
  height: 500px;
  border: 5px solid lightgray;
  background: transparent;
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 1px;
}

Ready for this coding adventure?

Let’s dive in to the CSS code. We will be creating the hat part in the next section.

Hat

Hat - Final
Hat - Final

Let’s start making Super Mario’s hat.

Hat
Hat

CSS Code:

.hat {
  position: absolute;
  width: 69px;
  height: 103px;
  top: 229px;
  left: 382px;
  background: var(--red);
  border: solid 8px var(--black);
  border-top-right-radius: 100px;
  border-bottom-right-radius: 100px;
  border-left: 0;
  transform: rotate(5deg);
}

We’re using CSS custom properties (variables) to set our colors.

Here’s the default way to set a background color.

background: red;

And here’s how we set colors using CSS custom properties.

background: var(--red);

Big advantages of using CSS custom properties (variables) are being able to centralize the color value. Our red color value is set to a hexadecimal (hex) value of #fe0000. It will be difficult to remember that hex code. By using CSS custom properties, we can assign a more human-readable keyword to the color value.

Another advantage is since we centralized the color value, in the future, let’s say you decide to change the hat color to green, you only need to change the hex value in one location. The color changes propagate throughout the CSS custom properties. Very handy!

Hat
Hat

CSS Code:

.hat::before {
  content: "";
  position: absolute;
  width: 236px;
  height: 337px;
  top: -217px;
  left: -252px;
  background: var(--red);
  border-top: solid 8px var(--black);
  border-right: solid 8px var(--black);
  border-left: solid 8px transparent;
  border-bottom: solid 8px transparent;
  border-radius: 50%;
  transform: rotate(-35deg);
}

We only need a top and right border for this part. We can set that using the below code.

border-top: solid 8px var(--black);
border-right: solid 8px var(--black);
border-left: solid 8px transparent;
border-bottom: solid 8px transparent;

Left and bottom borders are set to transparent.

We rotated the ellipse with this code.

transform: rotate(-35deg);
Hat
Hat

CSS Code:

.hat::after {
  content: "";
  position: absolute;
  width: 109px;
  height: 70px;
  top: -157px;
  left: -235px;
  background: var(--white);
  border: solid 8px var(--black);
  border-top-left-radius: 100px;
  border-top-right-radius: 100px;
  border-bottom: 0;
  transform: rotate(23deg);
}

This part will enclose the “M” logo that we’ll be creating in a later section.

We used border-top-left-radius and border-top-right-radius to create this half circle shape.

Let’s make the hat lip in the next section.

Hat Lip

It’s easier to make the outline or border of a shape first. Let’s see how we can do this below.

Hat Lip Outline
Hat Lip Outline

CSS Code:

.hat-lip {
  position: absolute;
  width: 290px;
  height: 155px;
  top: 98px;
  left: 53px;
  background: var(--black);
  clip-path: path("M 285,149 C 229,62 164,21 73,2 C -36,-7 -7,77 55,126");
}

We’re using the CSS path() function to create this shape. If you’re not familiar with CSS path() and Scalable Vector Graphics (SVG) check this article.

Let’s break down the SVG code.

  1. We set our starting point with this code.
M 285,149 
  1. This code draws the first arch of the shape.
C 229,62 164,21 73,2 
  1. This code draws the second arch.
C -36,-7 -7,77 55,126

If you want to avoid using SVG, you can experiment with CSS transform-function such as skew() and rotate() function to recreate the hat lip shape. Here’s a step-by-step article on how to use CSS transform-function.

Hat Lip
Hat Lip

CSS Code:

.hat-lip::after {
  content: "";
  position: absolute;
  width: 285px;
  height: 146px;
  top: 0;
  left: 0;
  background: var(--red);
  clip-path: path("M 276,160 C 229,85 164,22 73,9 C -31,-2 27,90 60,114");
}

Similar to the hat lip outline, we’re using CSS path() function and SVG to create this shape.

In the next section, let’s create the “M” logo.

Logo Outline
Logo Outline

CSS Code:

.hat-logo {
  position: absolute;
  width: 110px;
  height: 90px;
  top: 66px;
  left: 159px;
  background: var(--black);
  clip-path: polygon(
    44% 33%,
    67% 8%,
    91% 81%,
    79% 89%,
    68% 82%,
    58% 41%,
    39% 58%,
    32% 38%,
    21% 53%,
    8% 44%,
    35% 9%
  );
}

We’re using CSS polygon() function to create the logo. We won’t explain how to use polygon() function here. Check this article for step-by-step instructions on how to make shapes with polygon().

Logo
Logo

CSS Code:

.hat-logo::before {
  content: "";
  position: absolute;
  width: 110px;
  height: 90px;
  top: 0px;
  left: 0px;
  background: var(--red);
  clip-path: polygon(
    43% 38%,
    65% 16%,
    87% 80%,
    80% 84%,
    72% 79%,
    59% 35%,
    41% 52%,
    33% 32%,
    21% 48%,
    12% 43%,
    34% 16%
  );
}

Our code for the red shape is similar to the outline shape. You can control the different points of the polygon by adjust the percentage values within the code.

We’re done with the hat. Let’s move on to our first facial part, the right eye.

Right Eye

Right Eye
Right Eye

CSS Code:

.eye-right {
  position: absolute;
  width: 55px;
  height: 85px;
  top: 217px;
  left: 193px;
  background: var(--white);
  border: solid 8px var(--black);
  border-radius: 50%;
  transform: rotate(16deg);
}

Simple white ellipse with black borders. We rotated it slightly with this code transform: rotate(16deg);.

Right Eye Iris
Right Eye Iris

CSS Code:

.eye-right::before {
  content: "";
  position: absolute;
  width: 40px;
  height: 66px;
  top: 9px;
  left: 12px;
  background: var(--light-blue);
  border: solid 4px var(--black);
  border-radius: 50%;
}

We gave the iris shape a light blue background. Using the top and left CSS properties, we positioned it to the bottom-right side of our enclosing white ellipse.

Right Eye Pupil
Right Eye Pupil

CSS Code:

.eye-right::after {
  content: "";
  position: absolute;
  width: 29px;
  height: 50px;
  top: 24px;
  left: 27px;
  background: var(--black);
  border-radius: 50%;
}

Our pupil code is a slight variation of the iris code. We gave it a black background and set no borders.

Our right eye is almost finished. In the next section, let’s make the right eyebrow.

Right Eyebrow

Two ellipses compose the eyebrow. One is black, and the other one is beige color.

Right Eyebrow
Right Eyebrow

CSS Code:

.eye-brow-right {
  position: absolute;
  width: 70px;
  height: 104px;
  top: 176px;
  left: 205px;
  background: var(--black);
  border-radius: 50%;
  transform: rotate(24deg);
}

This ellipse will be our black eyebrow.

Right Eyebrow
Right Eyebrow

CSS Code:

.eye-brow-right::before {
  content: "";
  position: absolute;
  width: 74px;
  height: 87px;
  top: 26px;
  left: -2px;
  background: var(--beige);
  border-radius: 50%;
}

This beige ellipse will give our black eyebrow its crescent shape.

Next section will be left and eyebrow.

With a slight variation in size and location, the process of creating them is similar to the right eye. For brevity, we will only provide the CSS code.

Left Eye

Left Eye
Left Eye

CSS Code:

.eye-left {
  position: absolute;
  width: 36px;
  height: 62px;
  top: 202px;
  left: 121px;
  background: var(--white);
  border: solid 8px var(--black);
  border-radius: 50%;
  transform: rotate(8deg);
}
Left Eye Iris
Left Eye Iris

CSS Code:

.eye-left::before {
  content: "";
  position: absolute;
  width: 25px;
  height: 44px;
  top: 12px;
  left: 7px;
  background: var(--light-blue);
  border: solid 4px var(--black);
  border-radius: 50%;
  transform: rotate(0deg);
}
Left Eye Pupil
Left Eye Pupil

CSS Code:

.eye-left::after {
  content: "";
  position: absolute;
  width: 23px;
  height: 33px;
  top: 23px;
  left: 17px;
  background: var(--black);
  border-radius: 50%;
}

Left Eyebrow

Left Eyebrow
Left Eyebrow

CSS Code:

.eye-brow-left {
  position: absolute;
  width: 48px;
  height: 88px;
  top: 162px;
  left: 121px;
  background: var(--black);
  border-radius: 50%;
}
Left Eyebrow
Left Eyebrow

CSS Code:

.eye-brow-left::before {
  content: "";
  position: absolute;
  width: 50px;
  height: 73px;
  top: 24px;
  left: -1px;
  background: var(--beige);
  border-radius: 50%;
}

We’ve completed the left eye and eyebrow.

In the next section, let’s make the eye highlights.

Eye Highlight

Left Eye Highlight
Left Eye Highlight

CSS Code:

.eye-highlight {
  position: absolute;
  width: 9px;
  height: 12px;
  top: 242px;
  left: 155px;
  background: var(--white);
  border-radius: 50%;
  transform: rotate(3deg);
}

Similar to the pupil and iris, the highlight is an ellipse shape.

Right Eye Highlight
Right Eye Highlight

CSS Code:

.eye-highlight::before {
  content: "";
  position: absolute;
  width: 10px;
  height: 15px;
  top: 15px;
  left: 87px;
  background: var(--white);
  border-radius: 50%;
  transform: rotate(3deg);
}

Experiment with the location of the highlights. Make it so that it’s looking directly at you.

In the next section, we’ll be making the rest of the facial parts.


First up is the face.


Pyxofy Membership Sign Up
Pyxofy Membership Sign Up

Face

The face will be created with path() function and SVG. This is the most complex code in this article.

Face Outline
Face Outline

CSS Code:

.face {
  position: absolute;
  width: 347px;
  height: 302px;
  top: 180px;
  left: 74px;
  background: var(--black);
  clip-path: path(
    "M 0,202 C 0,200 0,240 58,258 C 71,312 161,316 185,274 C 216,277 247,242 246,237 C 246,236 298,271 336,206 C 371,143 316,112 285,118 C 288,112 265,63 262,65 L 248,64 C 235,69 204,29 204,30 C 163,-10 78,-2 60,13 C 35,31 29,59 29,64 Z"
  );
}

First, we create the black outline. If the shape doesn't render properly in your browser, check the path() code meticulously. You can break down the code like this.

M 0,202 
C 0,200 0,240 58,258 
C 71,312 161,316 185,274 
C 216,277 247,242 246,237 
C 246,236 298,271 336,206 
C 371,143 316,112 285,118 
C 288,112 265,63 262,65 
L 248,64 
C 235,69 204,29 204,30 
C 163,-10 78,-2 60,13 
C 35,31 29,59 29,64 
Z

Take note that each alphabet letter is a command to draw the shape in SVG.

Face
Face

CSS Code:

.face::after {
  content: "";
  position: absolute;
  width: 347px;
  height: 302px;
  top: 0;
  left: 0;
  background: var(--beige);
  clip-path: path(
    "M 12,203 C 15,222 26,234 66,250 C 75,300 156,307 175,266 C 223,267 241,224 241,224 C 267 239 301 244 325 203 C 356 142 311 122 283 131 C 290,144 266,84 252,67 L 251,67 C 235,79 204,53 200,44 C 163,-4 78,2 60,23 C 50,31 43,57 39,68"
  );
}

Let's break down the SVG code again for the beige part.

M 12,203 
C 15,222 26,234 66,250 
C 75,300 156,307 175,266 
C 223,267 241,224 241,224 
C 267 239 301 244 325 203 
C 356 142 311 122 283 131 
C 290,144 266,84 252,67 
L 251,67 
C 235,79 204,53 200,44 
C 163,-4 78,2 60,23 
C 50,31 43,57 39,68

You can use an SVG code visualizer tools like this one to help you understand how the different SVG commands work.

Next will be the nose.

Nose

Nose Outline
Nose Outline

CSS Code:

.nose {
  position: absolute;
  width: 146px;
  height: 132px;
  top: 243px;
  left: 40px;
  background: var(--black);
  clip-path: path("M 130,31.5 C 63,-21 6,-1 0,61 C 0,109 79,178 145,87");
  /* Take care of Webkit border-radius bug */
  -webkit-mask-image: -webkit-radial-gradient(white, black);
}

We’re using this code to take care of a Webkit (Safari) border-radius bug. Without this code, a thin line will appear around the border of the shape.

/* Take care of Webkit border-radius bug */
-webkit-mask-image: -webkit-radial-gradient(white, black);

Firefox and Chromium-based browser doesn’t have the above bug and should display the nose shape properly.

Nose
Nose

CSS Code:

.nose::after {
  content: "";
  position: absolute;
  width: 146px;
  height: 132px;
  top: 0px;
  left: 00px;
  background: var(--beige);
  clip-path: path("M 136,43.5 C 56,-4 25,4 14,60 C 9,108 101,136 146,66");
}

That completes our nose part.
Next up is the mustache.

Mustache

Mustache
Mustache

CSS Code:

.mustache {
  position: absolute;
  width: 222px;
  height: 94px;
  top: 304px;
  left: 46px;
  background: var(--black);
  clip-path: path(
    "M 212,3 C 228,18 223,53 191,53 C 191,80 147,86 137,72 C 137,77 125,103 86,83 C 86,90 57,102 44,79 C 45,78 21,85 16,61 C 11,59 0,54 2,27 C 50,101 117,46 137,30 C 140,32 198,17 205,3"
  );
}

We made the mustache with path() and SVG, but you can use a combination of half circles to make it as well.

path() code break down.

M 212,3 
C 228,18 223,53 191,53 
C 191,80 147,86 137,72 
C 137,77 125,103 86,83 
C 86,90 57,102 44,79 
C 45,78 21,85 16,61 
C 11,59 0,54 2,27 
C 50,101 117,46 137,30 
C 140,32 198,17 205,3

Let’s make the mouth part in the next section.

Mouth

Mouth Outline
Mouth Outline

CSS Code:

.mouth {
  position: absolute;
  width: 78px;
  height: 61px;
  top: 386px;
  left: 157px;
  background: var(--black);
  border-radius: 10px 5px 81px 70px;
  transform: rotate(-15deg);
}

We’re using border-radius to create the mouth shape.

border-radius: 10px 5px 81px 70px;

Experiment with the pixel, px, properties and modify the mouth shape to your liking. May be make it closed instead of open.

Teeth
Teeth

CSS Code:

.mouth::before {
  content: "";
  position: absolute;
  width: 62px;
  height: 17px;
  top: 5px;
  left: 9px;
  background: var(--white);
  border-radius: 8px 7px 16px 17px;
}

We made the teeth similar to how we made the mouth, using border-radius.

Tongue
Tongue

CSS Code:

.mouth::after {
  content: "";
  position: absolute;
  width: 51px;
  height: 26px;
  top: 26px;
  left: 14px;
  background: var(--red);
  border-radius: 17px 21px 79px 86px;
}

By completing the tongue, we’re done with the mouth part.

We’re almost done. In the following sections, we’ll create the sideburn and the ear.

Sideburn

Sideburn Outline
Sideburn Outline

CSS Code:

.sideburn {
  position: absolute;
  width: 86px;
  height: 106px;
  top: 264px;
  left: 277px;
  background: var(--black);
  clip-path: path(
    "M 61,0 L 83,46 Q 59,70 53,80 C 45,127 -19,94 10,61 C -13,44 7,16 35,24 Q 55,19 61,0"
  );
}

The sideburn is a very tricky shape to make. You may have noticed a pattern by now, for super complicated shapes we use path() and SVG.

M 61,0 
L 83,46 
Q 59,70 53,80 
C 45,127 -19,94 10,61 
C -13,44 7,16 35,24 
Q 55,19 61,0
Sideburn
Sideburn

CSS Code:

.sideburn::after {
  content: "";
  position: absolute;
  width: 85px;
  height: 106px;
  top: 0px;
  left: 0px;
  background: var(--brown);
  clip-path: path(
    "M 67,7 L 80,39 L 48,73 C 47,113 -13,93 22,63 C 2,54 4,25 37,35 Q 60,27 66,11"
  );
}

That completes our sideburn.
Let’s make our ear.

Ear

Ear
Ear

CSS Code:

.ear {
  position: absolute;
  width: 65px;
  height: 45px;
  top: 341px;
  left: 334px;
  border-top: solid 8px var(--black);
  border-radius: 50%;
  /* Take care of Webkit border-radius bug */
  -webkit-mask-image: -webkit-radial-gradient(white, black);
  transform: rotate(-42deg);
}

Similar to the nose part, we’re using a Webkit border-radius hack for this part.

Ear
Ear

CSS Code:

.ear::before {
  content: "";
  position: absolute;
  width: 32px;
  height: 20px;
  top: 0px;
  left: 13px;
  border-top: solid 5px var(--black);
  border-radius: 50%;
  /* Take care of Webkit border-radius bug */
  -webkit-mask-image: -webkit-radial-gradient(white, black);
  transform: rotate(32deg);
}

We’re done with our ear part.

You’ve successfully created a Super Mario image. Give yourself a big pat on the back for joining us all the way to the end.

Please don't hesitate to experiment with the CSS code. How about changing the hat or iris color? Maybe make the hat logo have a much rounder shape.

You can see and play with the code at Pyxofy’s CodePen page.

See the Pen CSS Art – How to Make a Game Character – Super Mario by Pyxofy (@pyxofy) on CodePen.

Conclusion

To create Super Mario, we combined path(), SVG, polygon() and other CSS functions and properties.

SVG code within path() is initially challenging, but through practice you will be able to grasp how they work. Use the SVG visualizer tools introduced in the article to help you get up to speed with SVG syntax and commands.

We’ll be making two more video game characters. Can you guess which ones? Share your guess with us on Twitter @pyxofy, on LinkedIn, or Facebook.

We hope you liked this article. Kindly share it with your network. We really appreciate it.

CSS Art – How to Make a Space Shuttle – Orbiter
Space shuttle orbiters are amazing machines. Can we make it with CSS? You bet! Join us making it step-by-step.
CSS Art - How to Make a Simple House
Let’s make a simple house using CSS and HTML. We’ll break down the house into basic shapes. Step by step guide, showing you how to make CSS Art.
CSS Art
Articles for creating CSS Art.
スクラッチプログラミング - プラットフォームゲームのつくりかた
かんたんなプラットフォーマーをプログラミングできるようになりましょう。変数(へんすう)をつかったリアルなジャンプ、スプライトのそうさ方法(ほうほう)やあたりはんていなど、つくりかたの基本(きほん)をしょうかいします。