Making a popsicle with CSS only!
Tags: css, cssart, codepen, wecoded
Published: 2021-05-22 22:30:59

## Getting creative with CSS illustrations
Even though CSS illustrations might not be ideal for production (let's face it, a simple SVG is a lot less painful), they are a great way to improve your CSS skills and let your creative spirit fly! 

## The project
In this project we'll make a refreshing popsicle with a small animation on hover.

{% codepen https://codepen.io/evakarls/pen/BaWWJPr %}

### Setting up the HTML
We start with setting up the HTML. In this case, the structure is simple:
```
<div class="container">
  <div class="popsicle-container">
    <div class="popsicle-top"></div>
    <div class="popsicle-base"></div>
    <div class="stick"></div>
  </div>
</div>
```
We have one general container which we'll use to center the popsicle. The popsicle itself is composed of the `.popsicle-container` which contains three div elements: 
1. `.popsicle-top`
2. `.popsicle-base` 
3. `.stick`
 
These are the only HTML elements we'll need for this project.


### Moving on to the CSS
The container is a flex box which takes the whole width of the viewport and both centers and aligns our popsicle in the middle of the screen: 
```
.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}
```

The `.popsicle-container` is very similar, except there we'll set the flex-direction to column so our elements will stack below one another. We'll also set the height and width of the popsicle. 
```
.popsicle-container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 30rem;
  width: 12rem;
}
```

Now our wrappers are ready and we can move on to the fun stuff! 


### How do we capture the depth? 
We want our popsicle to have proper dimensions. In order to achieve this, we'll be using two pseudo-elements: `::before` and `::after`.
> **What are pseudo-elements?**
> Pseudo-elements are hidden elements (think of them like ghosts that hang around your element). Like the names suggest, `::before` appears before the element and `::after` goes after it. Pseudo-elements are very useful for decorative purposes (like in our popsicle). However they are not always picked up by screenreaders so avoid putting any crucial information in them.

Let's start with the `.popsicle-base`. 

We will put most of the properties in the `::before` and `::after` elements so the `.popsicle-base` itself will contain the width and the height. We will also need to be able to link the position of the `::before` and `::after` elements to the `.popsicle-base`, so we'll give it a `position: relative;`. 
```
.popsicle-base {
  position: relative;
  height: 20%;
  width: 100%;
}
```
The `.popsicle-base::before` element will be the shaded part of the popsicle.

```
.popsicle-base::before {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: #ffbdce;
  border-bottom-right-radius: 10%;
  border-bottom-left-radius: 10%;
  transform: skewY(-5deg);
}
```
All before and after elements need the `content` property. Without it they won't be displayed. So, all we need to do is to set it to an empty string. We'll set the radius on the bottom borders to make it a bit rounded and add a nice pink background colour. We set `postion: absolute;` so it'll be relative to the `.popsicle-base` (we will fix the exact positioning once we have the after element). We'll also slightly skew the Y axis to create the angle needed on the shadow.

This is what we have so far: 
![slightly skewed pink rectangle](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f3g5czzbptx2pyk3a596.png)

Now for the `.popsicle-base::after`

We'll give it a bit of depth by putting an ellipse shaped gradient at the top of the element. Besides the background colour and the gradient, the `::after` element has all the same properties as the `::before`. So we can simplify the code above to this:
```
.popsicle-base::before, .popsicle-base::after {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  border-bottom-right-radius: 10%;
  border-bottom-left-radius: 10%;
  transform: skewY(-5deg);
}

.popsicle-base::before {
  background-color: #ffbdce;
}

.popsicle::after {
  background: radial-gradient(ellipse at top, rgba(241, 240, 
  240, 0.74), #ffcbd8 60%);
  background-color: #f3f3f3;
}
```
And here's what we have now. 
![A skewed pink rectangle with white radial shading at the top](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xmmhgp7qahv7nx3f4i26.png)
You might think, *wait, where's the first rectangle?*

It's there! It's just hidden behind the `::after` element. In order to make it visible we'll need to shift the `::before` element a bit to the right. We'll also push it a tiny bit upwards.
```
.popsicle-base::before {
  background-color: #ffbdce;
  right: -1.5rem;
  top: -0.1rem;
}
```
The result is a nicely shaded and slightly skewed rectangle:
![A pink rectangle with slightly darker right side](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6gfeejbrykx6yp234yo1.png)

### Doing the same for the .popsicle-top and .stick
The `.popsicle-top` follows the same logic except we put the gradient at the bottom of the element so that it blends with the other gradient:

```
.popsicle-top {
  position: relative;
  height: 60%;
  width: 100%;
  border-top-left-radius: 35%;
  border-top-right-radius: 35%;
}

.popsicle-top::before, .popsicle-top::after {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  border-top-left-radius: 35%;
  border-top-right-radius: 35%;
  transform: skewY(-5deg)
}

.popsicle-top::before {
  right: -1.5rem;
  background: #86c8e4;
}

.popsicle-top::after {
  background: radial-gradient(ellipse at bottom,  rgba(241, 
  240, 240, 0.74), rgba(152, 208, 241, 0.877) 80%);
  background-color: #97DFFC;
}
```
What we have so far:
![A blue and pink popsicle which is missing the stick](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4686rau2jf19yab7vd2v.png)

The stick is also the same but there we also add a bit of shading on the top of the stick to make it's placement with the popsicle more realistic:
```
stick::before, .stick::after {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  border-bottom-left-radius: 10%;
  border-bottom-right-radius: 10%;
  box-shadow:
  inset 0 0 1rem rgb(236, 187, 113),
  inset 0 0.5rem 0.7rem -0.3rem rgba(0,0,0,0.4);
  transform: skewY(-5deg)
}

.stick::after {
  background-color: #F3D4A5;
}

.stick::before {
  right: -0.5rem;
  background-color: rgb(219, 183, 128);
}
```

With that we have our lovely popsicle: 
![A blue and pink popsicle](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/attq9qq8gtpz99gg632f.png)

### Adding animation
We'll add a small pulsating animation where we slightly decrease the size and then increase it again.
```
@keyframes pulse {
  0% {
    transform: scale(1);
  }
  60% {
    transform: scale(0.95);
  }
  100% {
    transform: scale(1);
  }
}
```
We'll then apply it on the `.popsicle-container` on hover with a 2 second duration and on an infinite loop (as long as the element is in the hover state):
```
.popsicle-container:hover {
  animation: pulse 2s ease-in infinite;
}
```

## That's it!
I hope you've enjoyed making this colourful popsicle :)