Files
sousa-gecko/testing/web-platform/tests/layout-instability/attribution-rectangles-css-pixels.html
T
Ane Diaz de Tuesta c34dcc05d9 Bug 1993615 [wpt PR 55329] - Fix LayoutShift attribution data to use CSS pixels, a=testonly
Automatic update from web-platform-tests
Fix LayoutShift attribution data to use CSS pixels

The LayoutShift API was returning attribution data (currentRect and
prevRect) in physical pixels instead of CSS pixels. This makes the Layout
Instability API inconsistent with other layout-related APIs, which all use
CSS pixels.

With the current behavior, consumers of this API are required to manually
convert the attribution data using devicePixelRatio to make the coordinates
relative to the viewport.

Previously, on a display with device pixel ratio 2.0, a 100x100 CSS pixel
element positioned at (50, 50) would be reported as 200x200 at (100, 100)
in the attribution data. After this fix, it correctly reports as 100x100
at (50, 50) CSS pixels, matching the actual element position and size as
seen by web developers.

The layout shift scores themselves remain unaffected as they are calculated
using the impact fraction (shifted area relative to viewport) multiplied
by the distance fraction (movement distance relative to viewport dimensions).
Only the attribution data reporting to the Performance API is corrected.

Bug: 399058544
Change-Id: Ib8109c12eaf1c1a2e5648edbc39ef97111431494
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6624567
Reviewed-by: Manuel Rego <rego@igalia.com>
Reviewed-by: Michal Mocny <mmocny@chromium.org>
Commit-Queue: Manuel Rego <rego@igalia.com>
Cr-Commit-Position: refs/heads/main@{#1527545}

--

wpt-commits: 30a480fedde7c4a4b51fb7697b39d7296d3ac292
wpt-pr: 55329
2025-10-20 16:39:02 +00:00

70 lines
2.3 KiB
HTML

<!DOCTYPE html>
<title>Layout Instability: attribution rectangles pixel units</title>
<link rel="help" href="https://wicg.github.io/layout-instability/" />
<style>
body { margin: 10px; }
#shifter { position: relative; width: 100px; height: 100px; background: blue; }
</style>
<div id="shifter"></div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/util.js"></script>
<script>
strrect = r => `[${r.x},${r.y},${r.width},${r.height}]`;
promise_test(async () => {
const watcher = new ScoreWatcher;
const shifter = document.querySelector("#shifter");
// Wait for the initial render to complete.
await waitForAnimationFrames(2);
// Modify the position and size of the div.
shifter.style = "top: 60px; left: 10px; width: 200px; height: 200px";
await watcher.promise;
const sources = watcher.lastEntry.sources;
assert_equals(sources.length, 1);
const source = sources[0];
assert_equals(source.node, shifter);
// Test that attribution rectangles are in CSS pixels
assert_equals(strrect(source.previousRect), "[10,10,100,100]",
"previousRect should be in CSS pixels");
assert_equals(strrect(source.currentRect), "[20,70,200,200]",
"currentRect should be in CSS pixels");
}, "Attribution rectangles should be in CSS pixels.");
// Test fractional pixel values
promise_test(async () => {
const watcher = new ScoreWatcher;
const shifter = document.querySelector("#shifter");
// Wait for the initial render to complete.
await waitForAnimationFrames(2);
// Test with fractional CSS pixel values
shifter.style.cssText = 'position: relative; width: 100.5px; height: 75.25px; background: blue;';
await waitForAnimationFrames(2);
shifter.style.top = '10.5px';
shifter.style.left = '15.75px';
await watcher.promise;
const sources = watcher.lastEntry.sources;
assert_equals(sources.length, 1);
const source = sources[0];
assert_equals(source.node, shifter);
// Test that fractional CSS pixel values are preserved
assert_equals(source.previousRect.width, 100.5, "previousRect.width should preserve fractional CSS pixels");
assert_equals(source.previousRect.height, 75.25, "previousRect.height should preserve fractional CSS pixels");
}, "Fractional pixel values should be handled correctly.");
</script>