8.6 CSS transform

Fashioning unique shapes

We’ve seen so far how CSS allows us to apply colors, set fonts, tweak the text settings, position elements, space them, decorate them, move them around.

CSS transforms are a collection of functions that allow to shape elements in particular ways:

  • translate: moves the element along up to 3 axis (x,y and z)
  • rotate: moves the element around a central point
  • scale: resizes the element
  • skew: distorts the element

transform properties

There are 3 CSS transform properties available:

  • transform defines which transform function to use (translate, rotate, scale…)
  • transform-origin allows to modify the origin point of a transformation (works like background positions)
  • transform-style is for 3d settings

Note that unlike background and border, transform is not a shorthand property.

We’ll only use transform here.

Doesn’t break the Flow

To prevent unexpected behavior, transformed elements do not affect the Flow. Whether rotated, scaled or translated, they won’t affect other elements.


The translate() function allows to move an element across the plane (on the x and y axis). It accepts either:

  • 1 parameter: moves the element along the x axis
  • 2 parameters: first value is for the x axis, second for the y one

It’s like using relative positioning with left and top values.

Let’s redo our circuit animation using translation instead of left/top positioning:

@keyframes translating {
  0%  { transform: translate(0, 0);}
  25% { transform: translate(240px, 0);}
  50% { transform: translate(240px, 140px);}
  75% { transform: translate(0, 140px);}
  100%{ transform: translate(0, 0);}
p{ animation: translating 4s linear infinite;}


Remember: transform is the CSS property, translate() is the CSS value attached to that property (and also happens to be a function).

You can use translateX() and translateY() to only move your element along the x and y axis respectively.


The rotate() function allows to make an element revolve around a fixed point. By default, it revolves around the element’s center. Think of it as vinyl being played on a turntable.

rotate() accepts only 1 parameter, which is an angle value defined in degrees deg, gradians grad, radians rad or turns turn (with 1 turn being equivalent to a full circle).

@keyframes rotating {
  0%  { transform: rotate(0deg);}
  100%{ transform: rotate(360deg);}
p{ animation: rotating 4s linear infinite;}



The scale() function allows to resize an element. It can either expand or shrink it. The function accepts either:

  • 1 parameter: the element is resized uniformily in height and width
  • 2 parameters: the first value resizes the element horizontally, the second one vertically

The range of possible value is:

  • 1: the element retains its original size
  • 2: the element doubles in size
  • 0.5: the element is half of its size
  • 0: the element basically disappears (as its height and width are equal to zero)
  • -1: the element is mirrored
@keyframes scaling {
  0%  { transform: scale(1);}
  20%{ transform: scale(2);}
  40%{ transform: scale(0.5);}
  60%{ transform: scale(0);}
  80%{ transform: scale(-1);}
  100%{ transform: scale(1);}
p{ animation: scaling 10s steps(1) 0s infinite;}

scale(1): normal size

scale(2): double size

scale(0.5): half size

scale(0): zero size (invisible)

scale(-1): mirrored


Like translate(), the scale() function has x and y versions: scaleX() and scaleY() to resize horizontally and vertically respectively.


The skew() function allows to distort an element, by dragging its sides along a line basically.

This transform function is rarely used, as its effects are quite unpredictable, and its results not necessarily appealing. Nevertheless, let’s see how it works.

Like scale(), the skew() functions accepts either:

  • 1 parameter: the element is distorted horizontally
  • 2 parameters: the first value distorts the element horizontally, the second one vertically

And like rotate(), skew() only accepts angle values like degrees deg.

@keyframes skewing {
  0%  { transform: skew(0deg);}
  20% { transform: skew(10deg);}
  40% { transform: skew(45deg);}
  60% { transform: skew(90deg);}
  80% { transform: skew(120deg);}
  100%{ transform: skew(0deg);}
p{ animation: skewing 10s steps(1) 0s infinite;}

skew(0deg): no distortion

skew(10deg): subtle horizontal distortion

skew(45deg): quarter distortion

skew(90deg): half distortion (invisible)

skew(120deg): same as -60deg


3d functions

We’ve seen how transform functions operate on a plane, along the x and y axis.

For example:

  • translate() with up to 2 parameters:
    • translate(x)
    • translate(x,y)
  • translateX() as x only
  • translateY() as y only

But all these functions also have a 3d version.

For example, translate() has a translate3d() version that performs transformation along 3 dimensions, which means it includes the z axis as well (and as such, a standalone translateZ() function exists as well).

The z parameter basically make the element move closer and further, whether we increase or decrease its value. It’s like zooming in and out.

@keyframes zooming {
  0%  { transform: translate3d(0, 0, 0);}
  100%{ transform: translate3d(0, 0, 200px);}
p{ animation: zooming 5s alternate;}


The green block rise 200px “upwards”, as if coming closer to us, along the z axis.

perspective: 500; needs to be applied to the parent element in order for the 3d space to become active. Alternatively, transform: perspective(500px); can be used as well.

Back to top

Learn CSS with my ebook

This ebook is a step by step guide in which I teach you how to build your own personal webpage from scratch, line by line, with HTML5, CSS3, and even JS.

CSS in 44 minutes book cover
Get it now