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?
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.
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).
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 ofpx
for all its measures. And the media query will change its basefont-size
only. Different size, no potential scaling visualization issues, same content position. :)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
Disable/Turn Off Inherited CSS3 Transitions
Combining Multiple CSS Animations into One Overall Animation
Keep Div at the Bottom of Another Div - CSS
Smooth Scrolling with Just Pure CSS
Linear Gradient in Chrome and Safari Browsers
How to Add Padding or Border to a Div and Keep Width and Height
How to Set the CSS Content Property with a Google Material Icon
Full Height Sidebar and Full Height Content, Fluid Layout
Styled Component Styles Are Disabled in Chrome Devtools
Transparent Strikethrought on Text
CSS Transition When Class Removed
Vertical Align Center Image in Fixed Size Div
Clicking Safari 5.1 Select Menu Refreshes Page
Bootstrap - Some Kind of Margin on Mobile Devices (Only Right Side)