85

How would I rotate an element with a jQuery's .animate()? I'm using the line below, which is currently animating the opacity correctly, but does this support CSS3 transforms?

$(element).animate({
   opacity: 0.25,
   MozTransform: 'rotate(-' + -amount + 'deg)',
   transform: 'rotate(' + -amount + 'deg)'
});
Dyin
  • 5,815
  • 8
  • 44
  • 69
kalpaitch
  • 5,193
  • 10
  • 43
  • 67
  • 1
    There is a jQuery plugin that will animate CSS transforms. Works in Firefox, Chrome, Safari, Opera and Internet Explorer. https://github.com/puppybits/QTransform – puppybits Jun 03 '11 at 20:57
  • Ended here in a search with the same topic, and downladed the plugin; works fine, but it caused a conflict with this instruction in another plugin I made: $("#"+self.id).css("transform", "scale(1)"); I changed this line: elem.style[$.cssProps.transform] = val+'%'; to this: if ( isNaN(val) ) elem.style[$.cssProps.transform] = val; else elem.style[$.cssProps.transform] = val+'%'; Think it doesn´t need further explanation. – sergio0983 Jun 15 '16 at 16:43

7 Answers7

97

As far as I know, basic animates can't animate non-numeric CSS properties.

I believe you could get this done using a step function and the appropriate css3 transform for the users browser. CSS3 transform is a bit tricky to cover all your browsers in (IE6 you need to use the Matrix filter, for instance).

EDIT: here's an example that works in webkit browsers (Chrome, Safari): http://jsfiddle.net/ryleyb/ERRmd/

If you wanted to support IE9 only, you could use transform instead of -webkit-transform, or -moz-transform would support FireFox.

The trick used is to animate a CSS property we don't care about (text-indent) and then use its value in a step function to do the rotation:

$('#foo').animate(
..
step: function(now,fx) {
  $(this).css('-webkit-transform','rotate('+now+'deg)'); 
}
...
Ryley
  • 21,046
  • 2
  • 67
  • 81
  • This is a painful solution both regarding code maintenance and speed. Forget `jQuery` while `transform`ing, check my solution. – Dyin Oct 08 '13 at 19:23
  • What about if you have value that changes all the time to rotate, not fixed one ? – edonbajrami Mar 18 '14 at 09:51
80

Ryley's answer is great, but I have text within the element. In order to rotate the text along with everything else, I used the border-spacing property instead of text-indent.

Also, to clarify a bit, in the element's style, set your initial value:

#foo {
    border-spacing: 0px;
}

Then in the animate chunk, your final value:

$('#foo').animate({  borderSpacing: -90 }, {
    step: function(now,fx) {
      $(this).css('transform','rotate('+now+'deg)');  
    },
    duration:'slow'
},'linear');

In my case, it rotates 90 degrees counter-clockwise.

Here is the live demo.

Community
  • 1
  • 1
atonyc
  • 2,207
  • 2
  • 19
  • 25
51

In my opinion, jQuery's animate is a bit overused, compared to the CSS3 transition, which performs such animation on any 2D or 3D property. Also I'm afraid, that leaving it to the browser and by forgetting the layer called JavaScript could lead to spare CPU juice - specially, when you wish to blast with the animations. Thus, I like to have animations where the style definitions are, since you define functionality with JavaScript. The more presentation you inject into JavaScript, the more problems you'll face later on.

All you have to do is to use addClass to the element you wish to animate, where you set a class that has CSS transition properties. You just "activate" the animation, which stays implemented on the pure presentation layer.

.js

// with jQuery
$("#element").addClass("Animate");

// without jQuery library
document.getElementById("element").className += "Animate";

One could easly remove a class with jQuery, or remove a class without library.

.css

#element{
    color      : white;
}

#element.Animate{
    transition        : .4s linear;
    color             : red;
    /** 
     * Not that ugly as the JavaScript approach.
     * Easy to maintain, the most portable solution.
     */
    -webkit-transform : rotate(90deg);
}

.html

<span id="element">
    Text
</span>

This is a fast and convenient solution for most use cases.

I also use this when I want to implement a different styling (alternative CSS properties), and wish to change the style on-the-fly with a global .5s animation. I add a new class to the BODY, while having alternative CSS in a form like this:

.js

$("BODY").addClass("Alternative");

.css

BODY.Alternative #element{
    color      : blue;
    transition : .5s linear;
}

This way you can apply different styling with animations, without loading different CSS files. You only involve JavaScript to set a class.

Community
  • 1
  • 1
