Create Spinning Rays with CSS3 Animations & JavaScript

By on  
CSS3 Animations

Thomas Fuchs, creator of script2 (scriptaculous' second iteration) and Zepto.js (mobile JavaScript framework), creates outstanding animated elements with JavaScript.  He's a legend in his own right, and for good reason:  his work has helped to inspire developers everywhere to drop Flash and opt for JavaScript development for smooth UI's.  One simple effect I enjoy is the script2 website's rotation of a ray image.  Let me show you how Thomas did it!


There's very little CSS to add to your stylesheet:

#rays	{ 
	background:url(rays.png) 0 0 no-repeat; 
	transform:scale(1) rotate(16.768rad);

The rays image should be a background image and it's probably best to set the element's dimensions. You can set an initial rotation value as well.

The JavaScript

The spinning rays effect works by using JavaScript to update browser-specific CSS3 animation properties.  The first step is detecting the browser:

var cssPrefix = false;
switch(Browser.name) {
	case "safari":
		cssPrefix = "webkit";
	case "chrome":
		cssPrefix = "webkit";
	case "firefox":
		cssPrefix = "moz";
	case "opera":
		cssPrefix = "o";
	case "ie":
		cssPrefix = "ms";

I've chosen to use MooTools' Browser object to detect the browser.  jQuery and other libraries provide a method by which to get the current browser.  As you can tell by the code, this effect will support Webkit-based browsers (Chrome, Safari, Webkit-mobile), Firefox, and Opera. Once the current browser is detected, you set forth a setInterval directive to perodically update the degree rotation of the element:

// Spin them rays!
if(cssPrefix) { // Skip IE!
	var rays = document.getElementById("rays"), degrees = 0, speed = 0.05;
	setInterval(function() {
		degrees += speed; // degree adjustment each interval
		rays.setAttribute("style","-" + cssPrefix + "-transform:rotate(" + degrees + "deg)");

With MooTools it would look like:

// Spin them rays!
if(cssPrefix) { // Skip IE!
	var rays = $("rays"), degrees = 0, speed = 0.05;
	(function() {
		degrees += speed; // degree adjustment each interval
		rays.set("style","-" + cssPrefix + "-transform:rotate(" + degrees + "deg)");

I've found a 20 millisecond class assignment interval provides a smooth but subtle transition.  After all you don't want the ray movement to steal the user's attention. To add some fun you could adjust the speed of the animation when the user mouses in and out of the element:

	mouseenter: function() { // 5x! Warp speed!
		speed = 0.25;
	mouseleave: function() { // Back to normal;
		speed = 0.05;

Subtlety is the key to using this effect...effectively.  Using CSS properties to transition the element's rotation is even more optimal, seeing as they're native to the browser.  You'll want to be sure not to use this effect to much on a given page, as many concurrent animations can be taxing to any browser.  I'd also like to point out that Safari and Chrome handle these animations best.

Track.js Error Reporting

Upcoming Events

Recent Features

  • CSS 3D Folding Animation

    Google Plus provides loads of inspiration for front-end developers, especially when it comes to the CSS and JavaScript wonders they create. Last year I duplicated their incredible PhotoStack effect with both MooTools and pure CSS; this time I'm going to duplicate...

  • How I Stopped WordPress Comment Spam

    I love almost every part of being a tech blogger:  learning, preaching, bantering, researching.  The one part about blogging that I absolutely loathe:  dealing with SPAM comments.  For the past two years, my blog has registered 8,000+ SPAM comments per day.  PER DAY.  Bloating my database...

Incredible Demos

  • jQuery Countdown Plugin

    You've probably been to sites like RapidShare and MegaUpload that allow you to download files but make you wait a specified number of seconds before giving you the download link. I've created a similar script but my script allows you to animate the CSS font-size...

  • dwImageProtector Plugin for jQuery

    I've always been curious about the jQuery JavaScript library. jQuery has captured the hearts of web designers and developers everywhere and I've always wondered why. I've been told it's easy, which is probably why designers were so quick to adopt it NOT that designers...


  1. Very nice, and not overly dramatic to make it seem unnecessary. I could see this being implemented in a lot of really great ways.

  2. Alelo

    hmm not working in Chrome 8.0.552.224 :( but looks nice in Safari

  3. css3 awesome … in IEless world :)

  4. Ya its not working on chrome 10.0.612.1
    perfect on safari. gr8 tho!

  5. CBloss

    Very interesting! Works good on Firefox, but like other people are saying, not working in IE7 or Chrome.

  6. IE9 now supports CSS transform, is there any particluar reason that it wasn’t included? (other than who knows if it’ll actually make it into the final release)

    What would be really interesting is to see this done without the ray.png. I’ve seen a sunburst type design done in the CSS3 iOS icons, it should be possible, I would think!

  7. The Safari issue surprises me — I’ll look into that.

    I don’t yet have an IE9-compatible OS so I couldn’t test — that’s why it wasn’t included.

  8. Ahhh, in the switch statement of the Browser.name, there is no case for Chrome, only safari. ;-) Hence the reason chrome doesn’t spin.

  9. It didn’t work in any browser for me! (Chrome 7, FF 3.6, FF 4, Opera) :-(

  10. Tested IE, this works beautifully in the IE platform preview 7 (the only place ms-transform is supported thus far) works just fine with a case statement for IE, and a cssPrefix of “ms”.

    Thanks for this, David. Love the effect. :-)

  11. Rohith

    doesnt work in Chrome in ubuntu 10.10
    But works in firefox.
    Realy cool

  12. I’ve updated the post for Chrome and IE!

    • Got it tested under Ubuntu Chrome and it’s really awesome!

      I’ve seen something similar to this at:
      G R O O v y !

    • Oh snap, I though you did it using MooTools!
      The power of habit :P

    • It is using mootools. ;-)

    • @dustin
      yea, I feel dumb.

  13. Really beautiful. I love the effect. The code is not very complicated and I can understand. Thank you so much for sharing great article.

  14. Great work David…
    BTW. Web browsers still need some performance optimization. This simple effect use 50% of my CPU (MacBookPro C2D 2,4 GHz) :-/

  15. Andy

    Does not work in any browser for me either, I’m on a PC. I tried Chome, Firefox, Safari and Opera

    • I’m on windows 7 and it works fine in Chrome 8, Firefox 3.6, IE9 Platform Preview, and Safari 5

  16. hamburger

    Very nice effect
    Does it work only with moo1.3 or with older versions (1.2.5) too?

    • 1.2.5 should work if you have the Browser object with it. The periodical code will work with any version of MooTools; the browser sniffing is what you’d need to make sure you had, or customized.

  17. nice tut.
    really smooth and nice work.

  18. wow

    useless as it only targets specific rendering engines

    • Really? It works in Safari, Chrome, Firefox, IE9, and will soon work in Opera (if they keep their word), I don’t know what the hell else you would want?

      No, it doesn’t work in Netscape Navigator 4.7.

  19. Dijital

    Works nicely on my HTC Desire running Android 2.2

  20. Matthew Grigajtis

    The code is slightly wrong in the sense that it doesn’t skip IE like the comments indicate. Setting the cssPrefix to false in the case of IE would actually be correct.

    • Considering IE9 supports CSS transforms, I believe it is correct. (You’ll have to check out the platform preview 4 to see this, and it will be in the final release of IE)

  21. You can actually detect which transform property to use instead of that nasty browser sniff branch.

  22. Erez Hod

    Very cool, I love it!
    Is there a way to do that with jQuery as well?

  23. I’m afraid that in win7(32bit) with FF 3.6.13 or Opera 11.00 1156 the script doesn’t work.
    Any tip about that?
    Thank you!

  24. MechanisM

    jQuery version?

  25. uho

    what should i do in html page ?

    • uho

      no one know about my question ?

  26. Nathan Jones

    I’ve been looking at these kind of animations for a while and your solution is quite elegant. Thanks for the post.

    I had a go at a no js version of this. I thought you might like to see a completely javascript free version.

    I’ve been playing around with css3 animation. This is the Safari webkit code, but it can be made to work in FF etc.

    in the #rays

    -webkit-animation-name:             rotate; 
        -webkit-animation-duration:         20s; 
        -webkit-animation-iteration-count:  infinite;
        -webkit-animation-timing-function: linear;

    and the animation style

    @-webkit-keyframes rotate {
      from {
        -webkit-transform: rotate(0deg);
      to { 
        -webkit-transform: rotate(360deg);
  27. This is a top effect.. I will be implementing this effect for my little poster website next week.(www.zip-posters.co.uk)
    It Works great on Mac Chrome, Safari, FF, Opera etc
    Works on FF,Safari & Chrome… But the rotation in chrome is a bit choppy and had to do a work around in IE to make it static and also not working on IE 9 Beta. but at least it displays
    Shame about IE, but then again it’s a shame about IE…
    I think IE was invented purely as a mechanism for stressing web devs out and making them work for there money.
    …Love this Site David

  28. Great stuff mate, love it!

  29. I just stole your demo’s rays-main.png image: http://www.cmsbox.com/de/cms
    I went for CSS Animations though.

  30. Love the effect. I’ll also be using this – Thanks man!

  31. This effect could be done in pure CSS with animations by keyframes. Just a thought… :)

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!

Recently on David Walsh Blog

  • Get Node.js Command Line Arguments with yargs

    Using command line arguments within Node.js apps is par for the course, especially when you're like me and you use JavaScript to code tasks (instead of bash scripts).  Node.js provides process.argv but that doesn't provide a key: value object like you'd expect: Bleh.  If you want to work with a...

  • OâReilly Velocity Conference â New York

    My favorite front-end conference has always been O'Reilly's Velocity Conference because the conference series has focused on one of the most undervalued parts of client side coding:  speed.  So often we're so excited that our JavaScript works that we forget that speed, efficiency, and performance are just as important. The next Velocity...

  • Free Download: Font Bundle Featuring 17 Incredible Typefaces

    The only thing we love more than a good font, is a good free font. So we’ve combed the Web for some of our favorite free fonts, and gathered them here in a single download. You’ll find a variety of useful typefaces, from highly geometric designs...

  • OâReilly Velocity Conference â Amsterdam

    My favorite front-end conference has always been O'Reilly's Velocity Conference because the conference series has focused on one of the most undervalued parts of client side coding:  speed.  So often we're so excited that our JavaScript works that we forget that speed, efficiency, and performance are just as important. The next Velocity...

  • CanIUse Command Line

    Every front-end developer should be well acquainted with CanIUse, the website that lets you view browser support for browser features.  When people criticize my blog posts for not detailing browser support for features within the post, I tell them to check CanIUse:  always up to date, unlike...