What Does the Scalez() CSS Transform Function Do

What does the scaleZ() CSS transform function do?

Seems silly to answer a question two years after it was asked, but posting it for posterity.

It has to do with transform matrices and matrix-vector multiplication. Basically, the transform won't appear to work unless the math works out to produce a product where the Z coordinate is greater than zero.

This is easy to explain, but a little bit hard to understand if you don't have the math background. (But a weekend's worth of WikiPedia reading and Google searches will teach you enough. That's how I learned it.) Every transform function, except matrix() and matrix3d() have an equivalent matrix value. For scale3d, the matrix is:

[sx 0 0 0]
[0 sy 0 0]
[0 0 sz 0]
[0 0 0 1]

Where sx, sy, and sz are the factor for scaling about the x, y, and z axes. For scaleZ, it's the same, but sx and sy are both 1.

When you apply a transform, the browser takes the coordinates for each vertex of the object (in non-nerd speak: takes the coordinates for each box corner) and multiplies it by the transform matrix. The product of this becomes the new coordinates for the object. For example the math of transform: scaleZ(3) on an object starting at (100,50,0) looks a little like this:

[1 0 0 0]   [100]   [100]
[0 1 0 0] * [ 50] = [ 50]
[0 0 3 0] [ 0] [ 0]
[0 0 0 1] [ 1] [ 1]

That product, [100 50 0 1] when translated into a 3D coordinate system becomes what we started with: (100,50,0). The result is that it looks like the transform wasn't applied. In order for a transform using scaleZ() to have an effect, the third number in the product of the matrix and vector must be greater than zero. It usually happens when scaleZ() or scale3d() are applied to the parent element, or used in combination with another transform function. In both cases cumulative/current transform matrix results in a Z coordinate whose value is greater than zero. Here's an example using transform: rotateY(30deg) scaleZ(3). First we need to multiply the matrix for rotateY(30deg) by the matrix for scaleZ(3).

[0.866 0 -0.499 0]   [1 0 0 0]   [0.866 0 -1.497 0]
[0 1 0 0] * [0 1 0 0] = [0 1 0 0]
[0.499 0 0.866 0] [0 0 3 0] [0.499 0 2.598 0]
[0 0 0 1] [0 0 0 1] [0 0 0 0]

Then we can multiply our matrix product (that bit to the right of the equal sign) by our point at (100,50,0).

[0.866  0 -1.497  0]   [100]   [86.6]
[0 1 0 0] * [ 50] = [50 ]
[0.499 0 2.598 0] [ 0] [49.9]
[0 0 0 1] [ 1] [ 1 ]

Our product [86.6 50 49.9 1] works out to coordinates of (87, 50, 50) if we round off to whole numbers. And that second 50 is our Z coordinate. The transform has a noticeable effect.

CSS - Independent Translate and Scale functions?

According to CSS documentation here:

The translate, rotate, and scale properties allow authors to specify simple transforms independently, in a way that maps to typical user interface usage, rather than having to remember the order in transform that keeps the actions of translate(), rotate() and scale() independent and acting in screen coordinates.

So when you use transform and applies several transform functions (such as translate, scale or rotate), the functions order will effect the visual (which is hard to remember how each function effects the others).

When you use individual transforms you don't have to deal with it and the order doesn't matters.

Why does this calc() function not work in transform scale?

You have two issues. The first one is about the formula without scale:

calc(0.75 + (0.3 - 0.75) * ((100vw - 320px) / (780 - 320)))

This is invalid because you are adding a number (0.75) with a length ((0.3 - 0.75) * ((100vw - 320px) / (780 - 320)))

At + or -, check that both sides have the same type, or that one side is a <number> and the other is an <integer>. If both sides are the same type, resolve to that type. If one side is a <number> and the other is an <integer>, resolve to .ref

The second issue, is that scale only take a number so you need to correct the formula to transform the second part into a number by removing any kind of unit (vw,px,etc).

Basically, what you want to do cannot be done this way because you have no way to convert your (100vw - 320px) to a number unless you consider using some JS as this is beyond CSS. Even with JS you will need to define what is the logic behind transforming a pixel number to non-pixel number.


Using the same formula within right and with percentage will work fine because:

