skip navigation

Transforms

On this page

THE TRANSFORM METHODS ARE BEING SUPERCEDED BY translate, rotate, scale. You can also use perspective and perspective-origin

Amongst CSS Animations, transitions and transforms transforms are probably the least sexy and exciting. On their own they’re not involved with movement. Using transforms you can’t do much you can’t do with many other methods. You can move an object to somewhere else, but that can be done with CSS positioning too. You can make an object bigger or smaller and obviously that can be done using font-size, height, width etc.. You can’t rotate objects but for static uses that’s somewhat limited. And skewing has even less use.

However all these methods become absolutely vital to know when creating animations with @keyframes and transtions.

Transforms have some not obvious at first pros too. When you use transform you don’t take the element out of the normal flow of the document. Also if you use percentage units the percentage in transforms refers to the elements size. Using transform: translateX(50%) will move an element half of it’s own width to the right. This can be good if you don’t want to change the overall positioning of other elements. See Josh Coneau’s post on transforms for more.

The key difference between transforms like translate vs width or height is that a transformed item won’t take up extra space in the page. It will overlap other elements as needed, just like position: absolute;. This makes them ideal for animations where you don’t want all the contents of the page being shifted as the animations takes place.

2D Transforms

The translate() Method

Translate is simply moving and object

Button

.translate:hover {
      transform: translate(13px, 20px)
    }

Two points:

  1. Remember to use the commers. It won’t work without.
  2. The new position doesn’t move other elements in the DOM.
  3. If you just want to move along one axis you can use either translateX or translateY instead of translate.
Move along the X-axis
An example of a translate Whoooo!!

You can use translate on it's own.

    div {
      translate: 0 12px 0;
        }

It can take 1, 2 or 3 values. With one value it affect only the X axis, two is X and Y, and three is X, Y and Z axes.

The rotate() Method

Rotate

This goes a bit funny if you hit in the wrong spot. That’s because as it rotates it leaves the hover state.

.rotate:hover {
    transform: rotate(90deg);
}

You can use degrees, rotate(450deg) or turns, rotate(1.25turn) where 1 turn = 360 degrees.

The scale() Method

Scale Me

REMEMBER:

  1. Use mulitpliers, NOT percentages.
  2. You can scale the height & width independently or just use a single value for both the same value.
  3. Don’t forget the commer if scaling X and Y values separately.

I’ve added a transition of 1s here. To get this to reverse over 1s when the hover state is left you have to add the transition to the non hover state.

.scale {
    transition: 1s;
}
.scale:hover {
    transform: scale(1.5);
    transition: 1s;
}

The skewX() & skewY() Methods

Skew Me X!
Skew Me Y!

Using negative values skews in the opposite direction.

.skewX:hover {
transform: skewX(25deg);
}
.skewY:hover {
transform: skewY(-25deg);
}

Not obviously useful with this example. But below you can add a skewed background using a ::before pseudo element.

Skewing the background

See article on 9elements on diagonals for more.

The matrix() Method

This combines all of the above into one property. The order used does not seem intuitive:

  1. scaleX
  2. skewY
  3. skewX
  4. scaleY
  5. translateX
  6. translateY

transform: matrix(1, -0.3, 0, 1, 0, 0);

Transform-origin

Setting the origin can be important

.box {
  transform: rotate(360deg);
  transform-origin: top left;
}

Values can be lengths, percentages or the keywords like top left

If undefined the default is in the center or center center or 50% 50%. However for SVG the default is 0 0 so center center could be useful.

3D Transforms

3D transformations are like the 2D versions but with a third axis to manipulate, the z axis. When writing a 3D transform simply add the z axis value after the x and y values: transform: translate3d(10px, 30px, 15px). Whilse the x goes from L to R and the y axis is up and down in the 2D transformations the z axis is a line coming out of the screen towards the viewer, or receding back behing the screen. Obviously the screen is 2D and objects cannot literally come out of the screen. However the 3D transforms give the impression that they’re 3D using converging lines on a vanishing point.

These 3D transformations can be used with 2 additional properties perspective and perspective-origin. These are what give an object those converging lines.

Rotate 3D

Here’s an example of 3D rotation using: transform: perspective(100px) rotate3d(1, 0, 0, 180deg);.

Rotate X

The perspective value give the 3D effect. The higher the value the less the effect. Why is that? Because the value is a measure of how far the viewer is from the object. With a low value you're very close to the effect of perspective is much greater.

Also notice you can see the backface when the object turns around. This can turned off with the property backface-visibility: hidden;.

You can also use the perspective property on it's own. This is useful if you want to transform several objects together. Here a group of buttons are rotated in a single group. So the container is given the perspective property:

