In this tutorial, you’ll learn the basic building blocks of single div drawing with CSS, putting them all together at the end to draw a lollipop.
The goal of this blog post is to introduce you to the world of single div drawing. Hopefully by the time you reach the end of it, you will be motivated to express your artistic creativity using CSS as your medium.
I didn’t know single div drawing was a thing until about two years ago when I came across a tweet from @lynnandtonic. It took me to this codepen she wrote and I was impressed. Then I realized she created the animated drawing using pure CSS. No JavaScript and the only HTML element on the page was a div with no content! This was both a humbling and a mind-blowing experience.
I made a mental note to give this a try, and here I am two years later with something to finally share.
I will walk you through how I created my first single div drawing: a lollipop.
However, before I jump into the steps I took to create the lollipop, there are several basics to single div drawing I want to cover first.
The Basics of Single Div Drawing
At it’s core, single div drawing is just drawing in layers. Many, many layers for the more complex and intricate drawings.
There are three main techniques commonly used for building up the layers in a single div drawing.
::before and ::after pseudo-elements
Selectors have a ::before
pseudo-element that inserts content before the selector’s content, and an ::after
pseudo-element that appends content after the selector’s content. By default, the pseudo-elements are added inline.
Here’s a simple example of how that works with a paragraph element:
<p>Some fancy quote</p>
And this corresponding CSS:
p::before {
content: open-quote;
}
p::after {
content: '!';
}
The p::before
pseudo-element is going to add an open quote before the paragraph’s content, and the p::after
will append an exclamation point after the paragraph’s content.
The final result will look like this:
"Some fancy quote!
::before and ::after example in Codepen.
In the context of single div drawing, the ::before
and ::after
pseudo-elements give us two additional elements to draw with. It’s like a 3 for 1 deal.
Let’s visualize this with 3 basic squares starting with the single div below:
<div>div</div>
The div
is styled as a basic red square. The div::before
is styled as a green square with an offset, and finally the div::after
is styled as a blue square with an offset from the div::before
so we can see how everything overlaps.
div {
background: red;
color: white;
box-sizing: border-box;
padding: 5px;
height: 100px;
width: 100px;
position: relative;
margin-top: 50px;
}
div::before {
content: 'div::before';
position: absolute;
background: green;
color: white;
box-sizing: border-box;
padding: 5px;
height: 100px;
width: 100px;
top: 25px;
left: 25px;
}
div::after {
content: 'div::after';
position: absolute;
background: blue;
color: white;
box-sizing: border-box;
padding: 5px;
height: 100px;
width: 100px;
top: 55px;
left: 55px;
}
body {
display: flex;
justify-content: center;
}
A couple of notes:
- You must set the content of the pseudo-elements or there is nothing to draw. If you don’t want to display text, and empty string will suffice.
- By default, the pseudo-elements are added as inline elements, so you’ll need to either change the display property or set the position of the element to absolute to change where the element is drawn.
With the CSS above we get the following result:
The div is the base layer. On top of that the ::before
pseudo-element is drawn, and on top of that element the ::after
pseudo-element is drawn. This is a really useful technique to employ for single div drawings, as you’ll soon see later in this tutorial.
div::before and div::after example in Codepen.
box-shadow
The next single div drawing technique is leveraging the box-shadow property. I’m sure many of us have used the box-shadow
property to add a simple drop shadow to an element so appears to float off the page as seen in the example below.
HTML:
<div></div>
CSS:
div {
background: red;
height: 100px;
width: 100px;
margin-top: 50px;
border-radius: 50%;
box-shadow: 5px 5px 10px dimgray;
}
body {
display: flex;
justify-content: center;
}
Result:
But, don’t let the typical use case for the box-shadow
limit the possibilities of your imagination. You can manipulate the box-shadow
of an element to create multiple variations of the original element.
Say you want three circles of differing colors, just add more box-shadows.
CSS:
div {
background: red;
height: 100px;
width: 100px;
margin-top: 50px;
border-radius: 50%;
box-shadow: 5px 5px 10px gray,
0px 110px gold,
5px 115px 10px gray,
0px 220px limegreen,
5px 225px 10px gray;
}
Result:
Multiple box-shadow example in Codepen.
You can pile up box-shadows to create some fun pixel art, too!
CSS:
div {
background: darkslategray;
height: 50px;
width: 50px;
margin-top: 50px;
margin-right: 50px;
box-shadow: 100px 0px darkslategray,
0px 150px darkslategray,
50px 150px darkslategray,
100px 150px darkslategray,
-50px 100px darkslategray,
150px 100px darkslategray;
}
Result:
Multiple box-shadows as pixel art example on Codepen.
Gradients
The final technique I will cover is using gradients with the background-image property. Like box-shadow
, you can layer multiple gradients.
The most commonly used gradients are the radial-gradient and the linear-gradient. Additional gradients include the conical-gradient, the repeating-radial-gradient, repeating-linear-gradient and repeating-conical-gradient.
Paired with the background-image
property, you can set the size and the position of your gradient using the background-size
and background-position
properties.
In the following example, I used three linear gradients to create three squares within a single div.
HTML:
<div></div>
CSS:
div {
height: 500px;
width: 500px;
margin-top: 50px;
background-image:
linear-gradient(white, red, darkred),
linear-gradient(orangered, orange, yellow, orangered),
linear-gradient(darkgreen, white, green);
background-size:
100px 100px,
100px 100px,
100px 100px;
background-position:
25% 0%,
50% 0%,
75% 0%;
background-repeat: no-repeat;
}
body {
display: flex;
justify-content: center;
}
A few notes:
- The first gradient in the list, is the topmost gradient. You can think of it as the gradient with the highest z-order index.
- The
background-size
andbackground-position
items correspond to the order of gradients in thebackground-image
property
With the CSS above we get the following result:
Multiple gradients example on Codepen.
Putting it all together
Now that I’ve covered the basics, let’s draw a lollipop.
It’s helpful to break down the object you plan on drawing into basic shapes. In the case of the lollipop, we have three:
- a circle for the candy
- a rectangle for the candy stick
- for a Dum Dum style lollipop, another rectangle for the band around the candy
Step 1: Create the basic shapes of the lollipop
With the three basic shapes in mind, the first thing we’ll do is draw them. Since we only have three shapes to draw, most of our work is cut out for us if we use the ::before
and ::after
pseudo-elements.
HTML:
<div></div>
CSS:
body {
background: limegreen;
display: flex;
justify-content: center;
}
div {
height: 100px;
width: 100px;
border-radius: 50%;
margin-top: 5%;
position: relative;
background: red;
}
div::before {
height: 250px;
width: 12px;
content: '';
position: absolute;
top: 100px;
left: 44px;
background: white;
}
div::after {
height: 16px;
width: 104px;
content: '';
position: absolute;
background: red;
top: 42px;
left: -2px;
background: red;
}
The div
draws the circle for candy. The ::before
pseudo-element draws the rectangle for the candy stick, and the ::after
pseudo-element draws the rectangle for the band around the candy.
Result:
While our result does look like a lollipop, it also looks pretty bland.
Step 2: Add some dimensions
We can make our lollipop look more realistic with the use of gradients.
Start with adding a radial gradient to the circle for the lollipop. By default, the origin of the radial gradient puts it in the middle of the circle. That looks a little off for our lollipop, so use the farthest-corner at
setting to adjust the position of the origin.
Updated CSS:
div {
height: 100px;
width: 100px;
border-radius: 50%;
margin-top: 5%;
position: relative;
background-image: radial-gradient(farthest-corner at 35px 25px, white, red, darkred);
}
Lollipop with the radial gradient:
Let’s not stop here. Add a linear gradient to the rectangle for the lollipop stick, and one for the rectangle representing the band around the lollipop.
CSS with more gradients:
div::before {
height: 250px;
width: 12px;
content: '';
position: absolute;
top: 100px;
left: 44px;
background-image: linear-gradient(90deg, lightgray, white 25%, darkgray);
}
div::after {
height: 16px;
width: 104px;
content: '';
position: absolute;
background: red;
top: 42px;
left: -2px;
background-image: linear-gradient(darkred, white 2%, transparent 15%, transparent 90%, darkred),
linear-gradient(90deg, red, white 15%, red 50%, darkred);
}
Result with additional gradients:
In this example, two linear gradients were used for the the rectangle on the lollipop. One that goes from top to bottom and another that goes from left the right. With the use of two, we’re able to capture a more realistic lighting effect for the lollipop.
Step 3: Add some final touches
The last thing we’ll add to our lollipop is a drop shadow so it pops a little off the lime background.
Final CSS:
body {
background: limegreen;
display: flex;
justify-content: center;
}
div {
height: 100px;
width: 100px;
border-radius: 50%;
margin-top: 5%;
position: relative;
box-shadow: 5px 5px 15px darkslategray;
background-image: radial-gradient(farthest-corner at 35px 25px, white, red, darkred);
}
div::before {
height: 250px;
width: 12px;
content: '';
position: absolute;
top: 100px;
left: 44px;
box-shadow: 5px 5px 15px darkslategray;
background-image: linear-gradient(90deg, lightgray, white 25%, darkgray);
}
div::after {
height: 16px;
width: 104px;
content: '';
position: absolute;
background: red;
top: 42px;
left: -2px;
background-image: linear-gradient(darkred, white 2%, transparent 15%, transparent 90%, darkred),
linear-gradient(90deg, red, white 15%, red 50%, darkred);
}
Final Result:
And there you have it, we’ve made our first single div drawing. Lollipop example on Codepen.
Additional Single Div Drawing Resources
- https://a.singlediv.com/
- https://hacks.mozilla.org/2014/09/single-div-drawings-with-css/
- https://www.educative.io/edpresso/3-secrets-behind-single-div-css-art
Let’s be friends!