commit c34dcc05d9003644c60665e3c505adc2eedbae23
parent 972e7bb6de6ca12e23a376a2146e84b94a4e5713
Author: Ane Diaz de Tuesta <anediaz@gmail.com>
Date: Wed, 15 Oct 2025 08:22:55 +0000
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
Diffstat:
1 file changed, 69 insertions(+), 0 deletions(-)
diff --git a/testing/web-platform/tests/layout-instability/attribution-rectangles-css-pixels.html b/testing/web-platform/tests/layout-instability/attribution-rectangles-css-pixels.html
@@ -0,0 +1,69 @@
+<!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>