.buttongroup {
      perspective: 250px;
    }
Rotate Y
Rotate Y
Rotate Y
Rotate Y
Rotate Y

scale 3D

Scale

Translate 3D

Here’s a translate3d:

Translate!
View the CSS for this page
/* .resources > ul > li:nth-child(2) {
  padding-bottom: .7em;
  border-bottom: solid 1px;
} */

.buttonbox {
  display: inline-block;
  background: #d523b8;
  color: white;
  font-family: 'segoe ui';
  text-transform: uppercase;
  padding: 12px;
  margin-right: 2em;
}

.translate:hover {
  transform: translate(13px, 20px)
}

.translateX:hover {
  transform: translateX(290px);
  transition: 3s;
}
.translateX {
  transition: .5s;
}

.translateOverflow {
  padding: 11px;
  background: #1f72f6;
  position: relative;
  width: 150px;
}

.translateOverflow div {
  display: inline-block;
  overflow: hidden;
  height: 65px;
  width: 150px;
  color: white;
  font-family: 'Segoe UI';
  text-transform: uppercase;
  transition: .7s;
  position: absolute;
  top: 0;
  left: 0;
}

.translateOverflow div strong {
  display: block;
}

.translateOverflow:hover div {
    position: absolute;
    top: -130px;
    transition: .7s;
}
.rotate {
  transition: .6s;
}

.rotate:hover {
  transform: rotate(90deg);
}

.scale {
  transition: 1s;
}

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

.skewX,
.skewY {
  transition: .4s;
}

.skewX:hover {
  transform: skewX(25deg);
}
.skewY:hover {
  transform: skewY(-25deg);
}

.diagonal-bg {
  position: relative;
  background-color: #fff;
  display: inline-block;
  isolation: isolate;
  padding: 2em;
  overflow: hidden;
  font-weight: bold;
}
.diagonal-bg::before {
  content: '';
  position: absolute;
  inset: 0;
  transform: skewY(-10deg);
  background-color:orangered;
  z-index: -1;
}

/* ------ 3D Transforms start here ----- */

.translate3 {
  transition: .4s;
}
.translate3:hover {
  transform: translate3d(100px, 10px, 1150px);
  perspective: 100px;
  perspective-origin: bottom left;
}

/* -------- 3D Rotations ---------- */

.rotateX3 {
  transition: 2s;
}
.rotateX3:hover {
  transform: perspective(100px) rotate3d(1, 0, 0, 180deg);
}

.buttongroup {
  perspective: 250px;
  margin-top: 2.5em;
  background: #e9ede9;
  padding: 1em;
}
.buttongroup .buttonbox {
  transition: 2s;
}
.buttongroup:hover .buttonbox {
  transform: rotate3d(1, 0, 1, 360deg);
}






.scale3 {
  transition: .6s;
}
.scale3:hover {
  transform: scale3d(1, 1, 12);
}









/* --- PAGE NAVIGATION ---*/


.pagenav {
  display: flex;
}

.pagenav ul {
  margin: 0;
  padding: 0;
  list-style: none;
  margin-right: 3em;
}

.pagenav ul li:first-child {
  font-weight: bold;
  text-decoration: underline;
}




/* --- Main Nav --- 

nav li a, nav li a:link, nav li a:visited {
  display: inline-block;
  transition: 1s;
}


nav li a:hover {
  transform: scale(1.3);
  border: none;
}

/* ---- Resources nav ---- */

.resources a {
 position: relative;
 display: inline-block;
 /* outline: none; */
 color: #fff;
 text-align: center;
 text-shadow: 0 0 1px rgba(255,255,255,0.3);
}

.resources a:hover,
.resources a:focus {
 outline: none;
 border: none;
}

/* .resources a {
	line-height: 44px;
	perspective: 1000px;
} */

.resources a span {
	position: relative;
	display: inline-block;
	padding: 0 14px;
	background: tomato;   /*  --- The start colour --- */
	transition: transform 0.5s;
	transform-origin: 50% 0;
	transform-style: preserve-3d;
}

.resources a span::before {
	position: absolute;
	top: 100%;
	left: 0;
	width: 100%;
	height: 100%;
	background: #9c410a;  /* --- The tranforming colour -- */
	content: attr(data-hover);

	transition: background 0.5s;
	transform: rotateX(-90deg);
	transform-origin: 50% 0;
}

.resources a:hover span,
.resources a:focus span {
	transform: rotateX(90deg) translateY(-22px);
}

.resources a:hover span::before,
.resources a:focus span::before {
	background: #eb5b10;  /* --- The end hover colour --- */
}