Why is CSS matrix3d rendered faster than CSS position? - javascript

Let's say I want to to move an element from left to the right, I can achieve this by doing
transform: translate3d(200px,0,0);
/*or*/
transform: translateX(200px);
or
transform: matrix3d(x,x,x,x,x,x,x,x,x,x,x,x,200,x,x,x)
or just set left position.
Why is CSS matrix3d rendered faster than just setting a position left/top?
UPDATE:
CSS animation of top/left vs transform in slow-mo.
high performance animations on HTML5

There are 2 factors than are relevant here
1) Because left can potentially affect all the layout in your page, so it forces a recalculate of style and layout. Transforms do not need this step, the transforms do not afect the element neighbours.
see html5 - high performance animations for a better explanation
2) Because most 3d work is handled by the GPU and not by the CPU. The GPU not only can do that much faster, it also frees the CPU to handle better the rest of the work. You will see a lot of times the style
transform: translateZ(0px);
wich obviously does nothing, but that makes the broser use the GPU and accelerates the process. You could try to measure changes to left with this line added and see what the perfomance is.

Related

Can I force the browser to rasterize elements before they become visible?

Call me crazy, but I'm working on a game using vanilla DOM and TypeScript. It's not action-heavy, but there are some animations going on, which are driven from JavaScript (too complex to do in CSS).
I'm already applying the common trick of translateZ(0) (called null transform hack or less accurately silver bullet) to pull animated elements into their own rendering layer, and I'm animating nothing besides compositor-only properties (transform and opacity). This works beautifully: during the game, everything feels buttery smooth, even on older mobile devices.
The problem is during the start of the game. At that moment, about 70 individually transformed and animated elements enter the page one by one over the space of a few seconds, by animating their opacity from 0 to nonzero. This is causing visible stutter during the animation.
My guess was that Chrome is being too clever here, and will only rasterize each element at the moment it first becomes visible. A quick check with the dev tools confirms this, as there's a lot of rasterization going on even during the animation:
I would prefer to rasterize all these elements once, before the animation starts, and only then trigger the animation. But how can I force rasterization of elements that aren't yet visible, without showing a flash of them to the user?
I'd be happy with a Chrome-only approach, but cross-browser would be even better.

Scale down a webpage to 90%

When you press Ctrl+- on any browser, the page scales down to 90% of it's original size. I need to replicate that, and open my webpage at 90% of it's original by default, instead of 100% because it looks nicer at 90%.
I tried the most common approach as mentioned here, here, and here, all of which basically tell you to add this block of code in your css.
html
{
zoom: 0.9; /* Old IE only */
-moz-transform: scale(0.9);
-webkit-transform: scale(0.9);
transform: scale(0.9);
}
The problem with this is that it creates a gap on the left and the right sides, as well as a huge gap on the top, which aren't present when you manually reduce the size by doing a ctrl+-.
This is what happens when I use the above mentioned code - notice the gaps on the left, right, top.
While this is what I want - this is what happens when you do a ctrl+ - manually in your browser.
How do I go about this?
EDIT: As Jonathon said in the comments, if my page looks nicer at 90%, I should have designed it to be that way instead of having to scale down. The problem was that I'm using this default template, and I just prefer it at 90% over the full 100%.
You need to use/convert to relative units in your CSS. Either % or em or rem.
Then at the body level you can set an absolute size that results in the relative measures recalculating to what you want.
If you use em or ex exclusively:
You declare font-size: 90% for body and you'll be able to adjust on the fly.
It all comes down to the units you choose and making them relative will allow you the kind of freedom you are looking for now.
Maybe you can compensate this gaps with margin-top:-50px; for specific elements.

GSAP animations: scale vs height and width

When using GSAP to perform a transition where an element is scaled equally in both dimensions, there seems to be a choice between using scale, or both height and width.
Which is better, as in will result in a higher frame rate? Or if there are conditions on the element / other transitions / DOM / CSS / browser / processor / GPU (/anything else?) that makes one better over the other, what are these?
One of the differences in using Scale Vs Width/Height is the use of CSS but you have to keep in mind while using Scale it will resize from the center of the object, while using Width/Height it will be from top left. Unless you change the transform Origin.
One major factor is the content of the object you are resizing, if you use Scale and the object has content, it will also scale everything inside, while Width/Height will not.
From what I can understand, what scaleX and scaleY do is that they use CSS's transform in the background and generally, using transforms produces a much smoother result because of sub-pixel rendering. Also, if you add force3D: true on the same element as well, it forces it to render it on its own GPU layer hence, hardware accelerated. And that happens because it adds translate3d: (0px, 0px, 0px) onto the same element. So in my opinion, manipulating transform related properties is much better.
Although, this article by Paul Irish
talks about moving elements (i.e. moving with translate vs top and left), but I believe the same holds true in our case.
Here is a quick jsFiddle for you to play around with.

How do you move an SVG around a webpage without triggering slow redraws?

I'm using d3.js to draw a (multi)line graph (with quite a few data-points, 1600 to be exact) on an svg element.
This graph is in a container which has a transition on it.
On a certain event the container gets moved 400px to the top with a CSS3 transition which works fine in Chrome. When trying in Safari and Firefox I noticed that is was really slow. After some checks I can say with 99% certainty that the svg element gets redrawn during the transition (a lot) in Safari/Firefox (and possible other browsers, too).
Is there anyway to prevent the browser redrawing it constantly until the transition is finished? Or maybe other solutions that would make this fluent?
FYI: not drawing the chart in the SVG element makes the issue go away, so I'm certain the slowdown comes from the SVG element.
The simplified html code:
<div id="container" style="transition:margin 0.75s; -webkit-transition:margin 0.75s; ">
<svg id="simple_line" style='height:210px; width:100%;'/>
</div>
Generally speaking, using margin or any other CSS position value to make objects move around the screen is sub-optimum. Try using a transform/translation style to create the movement, which will tell the browser to use graphical optimization methods.
The idea is that a transform tells the browser to move around a block of rendered content, instead of re-calculating the whole layout. Results will still depend on the quality of the browser's implementation -- as you discovered, Chrome has good optimization either way, but this should reduce the browser-to-browser differences.

How to fast-blur in css/js?

I am having a performance issue when combining blurred images with some subpixel translate animation (I am using jQuery Transit):
filter: blur(5px);^
On mousemove, blur is recalculated to simulate Depth-of-Field.
When moving, the elements aren't moving as fluid as I would like them to be.
Demo here
Buggy movement appears when you click on a bottle in a -webkit browser
Any idea/tips how I could accelerate this?
I was thinking about pre-calculating every focus step and using opacity but this is the last solution I would use.
It looks like you're translating and scaling the images at the same time, which is causing the jumpiness. Try using translate3d -webkit-transform: translate3d(x,y,z) instead and modifying the z position instead of scaling. This should help quite a bit with performance as your animations will now be hardware accelerated.

Categories

Resources