Skip to content

Commit

Permalink
Snap Border and Outline Widths before Layout
Browse files Browse the repository at this point in the history
Chrome renders a 1 pixel gap
between a parent's border and a child's background,
when a sub pixel borders widths decimal value is
greater than or equal to 0.5.

This happens because
 * the parent's size gets calculated at layout time with
   the sub pixel values
 * the child's position gets calculated based on the
   parent's position and size
 * the border width gets floored at paint time to just the whole value

This leaves a 1 pixel gap between
the last pixel in the parent's border and
the first pixel in the child's background.

This behavior is a regression introduced in:
https://chromium-review.googlesource.com/c/chromium/src/+/2199140

Which changed Chrome to
"Use floor instead of round for decimal border widths"
with the intent to increase interop with Firefox and Safari
which both floor borders.

Previously Chrome was rounding the borders at Paint time,
avoiding the gaps between a parent's border and a child's background.

The proposed fix is to snap (floor) the borders widths before
layout, matching what Gecko and WebKit do.

Outline widths also use `ConvertBorderWidth` as their conversion
function and will also be snapped before layout.

CSS isses:
w3c/csswg-drafts#5210
w3c/csswg-drafts#7473

R=pdr

Change-Id: Ib32ba28e4f193ba79f90f96771378abaf0c589a8
Bug: 1120347, 1201762
  • Loading branch information
tcaptan-cr authored and chromium-wpt-export-bot committed Oct 15, 2022
1 parent d74cf76 commit b0b1f1d
Show file tree
Hide file tree
Showing 11 changed files with 485 additions and 7 deletions.
53 changes: 53 additions & 0 deletions css/css-borders/border-width-rounding.tentative.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<title>
CSS Border: width rounding
</title>

<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org">
<link rel="help" href="https://www.w3.org/TR/css-backgrounds-3/#border-width">

<meta name="assert" content="border-width computed value after rounding.">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<h1>
Test passes if border widths are rounded up
when they are greater than 0 and less than 1,
and rounded down when they are greater than 1.
</h1>

<script>
const values = [
{ input: "0px", expected: "0px" },
{ input: "0.1px", expected: "1px" },
{ input: "0.25px", expected: "1px" },
{ input: "0.5px", expected: "1px" },
{ input: "0.9px", expected: "1px" },
{ input: "1px", expected: "1px" },
{ input: "1.25px", expected: "1px" },
{ input: "1.5px", expected: "1px" },
{ input: "2px", expected: "2px" },
{ input: "2.75px", expected: "2px" },
{ input: "2.999px", expected: "2px" },
];

for (const value of values) {
const div = document.createElement("div");
div.style = `border: solid ${value.input} blue; margin-bottom: 20px;`;
document.body.appendChild(div);
}

test(function() {
var targets = document.querySelectorAll("div");

for (var i=0; i < targets.length; ++i) {
assert_equals(getComputedStyle(targets[i]).borderWidth, values[i].expected);
}
}, "Test that border widths are rounded up when they are greater than 0px but less than 1px, and rounded down when they are greater than 1px.");
</script>
</body>
</html>
44 changes: 44 additions & 0 deletions css/css-borders/reference/subpixel-border-width-ref.tentative.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<title>
CSS Border: width computed value
</title>

<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org">

<style>
.square {
height: 20px;
width: 20px;
border: 1px solid gray;
}
</style>
</head>

<body>
<h1>
Test passes if border widths are rounded up
when they are greater than 0 and less than 1,
and rounded down when they are greater than 1.
</h1>

<div class="square"></div>
<br>
<div class="square"></div>
<br>
<div class="square"></div>
<br>
<div class="square"></div>
<br>
<div class="square"></div>
<br>
<div class="square"></div>
<br>
<div class="square" style="border-width: 3px;"></div>
<br>
<div class="square" style="border-width: 3px;"></div>
<br>
<div class="square" style="border-width: 3px;"></div>
</body>
</html>
48 changes: 48 additions & 0 deletions css/css-borders/subpixel-border-width.tentative.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<title>
CSS Border: width computed value
</title>

<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org">
<link rel="help" href="https://www.w3.org/TR/css-backgrounds-3/#border-width">
<link rel="match" href="reference/subpixel-border-width-ref.tentative.html">

<meta name="assert" content="border-width computed value after rounding.">

