Avatar of Joel Olawanle
Joel Olawanle on (Updated on )

DigitalOcean joining forces with CSS-Tricks! Special welcome offer: get $100 of free credit.

The rotate property in CSS turns an element around one or more axes. Think of it like poking one or more pins into an element and spinning the element around those points in clockwise and counter-clockwise directions measured in degree, gradian, radian, and turn values.

.element {
  rotate: 45deg;

While CSS already has another way to rotate elements using the rotate() function in the transform property, like this:

.element {
  transform: rotate(45deg);

…the CSS rotate property does it independently of the transform property altogether, plus the added benefit of being able to rotate along the Z-axis, something not currently possible with transform: rotate().


rotate: none | <angle> | [ x | y | z | <number>{3} ] && <angle>;

The angle values are expressed in degrees, gradians, radians, or turns.

/* Keyword values */
rotate: none;

/* Angle values */
rotate: 45deg;
rotate: 0.35turn;
rotate: 1.27rad;
rotate: -50grad;

/* x, y, or z-axis name plus angle */
rotate: x 45deg;
rotate: y 0.35turn;
rotate: z 1.27rad;

/* Vector plus angle values */
rotate: 1 0.5 1 45deg;

/* Global values */
rotate: inherit;
rotate: initial;
rotate: revert;
rotate: unset;
  • Initial: none
  • Applies to: transformable elements
  • Inherited: no
  • Percentages: n/a
  • Computed value: as specified
  • Animation type: a transform
  • Creates stacking context: yes


  • none: Default value. No rotation is applied to the element.
  • <angle>: An <angle> value is used to specify a numeric value (expressed with deg, grad, rad or turn units) for how much to rotate the element around the Z axis. This value works exactly like the rotate() function we use with the transform` property.
  • axis name with <angle> value: This identifies which axis (X, Y or Z)) to rotate around along with a numeric value for how much to rotate the element around that axis
  • vector plus angle value: The three numbers represents an origin-centered vector that defines a line around which you want to rotate the element, plus an <angle> used to specify the angle to rotate the element through. Equivalent to a rotate3d() (3D rotation) function.


Most times, you’ll likely find yourself using a degree unit (e.g. 45deg) as a rotate property value. But as we’ve seen, there are four total types of units that the property accepts. They’re less common that, say, pixels, ems, rems, and percentages, so let’s break them down to understand what they are and how they work.

  • deg: One degree is 1/360 of a full circle.
  • grad: One gradian is 1/400 of a full circle.
  • rad: A radian is the length of a circle’s diameter around the shape’s arc. One radian is 180deg, or 1/2 of a full circle. One full circle is 2π radians, which is equal to 6.2832rad or 360deg.
  • turn: One turn is one full circle. So, halfway around a circle is equal to .5turn, or 180deg.

The rotate property accepts any of these units, as they are different way of expressing the same idea: an angle around a circle. And they are equally supported by all major browsers.

Transitions and animations

The rotate property supports CSS transitions and animations. That means we can transition from one angle to another on, say, hover:

.element {
  rotate: 5deg;

.element:hover {
  rotate: 45deg;
  transition: rotate 1s;

The same thing goes for CSS animations when working with @keyframes. We can use rotate when we define an animation like we can do with others:

We can implement more interesting and complex transitions and animations when we combine rotate with the transform functions, rotating an element independently of the transforms.

If you look at the browser support closely, you may want to consider a fallback solution that works with other browsers until rotate property gets full browser support. The transform property is a viable fallback alternative for an independent transform property, such as rotate.

For example, we could drop the rotate animation into an @supports block. This way, the animation only runs if the browser supports the rotate property:

/* Using transform by default */
@keyframes loader {
  0% {
    transform: rotate(0deg);
  100% {
    transform: rotate(180deg);

/* Use rotate instead, but only if it is supported */
@supports (rotate: 0deg) {
  @keyframes loader {
    0% {
      rotate: 0deg;
    100% {
      rotate: 180deg;

Speaking of which…

Browser support


More information

Further reading