CSS Transformations
📣 Sponsor
For most of CSS history, it only manipulated things on a 2D plain. Then, a new specification came on the scene talking about how we could continue to do this, and also move into the 3d dimension, with CSS transforms.
CSS Transforms are also a better way to move items around, since they are hardware accelerated. That means your computer will use your GPU to generate the movement is noticeably better with CSS transforms.
Simple translations
Let's start simple. CSS transforms support a number of values, and one of the most useful is translation. We can translate in a number of ways:
- translateX(x) - translate along the x-axis.
- translateY(y) - translate along the y-axis.
- translateZ(z) - translate along the z-axis.
- translate3d(x, y, z) - translate along all axis collectively.
As you might expect, translates accept distance values, i.e. 1rem, 1px, 1em, etc. Let's take a look at a quick example:
div > .transformed {
transform: none;
transition: transform 0.5s ease-out;
}
div:hover > .transformed {
transform: translateX(10px) translateY(20px);
}
We can separate multiple transformations with a space in transform. Notice how I have put the hover on the parent div. Why did I do that? Well, since the p is going to be moving, if the hover was on that, then the user wouldn't be hovering over the p anymore once it'd moved! This is a good practice, to ensure consistent experience for your user.
How it looks
Comparison of transform and positioning
Just for fun, remember I said transforms and positioning used different processing? Here is a side by side example of how they compare. If you rapidly hover over this many time, you'll notice the boxes go out of sync. This is because of the difference in hardware acceleration.
This is a small change because these elements are very small and simple, but on very large objects this begins to become noticeable.
Rotations
We can also rotate items with the rotate functions. They are similar to the translation effects:
- rotateX(x) - rotate along the x-axis.
- rotateY(y) - rotate along the y-axis.
- rotateZ(z) - rotate along the z-axis.
- rotate3d(x, y, z) - rotate along all axis collectively.
For rotations, we use different units. We can use deg
, rad
or turn
, referring to degrees, radians, or number of turns, respectively.
Here is an example:
Scaling
Finally, we can scale objects with scale
. As with the previous options, we can do it along all 3 axis:
- scaleX(x) - scale along the x-axis.
- scaleY(y) - scale along the y-axis.
- scaleZ(z) - scale along the z-axis.
- scale(x, y, z) or scale(all) - scale along all axis collectively.
Scale accepts a number between more than 0. A number of 0.5 therefore would be 50% smaller than the original element, while 2 would be 2 times bigger.
A Real World Example
One of my favourite transition scale effects is the scale to show effect, or zoom to show modal effect. It looks like this in code:
<div class="modal">
I am a modal!
</div>
.modal {
transform: scale(0.001);
opacity: 0;
transition: transform 0.1s ease-out, opacity 0.1s ease-out;
pointer-events: none;
background: white;
padding: 1rem;
color: black;
box-shadow: 0 2px 20px rgba(0,0,0,0.1);
}
.modal.show {
transform: scale(1);
opacity: 1;
pointer-events: all;
}
Preserve 3D
When you are working with multiple items transformed in 3D space in a specific container, you would expect that they would maintain a single 3D space. However, that is not the case. If you do not use transform-style
, each item will retain an individual 3D space. By adding the following code to the container, you can make sure items will move through each other:
.container {
transform-style: preserve-3d;
}
Making a 3D Cube
Using a what we've covered, and preserve-3d
, we can take a look at how we can create a cube. I've also added a button which removes or adds the preserve-3d
property - so you can see how it affects the shape:
#cube-element {
width: 200px;
height: 200px;
transform-style: preserve-3d;
transform: rotateX(20deg) rotateY(10deg) rotateZ(10deg);
}
#cube-element > div {
width: 100%;
height: 100%;
background: #5f86e240;
position: absolute;
}
#cube-element .front {
background: rgb(51 67 109 / 15%);
transform: translateZ(100px);
}
.back {
transform: rotateY(180deg) translateZ(100px);
}
#cube-element .right {
background: rgb(51 67 109 / 15%);
transform: rotateY(90deg) translateZ(100px);
}
#cube-element .left {
background: rgb(51 67 109 / 45%);
transform: rotateY(-90deg) translateZ(100px);
}
#cube-element .top {
background: rgb(51 67 109 / 0%);
transform: rotateX(90deg) translateZ(100px);
}
#cube-element .bottom {
background: rgb(51 67 109 / 5%);
transform: rotateX(-90deg) translateZ(100px);
}
<div id="cube-element">
<div class="front"></div>
<div class="back"></div>
<div class="right"></div>
<div class="left"></div>
<div class="top"></div>
<div class="bottom"></div>
</div>
More Tips and Tricks for CSS
- CSS Transitions
- How to disable text selection in CSS
- Stripe-Like Smooth Transition CSS Only Menu
- Sticky Positioning with CSS
- Multi colored text in CSS
- The Quick Guide to Dark Mode
- An Interactive Guide to CSS Flex Box
- How the CSS Box Model Works
- How to do Deletion Animations with CSS
- Using Only CSS to Recreate Windows 98