<style>
.square {
height: 20px;
width: 20px;
border: solid gray;
}
</style>
</head>

<body>
<h1>
Test passes if border widths are rounded up
when they are greater than 0 and less than 1,
and rounded down when they are greater than 1.
</h1>

<div class="square" style="border-width: 0.3px;"></div>
<br>
<div class="square" style="border-width: 0.5px;"></div>
<br>
<div class="square" style="border-width: 0.9px;"></div>
<br>
<div class="square" style="border-width: 1.3px;"></div>
<br>
<div class="square" style="border-width: 1.5px;"></div>
<br>
<div class="square" style="border-width: 1.9px;"></div>
<br>
<div class="square" style="border-width: 3.3px;"></div>
<br>
<div class="square" style="border-width: 3.5px;"></div>
<br>
<div class="square" style="border-width: 3.9px;"></div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<!DOCTYPE html>
<html>

<head>
<title>
CSS Column-Rule: width computed value
</title>

<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org">

<style>
.columns {
column-count: 2;
column-rule: 1px solid gray;
width: 420px;
height: 50px;
}
</style>
</head>

<body>
<h1>
Test passes if column rule widths are rounded up
when they are greater than 0 and less than 1,
and rounded down when they are greater than 1.
</h1>

<div class="columns">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns" style="column-rule-width: 3px;">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns" style="column-rule-width: 3px;">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns" style="column-rule-width: 3px;">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>
</body>

</html>
94 changes: 94 additions & 0 deletions css/css-column-rule/subpixel-column-rule-width.tentative.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<!DOCTYPE html>
<html>
<head>
<title>
CSS Column-Rule: width computed value
</title>

<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org">
<link rel="help" href="https://www.w3.org/TR/css-multicol-1/#crw">
<link rel="match" href="reference/subpixel-column-rule-width-ref.tentative.html">

<meta name="assert" content="column-rule-width computed value after rounding.">

<style>
.columns {
column-count: 2;
column-rule: solid gray;
width: 420px;
height: 50px;
}
</style>
</head>

<body>
<h1>
Test passes if column rule widths are rounded up
when they are greater than 0 and less than 1,
and rounded down when they are greater than 1.
</h1>

<div class="columns" style="column-rule-width: 0.3px;">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns" style="column-rule-width: 0.5px;">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns" style="column-rule-width: 0.9px;">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns" style="column-rule-width: 1.3px;">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns" style="column-rule-width: 1.5px;">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns" style="column-rule-width: 1.9px;">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns" style="column-rule-width: 3.3px;">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns" style="column-rule-width: 3.5px;">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>

<div class="columns" style="column-rule-width: 3.9px;">
Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.
</div>
</body>
</html>
53 changes: 53 additions & 0 deletions css/css-outline/outline-width-rounding.tentative.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html>
<head>
<title>
CSS Outline: width rounding
</title>

<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org">
<link rel="help" href="https://www.w3.org/TR/css-ui-4/#outline-width">

<meta name="assert" content="outline-width computed value after rounding.">

<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<h1>
Test passes if outline widths are rounded up
when they are greater than 0 and less than 1,
and rounded down when they are greater than 1.
</h1>

<script>
const values = [
{ input: "0px", expected: "0px" },
{ input: "0.1px", expected: "1px" },
{ input: "0.25px", expected: "1px" },
{ input: "0.5px", expected: "1px" },
{ input: "0.9px", expected: "1px" },
{ input: "1px", expected: "1px" },
{ input: "1.25px", expected: "1px" },
{ input: "1.5px", expected: "1px" },
{ input: "2px", expected: "2px" },
{ input: "2.75px", expected: "2px" },
{ input: "2.999px", expected: "2px" },
];

for (const value of values) {
const div = document.createElement("div");
div.style = `outline: solid ${value.input} green; margin-bottom: 20px;`;
document.body.appendChild(div);
}

test(function() {
var targets = document.querySelectorAll("div");

for (var i=0; i < targets.length; ++i) {
assert_equals(getComputedStyle(targets[i]).outlineWidth, values[i].expected);
}
}, "Test that outline widths are rounded up when they are greater than 0px but less than 1px, and rounded down when they are greater than 1px.");
</script>
</body>
</html>
Loading

0 comments on commit b0b1f1d

Please sign in to comment.