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:
See the Pen With and Without Transition by Rachel Cope (@rachelcope) on CodePen.
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:
transition-property
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.
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
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.
See the Pen Translation Duration by Rachel Cope (@rachelcope) on CodePen.
CSS syntax example for transition-duration
div {
transition-duration: 3s;
}
Shorthand example for transition-duration
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):
See the Pen Transition-Timing by Rachel Cope (@rachelcope) on CodePen.
For more advanced timing options, you can define a custom timing function with a cubic-bezier.
CSS syntax example for transition-timing-function
div {
transition-timing-function: ease-in-out;
}
Shorthand example for transition-timing-function
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.
See the Pen Transition Delay Example by Rachel Cope (@rachelcope) on CodePen.
Shorthand example for transition-delay
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.
See the Pen Staggered transition by Elaina Natario (@enatario) on CodePen.
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.
See the Pen Transform: Scale by Rachel Cope (@rachelcope) on CodePen.
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.
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.
See the Pen Zoom image on hover by Elaina Natario (@enatario) on CodePen.
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.
See the Pen Transform Rotate Example by Rachel Cope (@rachelcope) on CodePen.
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
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.
See the Pen Transform: Translate by Rachel Cope (@rachelcope) on CodePen.
CSS syntax example for translate
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.
See the Pen Transform: Skew by Rachel Cope (@rachelcope) on CodePen.
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
div {
transform: skewX(25deg);
transform: skewY(10deg);
transform: skew(25deg, 10deg);
}
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.
See the Pen Transform Origin Example by Rachel Cope (@rachelcope) on CodePen.
Make sure to add the transform-origin property to the parent element, not with the transform property in the hover selector.
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.
div {
transform: rotate(90deg) scale(2) translateY(-50%) translateX(50%);
}
See the Pen Combining Transforms by Rachel Cope (@rachelcope) on CodePen.
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.
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.
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. Much like light/dark mode, this query takes a user preference setting on their device into account and applies styles that match those queries.
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).
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, 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 thetransform
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.
- Use
perspective
: sets the distance between the Z-plane and the user for all child elements.perspective: 20rem;
would appear further away from you thanperspective: 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
.
- It takes x, y, and specific position values like
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 likematrix()
but with a 3rd plane, defining a transform on a 4x4 matrix (with 16 values).translate3d()
: Just liketranslate()
but with a 3rd plane, allowing you to reposition along the X, Y, and Z axis.transform: translate3d(-10rem, 5rem, 2rem);
translateZ()
: LiketranslateX()
andtranslateY()
, this function takes a single value and defines the position along the Z-axis.transform: translateZ(2rem);
scale3d()
: Just likescale()
but with a 3rd plane, resizing an element along the X, Y, and Z axis.transform: scale3d(-1.5, 0.75, 0.25);
scaleZ()
: LikescaleX()
andscaleY()
, 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 fromrotate()
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 oftransform
, 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.
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 about your project.