Spin.. spin..
This is a little something I made in my spare time, just for a bit of fun. It was excruciatingly time consuming as I felt the easiest way to do it was to make individual bars and rotate them into the right position. The pain of changing left
by 2% was almost excruciating. I used percentages in particular as I felt I wanted it to be resizeable in an easy way (It would have to be, changing the size manually is perhaps the most soul destroying endeavour you might ever lead yourself onto do). Anyway, onward with the understanding.
It’ll work in..
Webkit | Mozilla | Trident | Presto |
Yes | Yes | Yes | No Animaton |
How it was made
Basically, I got a bunch of divs, put them in another div, set each div inside the main div a particular size as a percentage of the main div, and animated them to change opacity. Pretty easy huh? Well it would have been if changing the position of something was easier, and if when we just did a property like ‘animation’ the browser would change to its specific iteration instead of having to use three properties consisting of -moz
, -webkit
and -ms
.
Perhaps one of the most devastating moments of my life was when I realised this wasn’t going to work in Opera. So I tried my damnest, but because of no animation support, it’ll just look like some fancy wheel rather than a loading sign. Anyway, here’s what the HTML is going to look like:
<div class="spinner"> <div class="piece a"> </div> <div class="piece b"> </div> <div class="piece c"> </div> <div class="piece d"> </div> <div class="piece e"> </div> <div class="piece f"> </div> <div class="piece g"> </div> <div class="piece h"> </div> <div class="piece i"> </div> <div class="piece j"> </div> <div class="piece k"> </div> <div class="piece l"> </div> <div class="piece m"> </div> <div class="piece n"> </div> <div class="piece o"> </div> <div class="piece p"> </div> </div>
The CSS looks like this:
<style type="text/css"> .spinner { width: 32px; height: 32px; } .piece { background: #000; width: 50%; height: 14%; position: relative; } .spinner div { opacity: 0.2; } @-webkit-keyframes fade { 5% { opacity: 0.8; } 30% { opacity: 0.5; } } @-ms-keyframes fade { 5% { opacity: 0.8; } 30% { opacity: 0.5; } } @-moz-keyframes fade { 5% { opacity: 0.8; } 30% { opacity: 0.5; } } .a, .p { height: 50%; width: 14%; left: 99%; } .a { top: 5%; -webkit-animation: fade 3.2s ease-in infinite; -moz-animation: fade 3.2s ease-in infinite; -ms-animation: fade 3.2s ease-in infinite; } .b { bottom: 21%; left: 50%; -webkit-animation: fade 3.2s ease-in-out 3s infinite; -moz-animation: fade 3.2s ease-in-out 3s infinite; -ms-animation: fade 3.2s ease-in-out 3s infinite; } .c { bottom: 34%; left: 110%; -webkit-animation: fade 3.2s ease-in-out 0.2s infinite; -moz-animation: fade 3.2s ease-in-out 0.2s infinite; -ms-animation: fade 3.2s ease-in-out 0.2s infinite; } .d { bottom: 31%; left: 27%; -webkit-animation: fade 3.2s ease-in-out 2.8s infinite; -moz-animation: fade 3.2s ease-in-out 2.8s infinite; -ms-animation: fade 3.2s ease-in-out 2.8s infinite; } .e { bottom: 43%; left: 134%; -webkit-animation: fade 3.2s ease-in-out 0.4s infinite; -moz-animation: fade 3.2s ease-in-out 0.4s infinite; -ms-animation: fade 3.2s ease-in-out 0.4s infinite; } .f { bottom: 32%; left: 11%; -webkit-animation: fade 3.2s ease-in-out 2.6s infinite; -moz-animation: fade 3.2s ease-in-out 2.6s infinite; -ms-animation: fade 3.2s ease-in-out 2.6s infinite; } .g { bottom: 45%; left: 149%; -webkit-animation: fade 3.2s ease-in-out 0.6s infinite; -moz-animation: fade 3.2s ease-in-out 0.6s infinite; -ms-animation: fade 3.2s ease-in-out 0.6s infinite; } .h { bottom: 30%; left: 6%; -webkit-animation: fade 3.2s ease-in-out 2.4s infinite; -moz-animation: fade 3.2s ease-in-out 2.4s infinite; -ms-animation: fade 3.2s ease-in-out 2.4s infinite; } .i { bottom: 43%; left: 155%; -webkit-animation: fade 3.2s ease-in-out 0.8s infinite; -moz-animation: fade 3.2s ease-in-out 0.8s infinite; -ms-animation: fade 3.2s ease-in-out 0.8s infinite; } .j { bottom: 29%; left: 12%; -webkit-animation: fade 3.2s ease-in-out 2.2s infinite; -moz-animation: fade 3.2s ease-in-out 2.2s infinite; -ms-animation: fade 3.2s ease-in-out 2.2s infinite; } .k { left: 149%; bottom: 41%; -webkit-animation: fade 3.2s ease-in-out 1s infinite; -moz-animation: fade 3.2s ease-in-out 1s infinite; -ms-animation: fade 3.2s ease-in-out 1s infinite; } .l { bottom: 30%; left: 28%; -webkit-animation: fade 3.2s ease-in-out 2s infinite; -moz-animation: fade 3.2s ease-in-out 2s infinite; -ms-animation: fade 3.2s ease-in-out 2s infinite; } .m { bottom: 43%; left: 134%; -webkit-animation: fade 3.2s ease-in-out 1.2s infinite; -moz-animation: fade 3.2s ease-in-out 1.2s infinite; -ms-animation: fade 3.2s ease-in-out 1.2s infinite; } .n { bottom: 40%; left: 50%; -webkit-animation: fade 3.2s ease-in-out 1.8s infinite; -moz-animation: fade 3.2s ease-in-out 1.8s infinite; -ms-animation: fade 3.2s ease-in-out 1.8s infinite; } .o { left: 110%; bottom: 52%; -webkit-animation: fade 3.2s ease-in-out 1.4s infinite; -moz-animation: fade 3.2s ease-in-out 1.4s infinite; -ms-animation: fade 3.2s ease-in-out 1.4s infinite; } .p { bottom: 78%; -webkit-animation: fade 3.2s ease-in-out 1.6s infinite; -moz-animation: fade 3.2s ease-in-out 1.6s infinite; -ms-animation: fade 3.2s ease-in-out 1.6s infinite; } .b, .o { -webkit-transform: rotate(67.5deg); -moz-transform: rotate(67.5deg); -ms-transform: rotate(67.5deg); -o-transform: rotate(67.5deg); } .d, .m { -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -ms-transform: rotate(45deg); -o-transform: rotate(45deg); } .f, .k { -webkit-transform: rotate(22.5deg); -moz-transform: rotate(22.5deg); -ms-transform: rotate(22.5deg); -o-transform: rotate(22.5deg); } .n, .c { -webkit-transform: rotate(-67.5deg); -moz-transform: rotate(-67.5deg); -ms-transform: rotate(-67.5deg); -o-transform: rotate(-67.5deg);} .l, .e { -webkit-transform: rotate(-45deg); -moz-transform: rotate(-45deg); -ms-transform: rotate(-45deg); -o-transform: rotate(-45deg); } .j, .g { -webkit-transform: rotate(-22.5deg); -moz-transform: rotate(-22.5deg); -ms-transform: rotate(-22.5deg); -o-transform: rotate(-22.5deg); } </style>
Now I could spend forever explaining this, but basically I just moved a bunch of divs around, and used some transforms to make them look like a wheel. Then I used a simple animation to make them fade in at the right time, and applied the animation with a certain timing so it all worked out. You can learn more about animations here, in our lovely tutorial. If you’re stuck that is.
Since I’ve used percentages (a tactical move, if I do say so), you can change the width and height of the spinner class and that’ll change the width and height of the spinner. Remember though, that won’t mean the spinner will be that height and width. It’ll be slightly larger. As a side note, compressed, the CSS file amounts to about 4kb, which is smaller than a lot of gifs out there. I realise perhaps its not a good alternative at the moment because it lacks 100% support, but we can hope one day it will be, right?
Check out the demo below to see what it looks like. I’ve also provided a condensed version in the download link, seeing as the CSS is a little elaborate.
Comments
If I were making this, I’d have used SASS then a loop to generate the properties – once you’ve made something like this once, it’s definitely something to think about! It then reduces the tedium to the absolute minimum.
You can also use the animation-delay property (https://developer.mozilla.org/en/CSS/animation-delay), which would reduce:
-webkit-animation: fade 3.2s ease-in-out 1.2s infinite;
to
-webkit-animation-delay: 1.2s;
for instance.
You could also use transform-origin to make it easier to position each of the bits, rather than absolute positioning.
Also, I’d make sure you add the -o- and unprefixed properties – one day Opera will implement this, and one day it won’t need a prefix. At that point, this will break. :(
Haha, yeah, but after doing it for the browsers that support it, I felt as though adding more prefixes for an unsupported browser would be an overkill!
In hindsight transform-origin would perhaps have been a better idea. Then again, in hindsight a lot of things seem clearer ;)
Cool demo, but I really hate it when I have to click through another link to see it, why are these tuts/demos always like this?
It’s WordPress. I hate it, so ended up writing my own CMS to get round it’s annoyingness!
I actually have an add-to-head meta element so I can do some custom CSS for posts when needed. I just felt this was more suited to a single demo page!
Hey Travis. Thanks for the comment! I think the main reason is because CSS from the main stylesheet can sometimes override properties in a way which is unsuitable. I understand your pain though, and sometimes I find myself thinking “why can’t this be on the same page!?”, but because of layout issues the amount of CSS required I thought it would’ve been better to include this demo on a separate page. I hope this is an adequate response!
Pretty cool idea. I am not sure I would use it but I will keep it in mind if I ever need something like this…
This is pretty cool and neat. I love what you did with those divs :P. Keep up the good work.
This is really imaginative use of CSS! It impresses me it looks good in Internet Explorer; from my experience IE and any transforms are a nightmare.
I do have one suggestion though. In IE it’s stuck in faded out mode because of the opacity setting on the div tag. IE reads this but doesn’t yet support animation so it’s not fading in. I’d personally add a tiny snippet somewhere on the page that sets the opacity of the div to 100% opaque in IE so that it looks like a typical image in IE.
I believe you could simply add an underscore opacity to the div as only IE uses them:
.spinner div {
opacity: 0.2;
_opacity: 1;
}
However it’s been awhile since I’ve bothered to cater to IE. Correct me if I’m wrong. Again, very nice page. Will definitely link to this.
Nevermind my previous comment! The underscore hack doesn’t work in IE9 so that wouldn’t work. I guess the other way to do it would be to add a little seperate stylesheet in the header to display if the person is using internet explorer:
Tried that and it works. :-)