Your browser doesn't support some of the latest features used to build this site. For the best experience you might want to look at upgrading your browser.

Skip to main content

40 adaptable progress loaders using inline SVG and CSS

Learn the fundamentals of working with inline SVG strokes to create some custom progress loaders and take these techniques and apply them to other areas of the web.

Setting up the markup

Whilst there are 4 different types of loader in this demo, I’ll only be going through the circle loader as the techniques used are the same for all of them.

So let’s begin by setting up the markup needed for our circle loader.

Circle loader markup

<svg class="a-loader" viewBox="0 0 96 96" xmlns="">
    <circle cx="48" cy="48" r="42"></circle>

As you can see the markup is pretty straightforward:

  • We have our svg element with a viewBox size of 96 by 96
  • Our title element describing the svg
  • A circle element that has been drawn in the svg

If you’ve not used inline SVG much, feel free to play around with these values.

  • Reducing the viewBox values will hide anything that has been drawn on those coordinates
  • Adjusting the cx value will change the circles horizontal positioning
  • Changing the cy value will update the circles vertical positioning
  • Updating the r value will change the size of the circle

That’s all for the markup, nice and straightforward .

Adding some style

Let’s begin by setting up some base styling that’ll be used on every loader.

.a-loader {
    animation: a-loader 3s linear infinite;
    color: #31cc89;
    fill: none;
    height: 6rem;
    stroke: currentColor;
    stroke-linecap: square;
    stroke-linejoin: miter;
    stroke-width: 10;
    vertical-align: top;
    width: 6rem;

@keyframes a-loader {
    100% {
        stroke-dashoffset: 0;

Nothing too complex going on here, just some basic styling and the animation that’ll run.

If all the stroke properties are new to you, feel free to go read the styling icons section on my previous post; it covers it all.

We’re also going to be using the stroke-dasharray and stroke-dashoffset properties quite a lot.

If you’ve never seen these properties before, here are some great articles on CSS Tricks:

If you want to find out how long a path is you can run the following in your browser console (replacing the selector with yours):


Now that the base styling is set up let’s have a look at our first loader – the fill loader.

Fill loader

See the Pen Fill loader (SVG and CSS animation) by Rob Simpson (@robsimpson) on CodePen.

Building on the base styling we setup earlier, all we need to do is add this CSS to create our fill loader animation:

.a-loader--circle-1 {
    stroke-dasharray: 263.467529296875;
    stroke-dashoffset: 263.467529296875;
    stroke-linecap: butt;

As mentioned above the values set on stroke-dasharray and stroke-dashoffset can be generated by running:


This is the total length of the line and then we’re offsetting it by the same amount to hide the line. Next, our CSS animation is animating back to an offset of 0 to reveal the full line.

Pretty straightforward right .

Half fill loader

See the Pen Half fill loader (SVG and CSS animation) by Rob Simpson (@robsimpson) on CodePen.

To create the half fill loader we need to apply the following css:

.a-loader--circle-2 {
    stroke-dasharray: 65.8668823242;
    stroke-dashoffset: 263.467529296875;

By dividing the full line length by 4 we get 65.8668823242; which we can use for the stroke-dasharray property.

This creates gaps in the circles stroke. It works by drawing a stroke that’s a 14 of the line length, followed by a 14 gap, followed by another 14 stroke and finished with another 14 gap.

Single dot loader

See the Pen Single dot loader (SVG and CSS animation) by Rob Simpson (@robsimpson) on CodePen.

As the name suggests (stroke-dasharray), we can pass in multiple values (seperated by a comma or a space). So let’s give it a try:

.a-loader--circle-3 {
    stroke-dasharray: 1 263.467529296875;
    stroke-dashoffset: 263.467529296875;

The value set on the stroke-dasharray draws a single stroke, followed by a gap the length of the entire line (263.467529296875).

The single stroke actually looks much thicker because we have stroke-linecap: square; applied, if you remove this, the stroke width is much smaller.

Double dot loader

See the Pen Double dot loader (SVG and CSS animation) by Rob Simpson (@robsimpson) on CodePen.

Expanding on the previous loader let’s create the double dot loader (yes, I know the names are great).

.a-loader--circle-4 {
    stroke-dasharray: 1 130.733764648;
    stroke-dashoffset: 263.467529296875;

If you haven’t guessed what’s going on here. We’re drawing a single stroke, followed by a gap 12 the size of the total line length, followed by another single stroke and finished with another 12 gap.

Hopefully, you’re starting to get the hang of this now .

Happy loader

See the Pen Happy loader (SVG and CSS animation) by Rob Simpson (@robsimpson) on CodePen.

This is my favourite loader…

.a-loader--circle-5 {
    stroke-dasharray: 21.95563 0 21.95563;
    stroke-dashoffset: 263.467529296875;

This one is a little bit more complicated than the other examples, so I’ll break it down.

Something very important about the stroke-dasharray property is if the value is set to an odd number, then the list of values is repeated to create an even number.

So in our example where we have; stroke-dasharray: 22 0 22;(I rounded up to 22 to keep the content tidy) this is actually interpreted as stroke-dasharray: 22 0 22 22 0 22;and not stroke-dasharray: 22 0 22 0 22 0;.

Ok, so now that we have that important detail clarified, let’s talk about what this is doing.

So it starts by drawing a stroke that is 22 long, followed by a gap of 0, followed by another stroke that is 22 long – this creates what looks like a stroke that is 44 long as the gap has no width.

Next, it draws a gap that is 22 long followed by a stroke of 0, followed by another gap that is 22 long.

So, in theory, we should a have a gap that is 44 long, right? Then why is there a single dot in the middle you’re probably thinking?

Well, it would be a gap of 44 but we’ve set the stroke-linecap property to square. This essentially extends the start and end of the stroke. So even if the stroke has a width of 0 it still adds a small stroke to the start and end of the stroke (stroke-linecap: round does the same thing).


There you have it, hopefully, you learnt a little bit more about inline SVG and strokes (I know I did).

These loaders can be adapted in so many different ways, try changing the colour, stroke width etc. in your animation.

Although we’ve used this technique for creating a bunch of different loaders, I hope you can see the potential use case for it in different areas of UI development.

If you’ve enjoyed this post I’d really appreciate it if you shared it around online .

Equally, if you have any questions or spotted any issues don’t hesitate to drop me a message on social media .

Thank you, your answers have been sent
These will help me create more relevant content that you’re looking for.
Which topics would you like to see more of?
Thank you, your answers have been sent
These will help me create more relevant content that you’re looking for.
Always stay up to date
What would you like to recieve?
Please confirm that you’d like to hear from me

I’ll only use the information you provide on this form to get touch about the topics you’ve chosen above. For more information on how I use and protect your data, please view my privacy policy.

Related tutorials