Dyin
  • 5,815
  • 8
  • 44
  • 69
  • 1
    That's fine, but it is limited to [browsers that support CSS3 transitions](http://caniuse.com/#search=transition). So, no IE8 or IE9. That's a pretty big segment to give up. – Ryley Oct 08 '13 at 22:35
  • 11
    @Ryley You are talking about [12% percentage](http://www.w3schools.com/browsers/browsers_stats.asp) of users. IE8 or IE9 users are below 5%. Its not a pretty big segment to give up, as we still talking about the presentation layer and not the functionality. About 5% of your visitors won't see your 3D animations. **Also if a browser (IE) does not support `transition`, it certainly won't support your transformations either.** – Dyin Oct 09 '13 at 06:47
  • That's not entirely true - `transform` is supported by IE9. But I agree that it's not the biggest user group to give up (IE8). – Ryley Oct 09 '13 at 15:29
  • 2
    @Dyin It isn't a flat 12%, it depends on your target demographic. 50% of my firm's users are on IE8 according to google-analytics. The key is to know your audience. That being said: bravo dude! This answer is much better than the top two. Way to be the "diamond in the rough". – Ziggy Dec 19 '13 at 23:25
  • Truly it depends, but we are talking in generality. When I'm developing a web-service for a "HTTP-compatible" smart-fridge, I can't expect my `transition` or `rotate3d` to get rendered. We should aim our solutions for common scenarios, if otherwise not requested. – Dyin Dec 20 '13 at 19:09
  • I have to agree with Ziggy here. It depends on your audience, we are looking at about 80% of our users on IE8 and Windows XP. Pretty horrible, but that is what we have to deal with! – tribe84 Jul 10 '14 at 19:37
  • @tribe84 We should aim our solutions for common, general scenarios, if otherwise not requested. – Dyin Jul 12 '14 at 11:44
  • 2
    This also does not account for dynamic rotation values. – Yuschick Aug 27 '14 at 12:35
19

To add to the answers of Ryley and atonyc, you don't actually have to use a real CSS property, like text-index or border-spacing, but instead you can specify a fake CSS property, like rotation or my-awesome-property. It might be a good idea to use something that does not risk becoming an actual CSS property in the future.

Also, somebody asked how to animate other things at the same time. This can be done as usual, but remember that the step function is called for every animated property, so you'll have to check for your property, like so:

$('#foo').animate(
    {
        opacity: 0.5,
        width: "100px",
        height: "100px",
        myRotationProperty: 45
    },
    {
        step: function(now, tween) {
            if (tween.prop === "myRotationProperty") {
                $(this).css('-webkit-transform','rotate('+now+'deg)');
                $(this).css('-moz-transform','rotate('+now+'deg)'); 
                // add Opera, MS etc. variants
                $(this).css('transform','rotate('+now+'deg)');  
            }
        }
    });

(Note: I can't find the documentation for the "Tween" object in the jQuery documentation; from the animate documentation page there is a link to http://api.jquery.com/Types#Tween which is a section that doesn't appear to exist. You can find the code for the Tween prototype on Github here).

skagedal
  • 2,323
  • 23
  • 34
  • what is myRotationProperty...is it something custom you defined; and what is `now` depends on this one. – Muhammad Umer Sep 21 '14 at 01:06
  • @MuhammadUmer - yes, `myRotationProperty` is something custom, a made-up, "fake" CSS property. `now` is the first argument to the step callback function, specifying the change to the property value at this step. – skagedal Sep 22 '14 at 11:22
  • then did you also initialize this property in css too. Or you can just put it animate it takes it zero. – Muhammad Umer Sep 22 '14 at 15:44
9

Just use CSS transitions:

$(element).css( { transition: "transform 0.5s",
                  transform:  "rotate(" + amount + "deg)" } );

setTimeout( function() { $(element).css( { transition: "none" } ) }, 500 );

As example I set the duration of the animation to 0.5 seconds.

Note the setTimeout to remove the transition css property after the animation is over (500 ms)


For readability I omitted vendor prefixes.

This solution requires browser's transition support off course.

Paolo
  • 15,233
  • 27
  • 70
  • 91
3

I stumbled upon this post, looking to use CSS transform in jQuery for an infinite loop animation. This one worked fine for me. I don't know how professional it is though.

function progressAnim(e) {
    var ang = 0;

    setInterval(function () {
        ang += 3;
        e.css({'transition': 'all 0.01s linear',
        'transform': 'rotate(' + ang + 'deg)'});
    }, 10);
}

Example of using:

var animated = $('#elem');
progressAnim(animated)
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Faradin
  • 117
  • 1
  • 4
1
//this should allow you to replica an animation effect for any css property, even //properties //that transform animation jQuery plugins do not allow

            function twistMyElem(){
                var ball = $('#form');
                document.getElementById('form').style.zIndex = 1;
                ball.animate({ zIndex : 360},{
                    step: function(now,fx){
                        ball.css("transform","rotateY(" + now + "deg)");
                    },duration:3000
                }, 'linear');
            }