Css3 Transform Order Matters: Rightmost Operation First

CSS3 transform order matters: rightmost operation first

Yes, the first operation done is the one the most on the right., i.e. here operation2 is done before operation1.

This MDN article states indeed:

The transform functions are multiplied in order from left to right, meaning that composite transforms are effectively applied in order from right to left.

Here is the documentation : http://www.w3.org/TR/css-transforms-1/.


Example 1

Here the scaling is done first, and then the translation of 100px vertically (if translation was done first, the scaling would make the translation of 500px!)

#container {    position: absolute;    transform: translate(0,100px) scale(5);    transform-origin: 0 0; }
<div id="container"><img src="https://i.stack.imgur.com/xb47Y.jpg"></img></div>

when an html element is translated then rotated it moves diagonally

It happens because the transforms take place in the order you write them.

It also provides better transform management because you might want to either

  • translate 200px to bottom and then rotate (in place, so you'll know the element does not go sideways):

    transform: translateY(200px) rotate(-15deg);
  • rotate and then translate 200px in the direction of the rotation:

    transform: rotate(-15deg) translateY(200px);

You can also imagine rotate rotating the XoY axis.

The translation written ahead of rotate (actually any previous operations) will take place within the normal axis setup.

The translation written after the rotate will take place within the rotated axis setup.

CSS3 2D Transform Module: multiple functions: order of function application in noncommutative case

The functions in the function list are applied right-to-left.

This can be seen by looking at the browser output for the following code snippet I put together:

I wanted to investigate whether the listed functions are composed right-to-left or left-to-right,
so I tested things out with the following page:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Example Code</title>
<meta name="description" content="Example Code" />
<meta name="author" content="John Doe" />
<style type="text/css">
* {
border: 0;
margin: 0;
padding: 0;
}
#container {
width: 200px;
height: 400px;
background-color: purple;
}
.box {
padding: 50px;
width: 100px;
height: 100px;
background-clip: content-box;
background-color: yellow;
transform-origin: 50px 50px;
}
.box.one:hover {
transform: translateX(100px) skewY(30deg);
}
.box.two:hover {
transform: skewY(30deg) translateX(100px);
}
</style>
</head>
<body>
<div id="container">
<div class="box one">
HELLO
</div>
<div class="box two">
WORLD
</div>
</div>
</body>
</html>

In these case the translateX and skewY transformations do not commute (i.e. order matters).
What I found, and this information seems to be lacking in the book, is that to derive the
transformed picture, you first need to apply the transformation on the right (e.g. skewY
for box one) and then apply each transformation to its left in turn (e.g. translateX
for box one). In each case the operation is computed with respect to the origin which
I have set to be the upper left hand corner of the yellow rectangle.

What I found about the order of application of transformations in the transformation list
is consistent with what I found on the CSS3 spec (and with other computer graphics systems
such as OpenGL/WebGL):

http://www.w3.org/TR/css3-transforms/#propdef-transform

The final transformation value for a coordinate system is obtained by
converting each function in the list to its corresponding matrix like
defined in Mathematical Description of Transform Functions, then
multiplying the matrices.

Rotate and translate

The reason is because you are using the transform property twice. Due to CSS rules with the cascade, the last declaration wins if they have the same specificity. As both transform declarations are in the same rule set, this is the case.

What it is doing is this:

  1. rotate the text 90 degrees. Ok.
  2. translate 50% by 50%. Ok, this is same property as step one, so do this step and ignore step 1.

See http://jsfiddle.net/Lx76Y/ and open it in the debugger to see the first declaration overwritten

As the translate is overwriting the rotate, you have to combine them in the same declaration instead: http://jsfiddle.net/Lx76Y/1/

To do this you use a space separated list of transforms:

#rotatedtext {
transform-origin: left;
transform: translate(50%, 50%) rotate(90deg) ;
}

Remember that they are specified in a chain, so the translate is applied first, then the rotate after that.

CSS Transform - Rotate & Skew doesn't work together

As I explained in another answer (Simulating transform-origin using translate). The multiplication is done from left to right but the visual effect is from right to left:

.test { width: 192px; height: 144px; transform:rotate(25deg)  skewX(-40deg) ; display: block; background-color: red; top:50px; left:50px; position:absolute;}
<div class="test"></div>

Getting unintended movement in CSS animation

The order of the transforms in the keyframes actually matter, refer to CSS3 transform order matters: rightmost operation first

If you do this for all keyframes, changing

@keyframes outleft {
0%{transform: translateX(-10%) rotate(-15deg);}
100%{transform: translateX(0%) rotate(0deg);}
}

to

@keyframes outleft {
0%{transform: rotate(-15deg) translateX(-10%);}
100%{transform: rotate(0deg) translateX(0%);}
}

will work.

Zooming on a point with CSS3 transform scale

One thing to watch out for when using transforms is the order that you apply them. You'll find your example works rather differently if you switch the scale and the translate around.

Here is an interesting article on the matter:

https://staff.washington.edu/fmf/2011/07/15/css3-transform-attribute-order/

I wasn't able to repair your version, mainly because it misbehaves unexpectedly when you switch the order of the transforms. Basically it seems you are running into odd behaviour because the scale itself causes an automatic translation in position, and then you also translate... and it seems these different translations are occurring at a slightly different pace.

I did however re-implement a version that works, and allows you to translate before scaling. Keeping the transforms in this order seems to avoid the issue.

http://jsfiddle.net/fxpc5rao/32/

I've modified the version below to use translate3D just because it performs better for many systems.

var current = {x: 0, y: 0, zoom: 1},    con = document.getElementById('container');    window.onclick = function(e) {    var coef = e.shiftKey || e.ctrlKey ? 0.5 : 2,        oz = current.zoom,        nz = current.zoom * coef,        /// offset of container        ox = 20,        oy = 20,        /// mouse cords        mx = e.clientX - ox,        my = e.clientY - oy,        /// calculate click at current zoom        ix = (mx - current.x) / oz,        iy = (my - current.y) / oz,        /// calculate click at new zoom        nx = ix * nz,        ny = iy * nz,        /// move to the difference        /// make sure we take mouse pointer offset into account!        cx = mx - nx,        cy = my - ny    ;    // update current    current.zoom = nz;    current.x = cx;    current.y = cy;    /// make sure we translate before scale!    con.style.transform        = 'translate3D('+cx+'px, '+cy+'px,0) '        + 'scale('+nz+')'    ;};
#container {    position: absolute;    left: 20px;    top: 20px;    width: 100%;    height: 100%;    transform-origin: 0 0 0;    transition: transform 0.3s;    transition-timing-function: ease-in-out;    transform: translate3D(0,0,0) scale(1);}
#item { position: absolute;}
<div id="container">    <div id="item">        <img src="http://fadili.users.greyc.fr/demos/WaveRestore/EMInpaint/parrot_original.png" />    </div></div>


Related Topics



Leave a reply



Submit