Commit e1e1bb4a authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Chromium LUCI CQ

Ignore layout shift under opacity:0

Bug: 1152869
Change-Id: Ie68a761a3cd2a81dcdd3de6d2469d64146c3f596
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2591907
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarSteve Kobes <skobes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#837687}
parent 447676f6
......@@ -11,6 +11,9 @@ shift. Now we also consider the previous visibility and ignore layout shift in
the case.
[Source code for this change](https://chromium-review.googlesource.com/c/chromium/src/+/2591367)
### Ignore layout shift under opacity:0
[Source code for this change](https://chromium-review.googlesource.com/c/chromium/src/+/2591907)
## How does this affect a site's metrics?
All of these changes only affect sites with specific types of content. Here are
......@@ -21,6 +24,11 @@ the specifics for each change:
Sites using visibility:hidden to hide layout changes may see a decrease in
their Cumulative Layout Shift scores.
### Ignore layout shift under opacity:0
Sites using opacity:0 to hide layout changes should see a decrease in their
Cumulative Layout Shift scores.
## When were users affected?
Chrome 89 is currently scheduled to be released the week of March 2, 2021.
......@@ -4,6 +4,7 @@ This is a list of changes to [Cumulative Layout Shift](https://web.dev/cls).
* Chrome 89
* Metric definition improvement: [Ignore layout shift when visibility:hidden becomes visible](2020_12_cls.md)
* Metric definition improvement: [Ignore layout shift under opacity:0](2020_12_cls.md)
* Chrome 88
* Metric definition improvement: [Cumulative layout shift properly detects shifts of fixed position elements](2020_11_cls.md)
* Metric definition improvement: [Cumulative layout shift properly detects shifts of descendents of a sticky element](2020_11_cls.md)
......
......@@ -176,6 +176,11 @@ void PaintInvalidator::UpdateLayoutShiftTracking(
if (!object.ShouldCheckGeometryForPaintInvalidation())
return;
if (tree_builder_context.this_or_ancestor_opacity_is_zero) {
object.GetMutableForPainting().SetShouldSkipNextLayoutShiftTracking(true);
return;
}
auto& layout_shift_tracker = object.GetFrameView()->GetLayoutShiftTracker();
if (!layout_shift_tracker.NeedsToTrack(object)) {
object.GetMutableForPainting().SetShouldSkipNextLayoutShiftTracking(true);
......
......@@ -1295,8 +1295,9 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
}
}
if (properties_->Effect()) {
context_.current_effect = properties_->Effect();
if (const auto* effect = properties_->Effect()) {
context_.current_effect = effect;
context_.this_or_ancestor_opacity_is_zero |= effect->Opacity() == 0;
if (properties_->MaskClip()) {
context_.current.clip = context_.absolute_position.clip =
context_.fixed_position.clip = properties_->MaskClip();
......
......@@ -129,6 +129,7 @@ struct PaintPropertyTreeBuilderFragmentContext {
// Therefore, we don't need extra bookkeeping for effect nodes and can
// generate the effect tree from a DOM-order traversal.
const EffectPaintPropertyNodeOrAlias* current_effect;
bool this_or_ancestor_opacity_is_zero = false;
// If the object is a flow thread, this records the clip rect for this
// fragment.
......
<!DOCTYPE html>
<title>Layout Instability: opacity:0</title>
<link rel="help" href="https://wicg.github.io/layout-instability/" />
<div id="target" style="position: absolute; top: 0; width: 200px; height: 200px; opacity: 0"></div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/util.js"></script>
<script>
promise_test(async () => {
const watcher = new ScoreWatcher;
// Wait for the initial render to complete.
await waitForAnimationFrames(2);
// Shift target, for which no shift should be reported because it's not visible.
target.style.top = '200px';
target.style.opacity = 0.9;
await waitForAnimationFrames(2);
assert_equals(watcher.score, 0);
// Shift again, for which shift should be reported.
target.style.top = '300px';
await watcher.promise;
const expectedScore = computeExpectedScore(200 * (200 + 100), 100);
assert_equals(watcher.score, expectedScore);
}, 'opacity:0');
</script>
<!DOCTYPE html>
<title>Layout Instability: opacity:0</title>
<link rel="help" href="https://wicg.github.io/layout-instability/" />
<div id="target" style="position: absolute; top: 0; width: 400px; height: 400px; opacity: 0">
<div id="child" style="position: relative; top: 0; width: 200px; height: 200px; opacity: 0.5"></div>
</div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/util.js"></script>
<script>
promise_test(async () => {
const watcher = new ScoreWatcher;
// Wait for the initial render to complete.
await waitForAnimationFrames(2);
// Shift target, for which no shift should be reported because it's not visible.
target.style.top = '200px';
await waitForAnimationFrames(2);
assert_equals(watcher.score, 0);
// Shift child, for which no shift should be reported, either.
child.style.top = '100px';
await waitForAnimationFrames(2);
assert_equals(watcher.score, 0);
}, 'opacity:0');
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment