---
title: CSS transitions and transforms for beginners
teaser: Learn to add simple animations and movement to your design with CSS transitions
  and transforms.
tags: design,css
author:
- Rachel Cope
- Elaina Natario
published_on: 2015-08-24
---

This post will introduce you to CSS transitions and CSS transforms: **the CSS
power couple**. When used together, these properties allow you to create simple
animations and add valuable interaction and visual feedback for your users.

Just remember when adding any kind of movement to your project to keep it
simple, subtle, and consistent. The movement you create should convey meaning,
always enhancing, not distracting from the interaction for your users.

So what are transforms and transitions? At their most basic level, **transforms
move or change the appearance of an element**, while **transitions make the
element smoothly and gradually change** from one state to another.

## CSS transitions: an introduction

Let's start with CSS transitions. Transitions are the grease in the wheel of CSS
transforms. Without a transition, an element being transformed would change
abruptly from one state to another. By applying a transition you can control the
change, making it smooth and gradual.

Hover below:

<figure>
  <p data-height="335" data-theme-id="18100" data-slug-hash="raGwPq"
  data-default-tab="result" data-user="rachelcope" class='codepen'>
  See the Pen <a href='http://codepen.io/rachelcope/pen/raGwPq/'>With and Without
  Transition</a> by Rachel Cope (<a href='http://codepen.io/rachelcope'>@rachelcope</a>)
  on <a href='http://codepen.io'>CodePen</a>.</p>
  <script async src="//assets.codepen.io/assets/embed/ei.js"></script>
</figure>

In this post I'll be using transitions in conjunction with transforms. However,
transitions can also be used elsewhere where elements change from one style to
another (e.g., when a button changes color on hover).

There are two properties that are required in order for the transition to take
effect:

1. `transition-property`
2. `transition-duration`

### Note: Transition Shorthand

Each transition property can be defined individually, but for cleaner and faster
code, it's recommended that you use the transition shorthand.

Here's the full shorthand sequence. Again, the first two properties are
required.

```css

div {
  transition: [property] [duration] [timing-function] [delay];
}
```

## `transition-property` *(required)*

The `transition-property` specifies the CSS property where the transition will
be applied. You may apply a transition to an individual property (e.g.,
`background-color` or `tranform`) or to all properties in the rule-set (i.e.,
`all`).

### CSS syntax examples for `transition-property`

```css
div {
  transition-property: all;
  transition-property: transform;
}
```

## `transition-duration` *(required)*

The `transition-duration` property specifies the time span of the transition.
You can specify in seconds or milliseconds.

<figure>
  <p data-height="360" data-theme-id="18100" data-slug-hash="vOqVjg"
  data-default-tab="result" data-user="rachelcope" class='codepen'>See the Pen <a
  href='http://codepen.io/rachelcope/pen/vOqVjg/'>Translation Duration</a> by
  Rachel Cope (<a href='http://codepen.io/rachelcope'>@rachelcope</a>) on <a
  href='http://codepen.io'>CodePen</a>.</p>
  <script async src="//assets.codepen.io/assets/embed/ei.js"></script>
</figure>

### CSS syntax example for `transition-duration`

```css
  div {
    transition-duration: 3s;
  }
```

### Shorthand example for `transition-duration`

```css
div {
  transition: all 3s;
}
```

## `transition-timing` *(optional)*

The `transition-timing-function` property allows you to define the speed of the
transition over the duration. The default timing is `ease`, which starts out
slow, quickly speeds up, and then slows down at the end. The other timing
options are: `linear`, `ease`, `ease-in`, `ease-out`, and `ease-in-out`.

Here's an example of the different timing options (used with the `transform:
translate` property):

<figure>
  <p data-height="429" data-theme-id="18100" data-slug-hash="gbxzmo"
  data-default-tab="result" data-user="rachelcope" class='codepen'>See the Pen <a
  href='http://codepen.io/rachelcope/pen/gbxzmo/'>Transition-Timing</a> by Rachel
  Cope (<a href='http://codepen.io/rachelcope'>@rachelcope</a>) on <a
  href='http://codepen.io'>CodePen</a>.</p>
  <script async src="//assets.codepen.io/assets/embed/ei.js"></script>
</figure>

For more advanced timing options, you can define a custom timing function with a
[cubic-bezier](https://developer.mozilla.org/en-US/docs/Web/CSS/timing-function).

### CSS syntax example for `transition-timing-function`

```css
div {
  transition-timing-function: ease-in-out;
}
```

### Shorthand example for `transition-timing-function`

```css
div {
  transition: all 3s ease-in-out;
}
```

## `transition-delay` *(optional)*

The `transition-delay` property allows you to specify when the transform will
start. By default, the transition starts as soon as it is triggered (e.g., on
mouse hover). However, if you want to transition to start after it is triggered
you can use the transition delay property.

<figure>
  <p data-height="350" data-theme-id="18100" data-slug-hash="vDIbj"
  data-default-tab="result" data-user="rachelcope" class='codepen'>See the Pen <a
  href='http://codepen.io/rachelcope/pen/vDIbj/'>Transition Delay Example</a> by
  Rachel Cope (<a href='http://codepen.io/rachelcope'>@rachelcope</a>) on <a
  href='http://codepen.io'>CodePen</a>.</p>
  <script async src="//assets.codepen.io/assets/embed/ei.js"></script>
</figure>

### Shorthand example for `transition-delay`

```css
div {
  transition: all 3s 1s;
}
```

A negative value will start the transition immediately, but part way through the
transition process.

### Staggering animations

You can also leverage `transition-delay` to stagger animations on elements.

<figure>
  <p class="codepen" data-height="425" data-slug-hash="raNeOgR" data-pen-title="Staggered transition" data-user="enatario" style="height: 425px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/enatario/pen/raNeOgR">
  Staggered transition</a> by Elaina Natario (<a href="https://codepen.io/enatario">@enatario</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>
</figure>

## CSS transforms: an introduction

Now that we reviewed how to make smooth and gradual transitions, let's look at
CSS transforms - how to make an element change from one state to another. With
the CSS transform property you can **rotate, move, skew, and scale elements**.
(This post will only cover 2D transforms, but stay tuned for future blog posts
on 3D transforms.)

Transforms are triggered when an element changes states, such as on mouse-hover
or mouse-click. The examples in this post will demonstrate transforms on
mouse-hover.

## `scale`

The `scale` value allows you to increase or decrease the size of an element.

For example, the value `2` would transform the size to be 2 times its original
size. The value `0.5` would transform the size to be half its original size.

<figure>
  <p data-height="329" data-theme-id="18100" data-slug-hash="gbxxXe"
  data-default-tab="result" data-user="rachelcope" class='codepen'>See the Pen <a
  href='http://codepen.io/rachelcope/pen/gbxxXe/'>Transform: Scale</a> by Rachel
  Cope (<a href='http://codepen.io/rachelcope'>@rachelcope</a>) on <a
  href='http://codepen.io'>CodePen</a>.</p>
  <script async src="//assets.codepen.io/assets/embed/ei.js"></script>
</figure>

You can scale an element by setting parameters for the width (X-axis) or height
(Y-axis). For example, `transform: scaleX(2)`.

Or, use the `scale()` shorthand to scale both axes at the same time: `transform:
scale(2);`. Or define them independently of each other: `transform: scale(2,
4);`

### CSS syntax example for `scale`

Don't forget to add a transition! Without applying transition, the element would
abruptly change sizes. Add the transition to the **parent selector** (not the
hover selector). To make the transition smooth on both hover-over/hover-off.

```css
div {
  transition: transform 1s;
}

div:hover {
  transform: scale(2);
}
```

### A real life example

Scale can be handy for hover states on an image that is also a link to indicate user interactivity.
In this case we can use this alongside `object-fit` to scale it within a container and create a zoom
effect on hover.

<figure>
  <p class="codepen" data-height="636" data-slug-hash="MYWyexq" data-pen-title="Zoom image on hover" data-user="enatario" style="height: 636px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/enatario/pen/MYWyexq">
  Zoom image on hover</a> by Elaina Natario (<a href="https://codepen.io/enatario">@enatario</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>
</figure>

## `rotate`

With the `rotate` value, the element rotates clockwise or counterclockwise by a
specified number of degrees. A positive value, such as `90deg`, rotates the
element clockwise, while a negative value, such as `-90deg`, rotates it
counterclockwise.

<figure>
  <p data-height="327" data-theme-id="18100" data-slug-hash="mhkgr"
  data-default-tab="result" data-user="rachelcope" class='codepen'>See the Pen <a
  href='http://codepen.io/rachelcope/pen/mhkgr/'>Transform Rotate Example</a> by
  Rachel Cope (<a href='http://codepen.io/rachelcope'>@rachelcope</a>) on <a
  href='http://codepen.io'>CodePen</a>.</p>
  <script async src="//assets.codepen.io/assets/embed/ei.js"></script>
</figure>

You can rotate more than a full rotation with numbers over than 360, such as
`1080deg`, for three full rotations.

### CSS syntax example for `rotate`

```css
div {
  transition: transform 1s;
}

div:hover {
  transform: rotate(1080deg);
}
```

## `translate`

The `translate` value moves an element left/right and up/down. The movement is
based on the parameters given for the X (horizontal) Y (vertical) axes.

A positive X value moves the element to the right, while a negative X moves the
element to the left. A positive Y value moves the element downwards and a
negative Y value, upwards.

In this example, the element will move 20 pixels to the right and 20 pixels
down.

<figure>
  <p data-height="432" data-theme-id="18100" data-slug-hash="GgvvyQ"
  data-default-tab="result" data-user="rachelcope" class='codepen'>See the Pen <a
  href='http://codepen.io/rachelcope/pen/GgvvyQ/'>Transform: Translate</a> by
  Rachel Cope (<a href='http://codepen.io/rachelcope'>@rachelcope</a>) on <a
  href='http://codepen.io'>CodePen</a>.</p>
  <script async src="//assets.codepen.io/assets/embed/ei.js"></script>
</figure>

### CSS syntax example for `translate`

```css
div {
  transition: transform 1s;
}

div:hover {
  transform: translate(20px, 20px);
}
```

## `skew`

With the `skew` value, the element skews (or tilts) one direction or the other
based on the values given for the X and Y axes.

<figure>
  <p data-height="406" data-theme-id="18100" data-slug-hash="azyGpO"
  data-default-tab="result" data-user="rachelcope" class='codepen'>See the Pen <a
  href='http://codepen.io/rachelcope/pen/azyGpO/'>Transform: Skew</a> by Rachel
  Cope (<a href='http://codepen.io/rachelcope'>@rachelcope</a>) on <a
  href='http://codepen.io'>CodePen</a>.</p>
  <script async src="//assets.codepen.io/assets/embed/ei.js"></script>
</figure>

A positive X value tilts the element left, while a negative X value tilts it
right. A positive Y value tilts the element down, and a negative Y value tilts
is up. Or use a shorthand to include both X and Y properties:

### CSS syntax examples for `skew`

```css
div {
  transform: skewX(25deg);
  transform: skewY(10deg);
  transform: skew(25deg, 10deg);
}
```

```css
div {
  transition: transform 1s;
}

div:hover {
  transform: skewX(-20px);
}
```

Note: Skewing an element will also skew all of the children inside of the
element as well (which may make text content unreadable). 
If you need to maintain the original angle of a child element,
you can use the opposite value of skew to bring it back.

## `transform-origin`

The `transform-origin` property is separate from the transform property but
works in tandem with it. It allows you to specify the location origin of the
transform. By default, the origin is in the center of the element.

For example, if you are using the `transform: rotate` property but want it to
rotate not from the center, but from the top left corner, you'd use the value
`0% 0%` or `left top`. For the bottom right corner, you would use `0% 100%` or
`right bottom`, etc.

<figure>
  <p data-height="393" data-theme-id="18100" data-slug-hash="bNjGrL"
  data-default-tab="result" data-user="rachelcope" class='codepen'>See the Pen <a
  href='http://codepen.io/rachelcope/pen/bNjGrL/'>Transform Origin Example</a> by
  Rachel Cope (<a href='http://codepen.io/rachelcope'>@rachelcope</a>) on <a
  href='http://codepen.io'>CodePen</a>.</p>
  <script async src="//assets.codepen.io/assets/embed/ei.js"></script>
</figure>

Make sure to add the transform-origin property to the parent element, not with
the transform property in the hover selector.

```css
div {
  transform-origin: left top;
  transition: transform 1s;
}

div:hover {
  transform: rotate(720deg);
}
```

## Combining transforms

You can combine multiple transforms by using the transform shorthand or the
matrix method.

### Shorthand for `transform-origin`

The transform shorthand allows you to string the various transform methods into
one property.

```css
div {
  transform: rotate(90deg) scale(2) translateY(-50%) translateX(50%);
}
```

<figure>
  <p data-height="363" data-theme-id="18100" data-slug-hash="jELxad"
  data-default-tab="result" data-user="rachelcope" class='codepen'>See the Pen <a
  href='http://codepen.io/rachelcope/pen/jELxad/'>Combining Transforms</a> by
  Rachel Cope (<a href='http://codepen.io/rachelcope'>@rachelcope</a>) on <a
  href='http://codepen.io'>CodePen</a>.</p>
  <script async src="//assets.codepen.io/assets/embed/ei.js"></script>
</figure>

## Matrix

The matrix method allows you to combine the scale, skew, and translate
properties into one using a coordinate system. This can be very useful for
manipulating transforms with a javascript library but is very difficult to do by
hand. You can read more about the [matrix method and
coordinates](https://developer.mozilla.org/en-US/docs/Web/CSS/transform#matrix).

## `will-change`

The `will-change` property informs the browser to optimize rendering of property changes that may occur in a transition. Some transform changes necessitate the browser to repaint, which can cause slower performance on your page. By using `will-change`, you can prevent that repaint as the browser now knows to plan for those changes
ahead of time. Do note, however, that this property should be used _sparingly_; overuse by telling the browser about all the potential property changes can cause its own performance issues.

```css
button {
  background-color: blue;
  transition: background-color 0.2s ease-in-out, transform 0.2s ease-in-out;
  will-change: transform, background-color;
}

button:hover {
  background-color: orange;
  transform: rotate(30deg);
}
```

## Keeping an accessible experience in mind

While introducing motion in this manner can support a user experience and help direct actions and understanding,
it can sometimes become a harmful interaction, especially to those with vestibular disorders. In these cases,
we can respect user settings by applying the [`prefers-reduced-motion` media query](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion). Much like light/dark mode, this query takes a user preference setting on their device into account and applies styles that match those queries.

```css
button {
  transform: scale(1);
  transition: transform 0.5s ease-in-out;
}

button:hover {
  transform: scale(1.5);
}

@media screen and (prefers-reduced-motion: reduce) {
  button {
    transition-duration: 0;
  }
}
```

In the above example, we still scale the button on hover, but the easing of it is turned off if a user has reduced
motion preferences.

Another way of respecting a user preference is to not scale the button on hover (if it's not needed to convey meaning).

```css
button {
  transform: scale(1);
  transition: transform 0.5s ease-in-out;
}

button:hover {
  transform: scale(1.5);
}

@media screen and (prefers-reduced-motion: reduce) {
  button {
    transition-duration: 0;
  }

  button:hover {
    transform: scale(1);
  }
}
```

## 3D transforms

All of the transforms discuss elements in a two-dimensional space. However, all of these properties have companion functions for operating within a third dimension. While browser screens still operate in a 2D space (we're not looking to make you wear 3D glasses here), there are still some interactions that can benefit from tweaking and tweening that third plane (wrap-around carousels, card flips, etc). Frankly, [3D transforms can be its own separate tutorial](https://3dtransforms.desandro.com/3d-transform-functions), but to get the foundations you can familiarize yourself with these properties and functions:

### Properties

* `transform-style`: denotes whether or not children of an element are within a 3D space. This must be used along with the `transform` property.
  * Use `transform-style: flat` for children that are on the same plane as the parent.
  * Use `transform-style: preserve-3d` for children that are in a 3D space.
* `perspective`: sets the distance between the Z-plane and the user for all child elements. 
  * `perspective: 20rem;` would appear further away from you than `perspective: 2rem;`
* `perspective-origin`: sets the position at which the viewer is looking. Essentially this is creating a "vanishing point" fo ryour element.
  * It takes x, y, and specific position values like `transform-origin`: `perspective-origin: center`, `perspective-origin: bottom left`, `perspective-origin: 1rem 15rem`.
* `backface-visibility`: show or hide the back face of a element.
  *  `backface-visibility: visible` shows the back face.
  *  `backface-visibility: hidden` hides the back face and will render it invisible in a 2D space, or just not shown in a 3D space as other planes will be hiding it.

### Functions

* `matrix3d()`: Just like `matrix()` but with a 3rd plane, defining a transform on a 4x4 matrix (with 16 values).
* `translate3d()`: Just like `translate()` but with a 3rd plane, allowing you to reposition along the X, Y, and Z axis.
  * `transform: translate3d(-10rem, 5rem, 2rem);`
* `translateZ()`: Like `translateX()` and `translateY()`, this function takes a single value and defines the position along the Z-axis.
  * `transform: translateZ(2rem);`
* `scale3d()`: Just like `scale()` but with a 3rd plane, resizing an element along the X, Y, and Z axis.
  * `transform: scale3d(-1.5, 0.75, 0.25);`
* `scaleZ()`: Like `scaleX()` and `scaleY()`, this function takes a single value and defines the size along the Z-axis.
  * `transform: scaleZ(-1.25);`
* `rotate3d()`: Rotates an element in a 3D space. This departs from `rotate()` a bit since we're defining all the plane coordinates on a fixed axis. The function takes 4 values: an x coordinate, a y coordinate, a z coordinate, and an angle of rotation.
  * `transform: rotate3d(1, 1.5, 3, 45deg);`
* `rotateZ()`: Rotates an element on the Z-axis.
  * `transform: rotateZ(90deg);`
* `perspective()`: This function sets the distance between the Z-axis and the user. Unlike its property counterpart, this function relies on being directly applied to an element within a transform instead of its parent. Like any value of `transform`, we can chain this to other transformations:
  * `transform: perspective(2rem) rotateX(-15deg) rotateY(30deg);`

## What's next?

Next, take what you've learned here and combine CSS transforms with CSS
animations to create more complex animations and interactions - [Beginner's
Guide to CSS
Animations](https://thoughtbot.com/blog/css-animation-for-beginners).

## Work with thoughtbot design experts 

The fastest way to learn is alongside a seasoned expert. thoughtbot designers can help with your CSS project and level up your skills in the process. [Let's chat](https://thoughtbot.com/hire-us) about your project.
