DEV Community

Cover image for How To Use the CSS Transform Property
Brittan McGinnis
Brittan McGinnis

Posted on

How To Use the CSS Transform Property

How To Use the CSS Transform Property

I’m setting out to learn CSS animations and the transform property was the second piece on my list.
My goal of this post is to teach (so that I can better learn), the very basics of transform.
This property is super cool and was actually pretty fun to learn. I would suggest playing around with it if you are not familiar.

Basics

You should have a basic understanding of CSS and HTML prior to reading this article.

Introduction

This journey that I’m on to learn CSS animations has a super important learning element to it. I basically find and filter information pertaining to this concept. Make a list of learning comprehensions that need to be understood before I can say I “know” the thing. Do those things, be it reading articles, doing exercises, watching videos, reading books, etc. one by one. Then I play around. I have no set goal when doing this. Just to play in the most basic sense. Break stuff. Have fun. Mostly this step is to develop questions. Then research and answer my questions. Then teach. That could be a blog post, teaching a friend or just explaining in depth the concept.

During this post I may gloss over some other concepts. This post is mainly just for the CSS transform property. However, I will be using the transition property quite a bit as well. If you would like to read further on that, I have another blog post for that.

Transforms

CSS transform has 6 main property values:

  • scale
  • translate
  • rotate
  • skew
  • perspective
  • matrix

In truth it has way more, because many of those values have an X, Y and Z property. For the sake of brevity though, I will not display that entire list. If you would like to take a look, you can see it [here].

I’ll explain below what each one of the values does.

Lets play with these

Below, I’ll build 7 examples cards. Each will perform the animation that it’s named.

Starter Code

<div class="container">
  <div class="translate">
    <p>translate</p>
  </div>  
</div>
@import url(https://fonts.googleapis.com/css?family=Open+Sans);

body {
  background: lightblue;
  font-family: 'Open Sans';
}

.translate {
  margin: 50px auto;
  background: papayawhip;
  width: 150px;
  height: 150px;
  border-radius: 20px;
}

p {
  margin-top: 60px;
}

Adds hover psuedo class

This moves the element down the Y axix 100px. While kinda cool and useful depending on your use case, it is not very graceful and does not animate very nicely. Next we'll add a transition to make this animate smoothly.

// ...

.translate:hover {
  transform: translateY(100px);
}
// ...

.translate {
  // ...
  transition: 1s ease;
}

.translate:hover {
  transform: translateY(100px);
}

Scale

Add a duplicate of the previous div and name the class to the property that we will be changing.
I will not include this code for the following examples as it is the same.

<div class="container">
  <div class="translate">
    <p>translate</p>
  </div>  
  <div class="scale">
    <p>scale</p>
  </div>  
</div>

Here we'll add a text-align center to the .container so the elements will be in the center of this container.
Then we'll change the margin and display properties so they sit next to each other.

// ...
.container {
  text-align: center;
}

.translate, .scale {
  margin: 50px 10px auto;
  display: inline-block;
  background: papayawhip;
  width: 150px;
  height: 150px;
  border-radius: 20px;
  transition: 1s ease;
}

p {
  margin-top: 60px;
}

// ...

Then we'll add a scale property on hover. This will shrink it to 1/2 of it's original size. Because I only provide one value it uses that value for both the x and y coordinates.

// ...
.scale:hover {
  transform: scale(.5);
}

If I provide it a second value then it will apply the value to the x and y coordinates respectively.

// ...
.scale:hover {
  transform: scale(.5, 2);
}

Rotate

After you have duplicated the html and renamed the class and inner text for the p tag to rotate, then add the rotate class to our base styling for our divs like so:
.translate, .scale, .rotate {

Then we'll add an :active psuedo class to the .rotate class. This way when we click on that element it rotates.
The rotate value takes a turn value or a degree value.

rotate takes a negative or positive value. If you were to give this transform: rotate(-360deg) for example it would turn counter-clockwise

// ...

.rotate:active {
  transform: rotate(360deg);
}

// This accomplishes the same thing as above
.rotate:active {
  transform: rotate(1turn);
}

Skew

The skew value will 'tilt' the element to one side depending on the value given. As with many of these functions you can specify either scaleX, scaleY or scale. If you pass in only one value to scale() it will give the Y axis a 0 value which will then only scale the X axis.

The skew value also takes degree values, turns or radius as parameters. This signature looks like this: skew(10deg) or skew(-0.06turn, 18deg) or skew(.312rad). Taken from the MDN docs

Skew can be a little tricky because you may only want to skew the container of an element and not the inner content. In that case you will have to skew in reverse.

Below you can see an example of skewing the div but keeping the text inside un-skewed.

  1. We'll duplicate our html, change our class name and our inner text like so <p>skew</p>
  2. We'll add .skew to our growing list of elements targeted in our base CSS

Now we'll add a skew value to this element.

// ...

.skew:hover {
   transform: skew(10deg)
}

Problem with this is that it skews the inner text as well. We can remedy that by giving it an inverse value of the same amount and targeting that element.

.skew:hover p {
  transform: skew(-10deg);
}

This is still kind of weird looking because the text corrects itself on hover. I'm not sure if there is a more natural way to fix this. I couldn't come up with one in this contrived example. If any reader has a better way please let me know in the comments.

Perspective

The perspective value is used to give some perspective to 3d elements. You are targeting the z-index so that it looks as thought the element is popping out of the page. The point that the perspective originates from is the center. You can alter this using the perspective-origin value. I will however use the transform-origin property because I am using this on the transform property and on the perspective property.

For this example I will use both the perspective and the transform-origin values. I'll make it look as though the card is flipping up and out from the bottom.

Copy the code from the last example and add the respective class and supporting css.

Then add this to the hover state.

// ...
.perspective {
  transform-origin: top;
}

.perspective:hover {
  transform: perspective(300px) rotateX(50deg);
}

Matrix

The matrix function is a little more complex and admittedly the one that I spent the least amount of time playing with. Also it requires that you have a pretty good understanding of linear algebra and the Cartesian coordinates system (which I do not), in order to really understand what is going on.

There is both a matrix and a matrix3d function. The matrix function is behind every transform function. For example, when you are calling rotateX(30deg), you are actually saying matrix(0.86602540, 0.50000000, -0.50000000, 0.86602540, 0, 0);. There is a cool matrix calculator for rotate here, where you can see the value of your rotation.

2d transforms are a 3x3 matrix of integers where 3d transforms are a 4x4 matrix. Hence the arguments passed to each function respectively.

Big thanks to this deep dive article Understanding the CSS Transforms Matrix by Tiffany Brown.

Here I'll make this card flip up and out to the left using the matrix function.

We'll add our html and css same as with the previous cards, then you can add this :hover state to the .matrix class

// ...
.matrix:hover {
  transform: matrix(.5, -1, 0, .5, 0, 0);
}

The matrix3d can create the illusion of 3 dimensions in 2 dimensions using CSS. The signature takes 16 arguments as coordinates.

I'll copy all the stuff I just did for Matrix and just add 3d to the class name and text. Then we'll rotate this card up, right and out at the bottom using the matrix3d function. We'll do this on the :active psuedo class.

// ...
.matrix3d:active {
  transform: matrix3d(0.8535533905932737, 0.4999999999999999, 0.14644660940672619, 0, -0.4999999999999999, 0.7071067811865476, 0.4999999999999999, 0, 0.14644660940672619, -0.4999999999999999, 0.8535533905932737, 0, 22.62994231491119, -20.3223304703363, 101.3700576850888, 1);
}

Below is a pen of all these examples.

Conclusion

I would love to hear any feedback that anyone has about my understanding of the transform property. I wrote this post to re-enforce my knowledge of this concept. If I have made any glaring errors please let me know. I will gladly update this post with the correct information.

This is a Cross Post from Medium

Discussion (0)