If percentages are accepted in the context in which the expression is placed, and they are defined to be relative to another type besides <number>, a <percentage-token> is treated as that type. For example, in the width property, percentages have the <length> type. A percentage only has the <percentage> type if in that context <percentage> values are not used-value compatible with any other type. If percentages are not normally allowed in place of the calc(), then a calc() expression containing percentages is invalid in that context.ref

So in this case percentage is allowed to be used with right because we can resolve it thus the forumla will be valid because at the end it will be something like A% + Bpx.

Javascript style.transform = scale(x,y) animation not working

You should use CSS transitions.
Style your button like so:

#btn {
transition: transform 0.1s
}

That code will make the button transition during 0.1 seconds whenever the transform property is changed, for example the scale.

Then, from your JavaScript code, you juste have to assign the transform style once, and CSS will transition automatically.

x = document.getElementById("btn");

x.onclick = function() {
x.style.transform = 'scale(2,2)'; // or any x and y value
}

x = document.getElementById("btn");

x.onclick = function() {
x.style.transform = 'scale(2,2)'; // or any x and y value
}
#btn {
transition: transform 0.1s
}
<button id="btn">button</button>

Is transform: scale(x) a costly operation?


  1. Is transform: scale(x) a costly operation?

No, the transform operation doesn't require a DOM update. A browser makes a rendering update. Its pros are its performance costs are low, it works fast. Its cons are scaling could greatly downgrade its visual quality (for example, blur images), the downscaled component with its content could be hard to use or read.


  1. A JS usage to set CSS is definitely a costly way to make changes. The most efficient way is to use CSS only (media query).

  2. It looks weird to 'scale' a component for a small screen. A common way to solve it now is to make a responsive layout. But think, you don't need to let its content be dynamic inside. Such a task could be solved with CSS. Just make another step forward. Tie the inner content with outer sizes at CSS - use em/rem units instead of px for all its measures. And the media query will change its base font-size only. Different size, no potential scaling visualization issues, same content position. :)

  3. The CSS could be like this below. Sorry, a minimal working HTML, CSS, JS to demonstrate the concept. To check JS in different screen sizes in this snippet - change your screen size, refresh the snippet. The CSS option works without a refresh.

function setSizeJs() {
const element = document.getElementById('target-element-px');
element.style.transform = window.innerWidth < 600 ? 'scale(.7)' : 'scale(1)';
}
.parent {
font-size: 14px;
}

#target-element-px {
/* original width */
width: 200px;
/* colorize element to show its size */
background-color: green;
}

#target-element-em {
/* main style, will be applied always */
/* an equivalent of 'width 200px' in EMs, where EM is taken as '14px' from the 'parent' class */
width: 14.28571428571429em;
background-color: grey;
}

@media screen and (max-width: 600px) {
/* additional style, will be applied only when the screen size will be less than 600px */
/* it will overwrite the main style */
#target-element-em {
font-size: 0.7em;
}
}
<div class="parent">
<div id="target-element-px" class="target-element" onload="setSizeJs">
Some content for original 200px width
</div>

<div id="target-element-em" class="target-element">
Some content for original 200px width
</div>
</div>

Does anybody know why my transform scale css isnt working?

You need to add a display property to your button:

.btn-s,
.btn-e { display: inline-block; }

http://jsfiddle.net/5dhjLm80/

var btnE = document.querySelector(".btn-e");btnE.addEventListener('mouseover', function() {    btnE.classList.add("btn-eScript")})btnE.addEventListener("transitionend", function() {    btnE.classList.remove("btn-eScript")})
.btn-e {    margin-left: 155px;    background-color: rgba(83,155,232,0.9);   }
.btn-s { margin-left: 120px; background-color: rgb(236, 130, 139);
}
.btn-s,.btn-e { text-decoration: none; color: white; font-size: 90%; font-weight: 100; text-align: center; padding: 10px 20px; border-radius: 25px; transition: 0.15s; display: inline-block;}
.btn-eScript { color: blue; transform: scale(1.5);}
<div class="btns">                <a class="btn-s" href="#">Más demos</a>                <a class="btn-e" href="#">Más demos</a>            </div>


Related Topics



Leave a reply



Submit