css-triggers
css-triggers copied to clipboard
Wrong data
Hey, are you sure you have correct data for Webkit and Gecko? For example - is it true that using "transform" in webkit causes layout recalculation?
The data is correct in so far as that it reflects what the respective DevTools are showing when running the tests. Engineers from both Webkit and Gecko were just as surprised as we were, but we haven’t heard from them since.
@surma Looking into that further, transform behaves totally differently when you force to create a render layer. This happens specifically for 3d transforms (translateZ(0)
counts). Because it's so different, shouldn't there be a separate entry on the list for that case?
Speaking as a Gecko developer who works on painting, subsequent changes to transform absolutely don't cause painting in Gecko. With two exceptions: If your element is much larger than the viewport, we only paint those areas that are currently inside the viewport, so you'll see some painting as you move other areas into the viewport. The other exception is scaling: If you cross a power-of-two scaling threshold, we re-rasterize the layer contents at a different resolution.
How did you gather the data? If you see painting during transforms in cases where the exceptions I mentioned don't apply, I'd love to hear about those cases.
I'm also interested in knowing through what channel you contacted Gecko engineers.
The data came from Jordan Santell a while ago (on the old repo over on my personal account). I'm more than happy to take PRs for fixes, though from my POV if we could pull logs directly via WebDriver etc then it would remove the human element entirely. Unfortunately today we can only get the logs for Chrome, but I'd love that to change!
@mstange Help would be greatly appreciated to automate this for Gecko!
In case you haven’t seen it: The _suite
folder contains the code to generate and run the test suite.
Thanks for the pointers! I'll take a look next week.
Sorry for taking so long here. This is still on my to-do list.
I've run gogo() on suite/html/transform-change.html, and indeed, Firefox does a paint. Apparently there is a Firefox bug here due to the table elements. If I remove the table, gogo() causes no paints, and there is no paint marker in the performance recording. I need to look into it some more.
Oh, I had missed the #targetElement.active *
rule. So the test changes the transform property on the table elements themselves, not just on the container div! And yes, Firefox doesn't support cheap transform changes on table elements yet.
It's a little unfortunate that Firefox's lack of efficient transform support on table elements makes it look like it has slow transforms in general. I don't think many people set transforms on table elements.
That is very interesting info! And yes, I agree that it is unfortunate that one “edge-case” is distorting the data for Firefox.
I’ll try and come up with a different template that accommodates for this.
I'm all up for changing the data to suit here, since it's not the common case. In the meantime, while Surma does the change to the template, we can update the data to match expectations.
Thanks for taking time out to look over it :)
In fact, @Qwal can I ask if you'd mind making a PR that sets the properties to the correct values as you see them? I assume it's the same for opacity as it is for transform? I'd do it myself, but I think it's better to come from you since you know Gecko far better than we do.
@paullewis I think you wanted to ask @mstange as he's a Gecko developer. I just found it strange in the data, as from my experience CSS animations using transform are smooth both in Chrome & FF.
@Qwal Sorry, my mistake. Should. Read. More. Closely!
Thanks for your offer to change the template.
I've created a pull request to change the data for transform and opacity. There are some more properties for which we're missing Gecko data, but I don't want to test those manually right now.
@mstange
..If your element is much larger than the viewport, we only paint those areas that are currently inside the viewp...
webkit seems to behave just like that!
I ran some tests inside the devtools console, and any transformations (I tested scale and translateX) that didn't cause the element to overflow the body, didn't trigger layout.
The first transformation that leads to horizontal scrollbar = layout opertation. subsequent transformations = no layout.
The first transformation that leads to vertical scrollbar = layout opertation. subsequent transformations = no layout.
If body's overflow property is set to overflow: hidden, no layout, no matter what.
Proof
1. Serve this code as html file.
<!DOCTYPE html>
<html>
<head>
<title>Browser Rendering</title>
<style>
#subject {
width: 4px;
height: 4px;
background: blue;
opacity: .2;
transform-origin: top left;
}
</style>
</head>
<body>
<div id="subject" style="transform: scale(1) translateX(0)"></div>
</body>
</html>
2. Fire up Chrome devtools and switch to Timeline view. 3. Make sure the console is open at the same time, by hitting ESC. 4. Start recording and execute this code in the console.
var testSubject = document.querySelector("#subject");
var activeScale = 0, activeXTranslation = 0;
var update = () => {
testSubject.setAttribute('style', `transform: scale(${ activeScale }) translateX(${ activeXTranslation }%);`);
}
var increaseScaling = (factor) => {
activeScale += factor;
update();
}
var increaseTranslation = (factor) => {
activeXTranslation += factor;
update();
}
var transformWithinViewport = () => {
activeScale = 150, activeXTranslation = 70;
update();
}
var haveItRenderHorizontalScrollBars = () => {
activeScale = 200, activeXTranslation = 180;
update();
}
var haveItRenderVerticalScrollBars = () => {
activeScale = 500, activeXTranslation = 180;
update();
}
requestAnimationFrame(() => {
// Applied at frame_1, no layout
transformWithinViewport();
requestAnimationFrame(() => {
// Applied at frame_2, still within viewport so no layout
increaseScaling(50);
requestAnimationFrame( () => {
// Applied at frame_3, still within viewport so no layout
increaseTranslation(50);
requestAnimationFrame( () => {
// Applied at frame_4, beyond viewport, horizontal scrollbars required, layout triggered
haveItRenderHorizontalScrollBars();
requestAnimationFrame( () => {
// Applied at frame_5, horizonal scrollbars are ready, another layout not triggered
increaseTranslation(50);
requestAnimationFrame( () => {
// Applied at frame_6, vertical scrollbars required, layout triggered
haveItRenderVerticalScrollBars();
requestAnimationFrame( () => {
// Applied at frame_7, vertical scrollbars are ready, another layout not triggered
increaseScaling(700);
});
});
});
});
});
});
});
Now follow Step 1 to 4, but this time body overflow set to hidden, get amazed!
@paullewis Hey, so the actual behaviour for opacity
is different from what is stated in this web fundamentals article (if css-triggers got it right).
If you can confirm it is the case, I'd create an issue for the article then.