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!

The CSS

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

#rays	{ 
	background:url(rays.png) 0 0 no-repeat; 
	position:absolute; 
	top:0; 
	left:0; 
	width:490px; 
	height:490px; 
	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";
		break;
	case "chrome":
		cssPrefix = "webkit";
		break;
	case "firefox":
		cssPrefix = "moz";
		break;
	case "opera":
		cssPrefix = "o";
		break;
	case "ie":
		cssPrefix = "ms";
		break;
}

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)");
	},20);
}

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)");
	}).periodical(20);
}

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:

rays.addEvents({
	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.

Recent Features

  • By
    Vibration API

    Many of the new APIs provided to us by browser vendors are more targeted toward the mobile user than the desktop user.  One of those simple APIs the Vibration API.  The Vibration API allows developers to direct the device, using JavaScript, to vibrate in...

  • By
    Chris Coyier’s Favorite CodePen Demos

    David asked me if I'd be up for a guest post picking out some of my favorite Pens from CodePen. A daunting task! There are so many! I managed to pick a few though that have blown me away over the past few months. If you...

Incredible Demos

Discussion

  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:
      http://scripty2.com/
      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.
    https://gist.github.com/523692

  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… :)

  32. Jay

    It’s indeed fun and educational to see how this is done.

    In real life though, I am wonder if you can use this to make text blink or scroll left or right, up or down.

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