CSS3 Transforms: Adding 2D and 3D Effects To Web Pages

Transitions are a way to smooth css changes to an element so they’re more natural. However, they don’t define the changes themselves. Today I want to look at a set of more dynamic changes, namely transforms.

Transformer vehicle

CSS transforms come in two types.

  • 2D Transforms allow elements rendered by CSS to be transformed in two-dimensional space.
  • 3D Transforms extends CSS Transforms to allow elements rendered by CSS to be transformed in three-dimensional space.

2D transforms have pretty good browser support, by which I mean they work in the current versions of all major browsers.

They won’t work in IE8 and below, however you’re probably used to that, and like transitions we probably shouldn’t be using transforms for critical elements.

I’ve set up a demo illustrating different 2D transforms.

The situation with 3D transforms is different. These will work in Safari and Chrome (as well as mobile Safari and mobile Android), but not much else. IE10 will support them, though with Firefox and Opera it’s anyone’s guess.

Like transitions we’ll need to use vendor prefixes to get things working, though in this post I’ll show properties without the prefixes.

A square that's been rotated 45 degrees, scaled up 1.5 times and moved 80px to the right and down

2D CSS Transforms

If you think of a computer monitor as a flat 2-dimensional plane then 2D transforms are a way to manipulate elements on that 2-dimensional plane.

There are only 2 properties we have to deal with, though the magic really happens with the values we give to the first property.

  • transform property
  • transform-origin property
  • transformation functions (values of the transform property)

As we’ll see in a moment it’s the last of these, transform functions where the fun begins.


The values you can give to the transform property are none or one or more transform functions. The idea is to set which transform you’ll be using.

{code type=css}
div {
transform: scale(1.5);

The above will scale divs 1.5 times their initial value.

Transforms apply to both block level and inline elements. When we use relative measurements like % they will refer to the element’s box and not its container.


As the name implies the transform-origin property sets the origin of the transformation. The origin becomes a fixed point in the before and after transformation states.

{code type=css}
div {
transform-origin: 0, 0;

The above sets the origin to 0,0 and this point will be fixed throughout the transformation.

Values allowed are [percentage | length | left | center | right] [percentage | length | top | center | bottom]

The 1st value is the horizontal point and the 2nd is the vertical point unless one of the keywords used. If either horizontal or vertical value isn’t specified it defaults to center.

diagram showing matrix multiplication for transformation functions

Transformation Functions

This is the magic. Transformation functions define how the element is changed. With one exception you should be able to figure out what each does from the name alone.


Let’s start with the exception, since it’s the general case for all that follows.

The idea here is that all transformations can be represented by a 3×3 matrix. In the 2D transforms we’re only using the top 2 rows in the matrix for a total of 6 values.

The original coordinate system (pre-transform) = this matrix &times the new coordinate system (post-transform).

In essence the matrix transform function allows you to create a custom transform, while the remaining functions are all specific values of this matrix.

{code type=css}
div {
matrix(<number>, <number>, <number>, <number>, <number>, <number>);

You’ll likely use the functions that follow in practice, but should you want to use matrix you would specific each of the 6 values.

A  squre undergoing a translation transform


There are 3 translation transforms, which allow you to move an element from one place to another.

  • translate(<translation-value>[, <translation-value>])
  • translateX(<translation-value>)
  • translateY(<translation-value>)

{code type=css}
div {
transform: translate(10px, 30%);

translation-values can be either a length or a % and each of the 3 functions above does just what you think it will do.

All 3 move the element from one location to another by an amount equal to the values set in the function. The first in both x and y coordinates and the latter 2 in one or the other.

When translate is used the first value is the x-coordinate and the second the y-coordinate.


There are also 3 scaling functions, which I’m sure you can guess make the element larger or smaller

  • scale(<number>[, <number>])
  • scaleX(<number>)
  • scaleY(<number>)

{code type=css}
div {
transform: scale(2.0);

Scale takes a unitless number. Numbers larger than 1.0 scale up and numbers less than 1.0 scale down. Like translate we can scale in both the x and y directions or in one or the other.

As with translate the first value is the x-coordinate and the second the y-coordinate.


Rotate only has the single function since by definition rotation acts around a fixed point (transform-origin) instead of x and y coordinates.

  • rotate(<angle>)

{code type=css}
div {
transform: rotate(45deg);

Positive angles rotate clockwise and negative values rotate counter-clockwise


I’ll give you one guess what skew does. It works similarly to the functions above and comes in the generic and x and y flavors.

  • skew(<angle> [, <angle>])
  • skewX(<angle>)
  • skewY(<angle>)

With skew you define the angle of skew in either or both directions

{code type=css}
div {
transform: skew(5deg, 20deg);

A caterpillar eating a leaf

Multiple Transforms

You aren’t limited to a single transform, but can use several as a space separated list.

{code type=css}
div {
transform: translate(10px 30%) scale(2.0) rotate(45deg) skew(5deg, 20deg);

When multiple transforms are set the net result is the same as if each transform was applied separately in the order in which they were applied.

3D glasses

3D CSS Transforms

If you’ve understood how 2D transforms work you shouldn’t have any trouble understanding 3D transforms either as they simply extend their 2D counterparts.

They use the transform property the same way by specifying one of the transform functions. They also set a transform-origin with the one difference being the z-coordinate added to the x and y coordinates.

{code type=css}
div {
transform-origin: 0, 0, 0;

There are a few new properties added as well, which I’ll cover briefly since 3D transforms probably aren’t ready for use yet beyond experimentation.

  • transform-style — defines how nested elements are rendered in 3d space. There are 2 values; flat and preserve-3d. Flat means that children of the element are rendered flattened onto the 2d plane of the element and preserve-3d prevents this flattening.
  • perspective — applies the same transform as the perspective transform-function (which we’ll get to momentary) except that it applies to children of the element. Values are none or a number.
  • perspective-origin — establishes the origin for the perspective set above. Values are [percentage | length | left | center | right] [percentage | length | top | center | bottom].
  • backface-visibility — determines if the backside of the transformed element is visible. Values are either visible or hidden.

A cocoon seen through a magnifying glass

3D Transformation Functions

The 3D transform functions build on the 2D functions in a rather predictable way, mostly by adding one or 2 new functions to each group that shouldn’t require explanation.

To matrix is added matrix3d, which now takes into account that bottom row of the matrix.

matrix3d(<number>, <number>, <number>, <number>, <number>, <number>, <number>, <number>, <number>;)

Again the remaining functions are specific values of matrix or matrix3d

Translate adds:

  • translate3d(<translation-value>, <translation-value>, <translation-value>)
  • translateZ(<translation-value>)

Scale adds:

  • scale3d(<number>, <number>, <number>)
  • scaleZ(<number>)

Rotate adds:

  • rotate3d(<number>, <number>, <number>, <angle>)
  • rotateX(<angle>)
  • rotateY(<angle>)
  • rotateZ(<angle>)

Because we now have another dimension we can specify around which axis the element will rotate.

Skew doesn’t add anything new, but we do have one new function, perspective.

  • perspective(<number>)

Perspective sets a perspective projection matrix, which maps a viewing cube onto a pyramid whose base is infinitely far away and whose peak represents the viewer’s position.

The number set in the function specifics the depth and represents the distance of the z=0 plane from the viewer.

Huh? That’s how I felt reading what perspective does. Perhaps this will be clearer.

Lower values lead to a flatter pyramid and higher values a more pronounced pyramid. The lower the number the more foreshortening in the perspective.

Again these 3D transforms are still not supported well and so for now are more for you to experiment with than use in an actual project. However there are some amazing examples of 3d transforms. You’ll want to use a Webkit browser to see them.

Orange butterfly on a  leaf


Like transitions, transforms can be a nice way to add something to the experience of your design. Transforms don’t require a css change in order to happen, though they can certainly happen with changes in the state of an element.

Used sparingly and subtly transforms can work to great effect, but be careful about getting carried away with them.

Few if any want to see elements on your page moving around or changing shape all the time. However adding a glow effect when mousing over an element or setting a background image at an angle can be a nice surprise for your audience.

Because browser support is not 100% there yet, you do need to make sure the transformations you set aren’t critical to the design, but for non-critical things go right ahead and use them.

« »

Download a free sample from my book, Design Fundamentals.


Leave a Reply

Your email address will not be published. Required fields are marked *