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>
is bad. I mean look at this...
We can sincerely convert this into a much 'sweeter' one and that too without the need of <progress>
. Sounds exciting? Let's dive in!
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:
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:
<div>
<span></span>
</div>
The div
is our holder upon which we will have a span
to make it an inline container. Here, see how it looks in the Chrome Dev Tools:
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:
.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:
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
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
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
pseudo element in CSS. According to the Mozilla Developer Network (MDN) 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!
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
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...
...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
property which supports color stops as specified in W3C's draft.
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
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.
.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.
@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:
So, who's ready to eat that candy? π
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:
If you're stuck making this, no worries, see the CodePen example I made.
Thanks for reading, I appreciate it! Have a good day. (βΏββΏββΏ)
Have you tried using Microsoft Docs yet?
β Microsoft Developer UK (@msdevUK) June 17, 2020
We're not saying it'll change the way you program but at the same time we're not saying it won't. π
Check it out: https://t.co/4o3bkwcdoq
Image source: https://t.co/h1wgHdR7Uc#DevHumour #Programming pic.twitter.com/TPl6vZCc5Z
Top comments (5)
Nice article .. can you write about circular progress bars. ?
Thanks! Circular candy progress bars --- up next. π
Here it is!
Let's make and wear those CSS3 progress rings. π
Vaibhav Khulbe γ» Jun 25 γ» 6 min read
Nice π€Έ
Thanks!