Cleanest CSS spinner, ever

For some reason, I seem to have a fascination with CSS loaders these days. After recreating the Google loader with clean CSS recently, I set off to recreate the classic spinner with CSS. Yes, I know this has been done zillions of times, but I wanted a clean, maintainable, reusable solution, not just a proof of concept. Something with not tons of CSS and/or HTML elements.

I managed to recreate it with only 2 elements. I’m still not completely satisfied, as I was hoping to come up with a solution with just one element, but it’s still much better than all those solutions out there that use tons of elements and code.

So, how did I do it?

  • I use the ::before and ::after pseudoelements of the parent and child div to create the 4 first bars
  • I use box-shadow with no blur on all four of the above to create the remaining 4 bars
  • I rotate the whole element with a steps(8) timing function to create the animation

As with the Google-style loader, just changing the font-size on this scales the whole element, as everything is sized with ems. Also, there is fallback text, to make it accessible to screen readers. Tested in Chrome, Firefox, Safari, IE10. Should degrade gracefully on IE9 (spinner should look fine, just no animation).

Using a preprocessor for variables and calculations should simplify the code even further.

Enjoy :)

Ideas for further improvement are welcome. Remember that it’s not just the size of the code that matters, but also its simplicity.

  • http://dan.cx/ Daniel Lo Nigro

    This is fantastic! Nice work :D

  • http://MichaelMusgrove.com/ Michael Musgrove

    Neat!

  • Lukyvj

    Well done ! You nailed it !

  • gp

    “For some reason, I seem to have a fascination with CSS loaders these days”
    My broher, who is therapist, says that it is maybe because you want to have a baby….

    • http://lea.verou.me/ Lea Verou

      I can’t help but wonder if I would have gotten this comment if I were male.

      • Alexander Sadler

        Haha don’t turn this into a gender debate

        • http://friendlybit.com Emil Stenström

          If you read a couple of comments on any kind of article written by a woman you will see that “people on the internet” obviously have a hard time disregarding gender. @365a706d629863f81da1d9ae2e64f32b:disqus is the one at fault here, not Lea.

        • JoaoBeno

          Lol, i see this same way as if i posted and someone stated “My brother, who is therapist, says that it is maybe because you should go out and have sex”…

          These jokes will aways exist on the web, man or woman, everybody need to learn how to deal with it… With male devs, they shot about their weirdness/lonellyness/depressiveness/so on… , and with female devs they shot with female stuff (Had no better way of calling it)…

          I usually ignore and move on, but i decided to give my two cents about the debate before someone break godwin’s law…

          Ah, and Lea, i love your posts, i wish you had time to post more stuff! =]

        • http://friendlybit.com Emil Stenström

          @JoaoBeno:disqus I agree in your description of the how comments work today. I just think it’s sad that they always have to be about (or colored by) gender. Let’s talk and joke about code instead.

        • JoaoBeno

          Sure sure, I’m just saying that they aways do that, be a male or a female coder, there is aways an troll to push us down…

        • http://friendlybit.com Emil Stenström

          Let’s just vote down the trolls.

        • http://danillonunes.net/ Danillo Nunes

          Do you know who also tried to stop discussions with the “let’s not bring in godwin’s law” excuse? Hitler!

      • Dustin

        I’m not even sure it matters. The comment has no correlation and makes no sense at all.

      • http://dan.cx/ Daniel Lo Nigro

        I can’t help but wonder how the comment by gp could have possibly gotten any upvotes.

    • Maslow

      My cat, who’s therapist too, says that you wrote this comment because you have mother issues. Meow :3 (Really nice job Lea btw. Love it)

    • kerriganmarois

      I’m pretty sure gp is a piece of robot code and not a real person.

  • Pingback: Pure CSS & Simplistic Loader/Spinner » CSS 3 & HTML 5 Links und Infos

  • Pingback: Cleanest CSS Spinner, Ever

  • toh

    Very nice !
    Thx

  • Robert North

    Very awesome! Well done – integrated it immediately into our web app.

    Scratching my head on how I might go about making the lines thinner, or longer. Trying the math in the comments, but I don’t think I understand. What is ‘part width’ and ‘part height’?

    • http://lea.verou.me/ Lea Verou

      Part width is the thickness of the lines, which is what you want to change. You need to change 2 values to change that, from what I see. Part height is the height of the lines. Sorry for the weird terminology, but wasn’t sure what to call it!

      • Robert North

        Ahh thank you!

        That is what I thought – my problem is in using a calculator.

        Such a great contribution to a lighter and cleaner web. Thanks again.

        • Robert North

          In case anybody needs an example of making the lines thinner with Lea’s weird terminology (jokes).. here is with thinner lines:

          http://dabblet.com/gist/7703479

  • Sander

    In Opera 12, the fallback text is visible and rotates with the rest of the spinner :) looks really funny. Changing text-indent to -999em fixes this.
    In Opera 18, it does not rotate, which is strange because it’s based on Chromium 31 and Chrome 31 works just fine.
    Other than that: nice work! Saves a request to a GIF file (or more if you have different size spinners) and looks much better!

  • http://varemenos.com/ Adonis K. (Varemenos)

    You could easily make some with 1 or 2 elements. Here are few I’ve made:
    http://codepen.io/varemenos/pen/krKoE
    http://codepen.io/varemenos/pen/IAzbo
    http://codepen.io/varemenos/pen/oJLge

    • http://kenverhaegen.be/ Ken Verhaegen

      Using :before and :after pseudo-elements would kill the need to nest 2 to 3 elements. (Interesting loaders though)

      • http://varemenos.com/ Adonis K. (Varemenos)

        That really depends on the purpose.

        If you for example use a CSS framework (as I do https://github.com/varemenos/verepo) then it’d be convinient to be able to just plug a css class in 1 html element and get a css loader. Imagine how difficult it would be if you had to remember the HTML structure of the loader as well.

  • don’t eat

    Nice work! Here’s another “one-element/simple css” spinner:
    http://dabblet.com/gist/7708654

  • http://caryhartline.com/ Cary Hartline

    Spinners on the Internet have always been weird. People have this expectation that once their browser’s loading bar is done then everything on the page should be loaded, but when you see more things loading(usually inside some sort of block of content or iframe) then it can be jarring. This used to happen a lot with Flash, but I’m seeing a resurgance of loading bars and spinners with some single-page web apps.

    Leaving that aside, I think for most web devs two divs is small enough to be easily reusable. Especially when so many bulky frameworks require four or five divs just to make a header!

  • Nick Beranek

    This looks great, Lea. Also, I appreciate you providing alternative text for screen reader users.

  • http://danillonunes.net/ Danillo Nunes

    Nice work, Lea! Though this just made me wonder why we still don’t have a JavaScript API to control the native browser progress bar/spinner.

    • http://lea.verou.me/ Lea Verou

      Usually we don’t use JavaScript APIs to style things :P There is a lot of discussion in the CSS WG from time to time about styling such native elements. Hopefully, when the Shadow DOM combinators get standardized and more widely supported, it should help in this.

      • http://danillonunes.net/ Danillo Nunes

        Sorry, I‘m not talking about styling, I‘m talking about starting/stopping the spinner.

        • http://dandascalescu.com/ Dan Dascalescu

          Why would you stop a spinner? When the activity is completed, the spinner should be hidden. If there’s a pause in activity and you can detect that, then you might be better off with a progress bar.

        • http://danillonunes.net/ Danillo Nunes

          Yes, by ‘stopping’ I mean ‘hiding’, not ‘freezing’.

          To be clear, I’m talking about this little guy:

          https://www.evernote.com/shard/s5/sh/f491b9c5-19b9-44fa-8f1b-38394898711e/b5099fa4707ab4441997157e300d5ef9

          Generally it’s shown when a page is loading, but since it doesn’t appear with every Ajax request (which is very reasonable, I agree), there should be an API so we can show/hide it whenever we want.

  • http://danillonunes.net/ Danillo Nunes

    I think it’s possible to do it with only one element if using squares to build the bars. Here’s my attempt: http://dabblet.com/gist/7712672

    Missing:
    - Rounded corners;
    - Weird tiny white space between the squares in Chrome;
    - Better order of the shadows properties (for reading), or at least useful comments.

    • Chris Nager

      @LeaVerou:disqus This is fantastic! Thanks for sharing. Love your work.
      @danillonunes:disqus Great job as well! I built off of your idea by building the bars with box-shadow squares. I also addressed the three issues you said were missing.

      I had some fun with this. Check out my Zero Element CSS Spinner: http://codepen.io/ChrisNager/pen/Bvnlc

  • http://giacomoballi.com/ Giacomo Balli

    How’s this for simplicity?

    #spinner {
    width: 150px;height: 150px;
    -webkit-animation: sweep 1s infinite linear;
    border-radius:75px;
    border-bottom:5px solid blue;
    }
    @-webkit-keyframes sweep { to { -webkit-transform: rotate(360deg); } }

  • crazyrohila

    If anyone using scss, I have created a scss mixin with some configurable variables for the same. http://codepen.io/crazyrohila/pen/rnjxg

  • http://www.gahe.co/ Gahe

    I definitely bookmark this page and share it with your friends, hopefully will be useful to them.

  • Pingback: Tweet Parade (no.48 Nov 2013) - Best Articles of Last Week | gonzoblog

  • Pingback: CSS | Annotary

  • Pingback: Collective #92 » CSS 3 & HTML 5 Links und Infos

  • http://hugogiraudel.com/ Hugo Giraudel

    Depending on the browser support you are aiming for, you could remove the extra element by using linear-gradients only.

    • http://lea.verou.me/ Lea Verou

      Yes, but then you can’t have the rounding unless you use tons of gradients which is worse than an extra HTML element. Removing the extra HTML element isn’t a goal in itself, it’s only a good idea if the extra CSS code involved makes sense and isn’t too long.

      • http://hugogiraudel.com/ Hugo Giraudel

        Definitely agreeing with you on this point.

  • jfcarr

    Nice spinner. I just wish I could get our company off of IE9 as their main browser so that I could use neat CSS stuff like this. At least Windows XP has been 99% expunged from our network. Baby steps.

    • http://lea.verou.me/ Lea Verou

      Hey there!
      Glad you liked it. Btw, I’m not sure if you mean that you still support IE9 or that you work with some sort of intranet apps that are all IE9, but if it’s just a %, the spinner is supposed to degrade gracefully. It won’t spin, but it will still look like a spinner, which by now is a pretty universal convention for progress.

      • jfcarr

        IE9 is the official corporate IT approved browser and only a few select users are allowed to install IE10, Chrome or other browsers. Therefore, I have to have IE9 compatibility on all intranet sites. User acceptance testing required the spinning spinner so I had to go with a Javascript solution.

  • http://www.mathewporter.co.uk/ Mathew Porter

    Very light, using this in a production site that contains some global resets may allow the code to be lightened even more. Brilliant as always.

  • http://newsviews.satya-weblog.com/ Satya Prakash

    Really, i landed here from twitter. I will fav that to come back.

  • stephen p

    Feel so dumb, why won’t this spin in a boot strapped (2x) page?

    • http://lea.verou.me/ Lea Verou

      Vendor prefixes.

      • Ian Simmons

        -webkit-allthethings Works great in node-webkit app. Thanks! :-)

    • stephen p

      Turns out it’s the latest version of Canary

  • Philipp Kyeck

    Am I the only one that’s having problems seeing this?

    Chrome 31 on a Mac … Safari is working fine though.

  • Pingback: Collective #92 | Web Design Factory

  • Kidlvr

    Is there a jQuery plugin for this?

    • http://kenverhaegen.be/ Ken Verhaegen

      Why would you use a jQuery plugin for this.
      It’s easier to load the element into DOM when you need it.
      Its styling is done by CSS anyhow.

      • Kidlvr

        How do you load it into the DOM without jQuery? Should I use mootools instead?

        • http://kenverhaegen.be/ Ken Verhaegen

          This should set you on the path to a solution. Code, Test, Fix, and Test Again.
          http://stackoverflow.com/questions/68485/how-to-show-loading-spinner-in-jquery
          It’s in jQuery, there are just multiple options to load objects. One of them is prepend() fo example.
          Not sure what your exact plan is. Problems and their possible solutions differs on what you exactly want it to do.

  • Daniel Furze

    Ah this is great! Thanks, I’ll be using something like this all the time now :)

  • Pingback: Pure CSS & Simplistic Loader/Spinner by sugeng tigefa

  • Pingback: Diacode Weekly #11 | Blog de Diacode

  • Pingback: Collective #92 | Daniele Milana

  • Pingback: Latest Apps and Tools of the Week [14th December-20th December]

  • Pingback: Useful Tools and Websites for Designers and Developers – December 2013

  • Pingback: The Best Tools of 2013 for Designers and Developers

  • Pingback: 10 Fresh Handy CSS Tools for Developers | Code Geekz

  • Pingback: 转:前端开发必备 40款优秀CSS代码编写工具推荐 | 心无境则梦无限

  • http://shpargalkablog.ru/2010/09/optimizatsiya-blogger.html NMitra
  • Pingback: Theme Performance | ThemeShaper

  • Pingback: 40款优秀CSS代码编写工具推荐 | 我是程序员

  • Pingback: 前端开发必备 40款优秀CSS代码编写工具推荐 | 博客编程

  • Dietrich T Miller

    this is good, but you need to make this compatible for different browsers, it currently does not work in chrome/I.E. have a look: http://jsfiddle.net/kTr44/9/

    • http://lea.verou.me/ Lea Verou

      Seems to work in Chrome, just like I say in my blog post. I’m pretty sure it works in IE10, I tested it before I published this.

  • Pingback: 前端开发必备 40款优秀CSS代码编写工具推荐 - 7科技

  • vsync

    checkout my clean spinners I wrote back in 2011 when CSS spinners where unheard of:
    http://dropthebit.com/demos/spinners/spinner.html

  • Blake Stephens

    I just discovered your site and have been really pleased and excited with a lot of your creative implementations! Great work! I was curious why the Spinner didn’t seem to be respecting the steps() timing function (in my browser, Mac Chrome v35) so I tinkered with it, and apparently for steps() to work as expected (and not just as smooth linear), you must also have a from{} in the animation definition:
    from { transform: rotate(0turn); }
    Adding that, made the stepping animation work as expected. Keep up the great work! I also really liked the angled tabs idea. Very ingenuitive. You’ve earned a new follower. :)