Let's make and eat those CSS3 progress bars. 🍭
Tags: css, html, beginners, tutorial
Published: 2020-06-19 14:55:10

Are you the one who still eats candies? Striped ones? 🍭 Well, I used to love them when I was a kid. So what I love now? I love CSS. 🤩

Let's do it. We'll transform a 'sweet' striped candy bar to a progress bar. Because...well, to be honest, the default HTML [`<progress>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress) is bad. I mean look at this...

![Progress bar](https://dev-to-uploads.s3.amazonaws.com/i/mo6fvf0nt2knq5cwe2je.jpg)

We can sincerely convert this into a much 'sweeter' one and that too without the need of `<progress>`. Sounds exciting? Let's dive in!

![Candy GIF](https://media.giphy.com/media/Jsi0pCShyVEo2xOjtJ/giphy.gif)
<figcaption>Time to give back candies its lost glory 🥺</figcaption>

## Finish off the HTML first 🤪
Because...well, you need something to style on? What we want to achieve is the following loading/spinning candy bar:

![loadingcandyfinished GIF](https://dev-to-uploads.s3.amazonaws.com/i/0imds6f9tl7ftld1k2ih.gif)

If you wear your frontend goggles and observe, you see there are two layers or elements we need to do this. First off is the bar holder element and the one above it is the actual candy bar with red colour. So, this is what we start with:

```html
<div>
  <span></span>
</div>
```
The `div` is our holder upon which we will have a [`span`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span) to make it an inline container. Here, see how it looks in the Chrome Dev Tools:

![Layers](https://dev-to-uploads.s3.amazonaws.com/i/1ttx16wcxfd8441pqaqt.jpg)
<figcaption>The skin colored element is our div on which the blue colored span is sitting.</figcaption>

## Let's make it look like a candy 🍭
Here comes the interesting stuff. First, give the `div` a class of `loading-bar` and in CSS this is what we need to style it:

```css
.loading-bar {
  position: relative;
  margin: 0 auto;
  height: 50px;
  width: 30%;
  border-radius: 50px;
}
```
Now the `relative` positioning is optional here as we are not setting values for the `top`, `left`, `bottom` or `right` properties to position it explicitly. We just center this to the document `body` by putting a `margin` of top and bottom to be `0` and left/right to be `auto`.  Setting a default `width` and `height` is necessary because without these we won't be able to see the div. These could be any value depending upon how big you want the bar to be. A nice, round `border` is also a good take to give it a shape of a loading bar.

You won't be able to see anything right now because technically the color of that div and the body element is both white by default. Try to add `background-color: orangered;` to the div and you'll now get your base holder.

Up next, we need to add those funky candy stripes, for that style the `span` as follows:

```css
span {
  display: block;
  position: relative;
  height: 100%;
  width: 100%;
  border-radius: 50px;
  background-image: linear-gradient(to bottom, #fac4c0, #f60000 60%);
  box-shadow: 
    inset 0 2px 9px  rgba(255,255,255,0.3),
    inset 0 -2px 6px rgba(0,0,0,0.4);
  overflow: hidden;
}
``` 
The block display ensures that it has a block-style element box with an equal amount of space before and after the span. This time we need it to be 100% area of the parent (i.e. div) so we give it the respective value of the width, height and border-radius. Any extra element (if it occurs) is clipped off the span by setting the value of [`overflow`](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow) to `hidden`.

Still, you won't be able to see anything :( We need to add some coloring! We do this by using a [`linear-gradient`](https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient) which is at a 180° angle. The bright red `#f60000` color occupies 60% of the total gradient value. And just when you do this you see our loader has a gradient! 

#### Completely optional... 
Time to add some depth so that it looks more like a candy. We add two shadow values. The first one adds a white shadow drop to the top and the second is black, at the bottom. The main point is that you need to use the `inset` so it looks like shadow is coming from one side. These type of shadows are drawn _inside_ its container.

#### Add stripes! 🌈
We're coming close! A candy with no stripe is a bad-looking candy for me. To do this, we need to understand the [`::after`](https://developer.mozilla.org/en-US/docs/Web/CSS/::after) pseudo element in CSS. According to the [Mozilla Developer Network (MDN)](https://developer.mozilla.org/en-US/) docs:

> In CSS, **::after** creates a pseudo-element that is the last child of the selected element. It is often used to add cosmetic content to an element with the content property. It is inline by default.
 
How it will help us? Well, we create our stripe pseudo-element with ::after! 

```css
span:after {
  content: "";
  position: absolute;
  top: 0px; left: 0; bottom: 0; right: 0;
  background-image: linear-gradient(
    -45deg, 
    rgba(255, 255, 255, .2) 25%, 
    transparent 25%, 
    transparent 50%, 
    rgba(255, 255, 255, .2) 50%, 
    rgba(255, 255, 255, .2) 75%, 
    transparent 75%, 
    transparent
  );
  z-index: 1;
  background-size: 50px 50px;
  border-top-right-radius: 8px;
  border-bottom-right-radius: 8px;
  border-top-left-radius: 20px;
  border-bottom-left-radius: 20px;
  overflow: hidden;
}
```
Every pseudo-element has to have a [`content`](https://developer.mozilla.org/en-US/docs/Web/CSS/content) property. Whatever is the value of content, it will replace that element with the newly generated value. If you add `content: "🍬";`, whatever your div was showing previously will now be replaced by "🍬". Sweet? But we don't want _any_ content inside the newly created ::after element. It will show up inside the span and is totally useless...until we add nothing! That's why we just use `' '`  (blank).

Stripe magic starts! We use `background-image` property to add a big gradient. Let's decode it one at a time:

- `-45deg`: This is the angle at which our gradient will be tilted.
- `rgba(255, 255, 255, .2) 25%`: A white (The value 255 means white in the rgb format) color with .2 as its opacity. 25% is the area it takes in the entire element.
- `transparent 25%`: A transparent value of color with the same 25% area of the total.  

There are three main values we focus on. Nothing much will change if you use just these. Now, look at the stripe pattern closely...

![Progress Candy Still](https://dev-to-uploads.s3.amazonaws.com/i/zt29nw9x1301q5oa70br.jpg)

...we can see that if there are multiple color-stops with the same position, they produce a transition from the first to the last. So what comes out is, the color suddenly changes at that position rather than smoothly transitioning. All this is possible because of the CSS3's [`background-image`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-image) property which supports color stops as specified in [W3C's draft](https://drafts.csswg.org/css-images-3/#color-stop).

This is how after repeating it several times all over the span (don't forget to use absolute positioning this time), we get a striped pattern perfect for our candy!

The default [`background-size`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-size) of half of the entire element are i.e. 50% on both width and height seems reasonable. Also, we need to make these stripes inside the container so we use the overflow and the specific `border` properties as our parent div on all four directions.

## Make it animate! 🎬
The real loading starts now. Let's select the newly created ::after element, create an `animate` class and we then select the span under it. Define the animation with `1s` duration, running infinitely.

```css
.loading-bar > span:after, .animate > span > span { 
  animation: load 1s infinite;
}
```
Now it's pretty straightforward. What we want to animate is the position of the stripes. The initial div stays locked in its position, stripes move on top indicating as if something is loading in the background.

```css
@keyframes load {
  0% {
    background-position: 0 0;
  }
  100% {
    background-position: 50px 50px;
  }
}
```
We start from zero to the 50px of width and height respectively. And there it is! How sweet that looks. 🤤 

Here's the CodePen to achieve this candy loader:

{% codepen https://codepen.io/kvaibhav01/pen/oNbYZNg default-tab=css,result %}

So, who's ready to eat that candy? 👀

![Candy eating](https://media.giphy.com/media/3o72F4AiJt2opESl44/giphy.gif)

---

## Where to next? 🤔
Fiddle around! We just made a loader this time, how about making an actual candy 'progress' bar? This time, the stripes move over the holder and move from left to right as if it's loading. This is what I'm talking about:

![Candy loader GIF](https://dev-to-uploads.s3.amazonaws.com/i/h2l5zg42dokqmlpxou97.gif)

If you're stuck making this, no worries, see the [CodePen example](https://codepen.io/kvaibhav01/pen/vYLyqJw) I made.

_Thanks for reading, I appreciate it! Have a good day. (✿◕‿◕✿)_

---

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="en" dir="ltr">Have you tried using Microsoft Docs yet? <br><br>We&#39;re not saying it&#39;ll change the way you program but at the same time we&#39;re not saying it won&#39;t. 😉 <br><br>Check it out: <a href="https://t.co/4o3bkwcdoq">https://t.co/4o3bkwcdoq</a><br><br>Image source: <a href="https://t.co/h1wgHdR7Uc">https://t.co/h1wgHdR7Uc</a><a href="https://twitter.com/hashtag/DevHumour?src=hash&amp;ref_src=twsrc%5Etfw">#DevHumour</a> <a href="https://twitter.com/hashtag/Programming?src=hash&amp;ref_src=twsrc%5Etfw">#Programming</a> <a href="https://t.co/TPl6vZCc5Z">pic.twitter.com/TPl6vZCc5Z</a></p>&mdash; Microsoft Developer UK (@msdevUK) <a href="https://twitter.com/msdevUK/status/1273156429688590337?ref_src=twsrc%5Etfw">June 17, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

---

#### [📫 Subscribe to my weekly developer newsletter 📫](https://mailchi.mp/f59beeac6b9b/devupdates)

##### PS: From this year, I've decided to write here on DEV Community. Previously, I wrote on Medium. If anyone wants to take a look at my articles, [here](https://medium.com/@vaibhavkhulbe)'s my Medium profile.