Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css2?] Define when border rounding happens, and to which properties it applies #5210

Closed
emilio opened this issue Jun 14, 2020 · 13 comments
Closed

Comments

@emilio
Copy link
Collaborator

emilio commented Jun 14, 2020

See https://crisal.io/words/2020/06/13/rounding-borders.html

At least the rounding up to device pixels happens consistently at computed value time:

Shipping Gecko and WebKit (my post was wrong, Blink and WebKit diverge, will fix) also floor to dev pixels at computed value time. Blink floors at rendering time, which I think is more unfortunate.

@emilio
Copy link
Collaborator Author

emilio commented Jun 14, 2020

Did some digging and Blink behavior is inherited from WebKit, but WebKit changed it to match Gecko in https://bugs.webkit.org/show_bug.cgi?id=156121.

@emilio
Copy link
Collaborator Author

emilio commented Jun 14, 2020

cc @mrego who was touching border rounding in Blink recently.

@gsnedders gsnedders added the css-backgrounds-3 Current Work label Jul 9, 2020
@gsnedders
Copy link
Contributor

On the whole this ties into the larger issue as to whether we should define rounding behaviour in CSS, which… we appear not to have an issue for?

@graouts
Copy link
Contributor

graouts commented Mar 8, 2021

I came across this trying to fix css-backgrounds/animations/border-width-interpolation.html for WebKit. This test should be changed to not test values where this behavior is somewhat undefined, filed WPT issue #27934.

graouts added a commit to graouts/wpt that referenced this issue Mar 8, 2021
… open discussion (see w3c/csswg-drafts#5210). This test should not be about testing that behavior but rather whether values are interpolated correctly when "initial" or "unset" is used as a "from" value. To do this we change the "to" value to always have integer values at the tested offsets.
graouts added a commit to web-platform-tests/wpt that referenced this issue Mar 8, 2021
How border-width values should be rounded in the computed style is an open discussion, per [csswg-drafts issue #5120](w3c/csswg-drafts#5210). This test should not be about testing that behavior but rather whether values are interpolated correctly when `initial` or `unset` is used as a "from" value. To do this we change the "to" value to always have integer values at the tested offsets.
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Mar 19, 2021
…oes not yield float values, a=testonly

Automatic update from web-platform-tests
Ensure border-width interpolation test does not yield float values

How border-width values should be rounded in the computed style is an open discussion, per [csswg-drafts issue #5120](w3c/csswg-drafts#5210). This test should not be about testing that behavior but rather whether values are interpolated correctly when `initial` or `unset` is used as a "from" value. To do this we change the "to" value to always have integer values at the tested offsets.
--

wpt-commits: 7e343597a6abe5601ebd686ba34ffba3dc95d3cf
wpt-pr: 27934
@wangxianzhu
Copy link

Did some digging and Blink behavior is inherited from WebKit, but WebKit changed it to match Gecko in https://bugs.webkit.org/show_bug.cgi?id=156121.

Blink diverged from WebKit more after https://codereview.chromium.org/2640143005 (support subpixel layout of borders, April 2017).

Browser: Rounding in layout / Rounding in computed style:
Firefox: Yes / Yes
WebKit before April 2016: Yes / No
WebKit after April 2016: Yes / Yes
Blink before April 2017: Yes / No
Blink after April 2017: No / No
Possible future Blink change: Yes / Yes

@progers
Copy link
Contributor

progers commented Sep 29, 2022

Chromium is attempting to unify on the behavior used by Gecko and WebKit:
blink-dev intent-to-ship: https://groups.google.com/a/chromium.org/g/blink-dev/c/0uq_S5p6uZg/m/ReHlihKaAwAJ
chromium bug: https://crbug.com/1201762

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 13, 2022
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
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 13, 2022
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
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 14, 2022
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
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 14, 2022
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
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 15, 2022
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
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 15, 2022
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
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 15, 2022
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
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 17, 2022
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

This CL is also reverting the subpixel border width behavior of
https://codereview.chromium.org/2640143005

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.

While Column-Rule widths were already snapped before layout by
`StyleBuilderConverter::ConvertLineWidth`,
with this CL they will also use
`StyleBuilderConverter::ConvertBorderWidth`
in order to unify the snapping of widths behavior and code paths.

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

R=pdr

Change-Id: Ib32ba28e4f193ba79f90f96771378abaf0c589a8
Bug: 1120347, 1201762
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 18, 2022
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

This CL is also reverting the subpixel border width behavior of
https://codereview.chromium.org/2640143005

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.

While Column-Rule widths were already snapped before layout by
`StyleBuilderConverter::ConvertLineWidth`,
with this CL they will also use
`StyleBuilderConverter::ConvertBorderWidth`
in order to unify the snapping of widths behavior and code paths.

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

R=pdr

Change-Id: Ib32ba28e4f193ba79f90f96771378abaf0c589a8
Bug: 1120347, 1201762
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 18, 2022
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

This CL is also reverting the subpixel border width behavior of
https://codereview.chromium.org/2640143005

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.

While Column-Rule widths were already snapped before layout by
`StyleBuilderConverter::ConvertLineWidth`,
with this CL they will also use
`StyleBuilderConverter::ConvertBorderWidth`
in order to unify the snapping of widths behavior and code paths.

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

R=pdr

Change-Id: Ib32ba28e4f193ba79f90f96771378abaf0c589a8
Bug: 1120347, 1201762
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 18, 2022
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

This CL is also reverting the subpixel border width behavior of
https://codereview.chromium.org/2640143005

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.

While Column-Rule widths were already snapped before layout by
`StyleBuilderConverter::ConvertLineWidth`,
with this CL they will also use
`StyleBuilderConverter::ConvertBorderWidth`
in order to unify the snapping of widths behavior and code paths.

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

R=pdr

Change-Id: Ib32ba28e4f193ba79f90f96771378abaf0c589a8
Bug: 1120347, 1201762
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 18, 2022
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

This CL is also reverting the subpixel border width behavior of
https://codereview.chromium.org/2640143005

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.

While Column-Rule widths were already snapped before layout by
`StyleBuilderConverter::ConvertLineWidth`,
with this CL they will also use
`StyleBuilderConverter::ConvertBorderWidth`
in order to unify the snapping of widths behavior and code paths.

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

R=pdr

Change-Id: Ib32ba28e4f193ba79f90f96771378abaf0c589a8
Bug: 1120347, 1201762
aarongable pushed a commit to chromium/chromium that referenced this issue Oct 18, 2022
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

This CL is also reverting the subpixel border width behavior of
https://codereview.chromium.org/2640143005

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.

While Column-Rule widths were already snapped before layout by
`StyleBuilderConverter::ConvertLineWidth`,
with this CL they will also use
`StyleBuilderConverter::ConvertBorderWidth`
in order to unify the snapping of widths behavior and code paths.

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

R=pdr

Change-Id: Ib32ba28e4f193ba79f90f96771378abaf0c589a8
Bug: 1120347, 1201762
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3717365
Reviewed-by: David Baron <dbaron@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Commit-Queue: Traian Captan <tcaptan@chromium.org>
Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
Owners-Override: Philip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1060652}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 18, 2022
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

This CL is also reverting the subpixel border width behavior of
https://codereview.chromium.org/2640143005

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.

While Column-Rule widths were already snapped before layout by
`StyleBuilderConverter::ConvertLineWidth`,
with this CL they will also use
`StyleBuilderConverter::ConvertBorderWidth`
in order to unify the snapping of widths behavior and code paths.

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

R=pdr

Change-Id: Ib32ba28e4f193ba79f90f96771378abaf0c589a8
Bug: 1120347, 1201762
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3717365
Reviewed-by: David Baron <dbaron@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Commit-Queue: Traian Captan <tcaptan@chromium.org>
Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
Owners-Override: Philip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1060652}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Oct 18, 2022
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

This CL is also reverting the subpixel border width behavior of
https://codereview.chromium.org/2640143005

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.

While Column-Rule widths were already snapped before layout by
`StyleBuilderConverter::ConvertLineWidth`,
with this CL they will also use
`StyleBuilderConverter::ConvertBorderWidth`
in order to unify the snapping of widths behavior and code paths.

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

R=pdr

Change-Id: Ib32ba28e4f193ba79f90f96771378abaf0c589a8
Bug: 1120347, 1201762
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3717365
Reviewed-by: David Baron <dbaron@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Commit-Queue: Traian Captan <tcaptan@chromium.org>
Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
Owners-Override: Philip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1060652}
@tcaptan-cr
Copy link
Contributor

The Chromium change that unifies the behavior with Gecko and WebKit is now complete, and we could update the spec to define the border-width rounding at computed value time.

A proposed wording for the spec definition could be:

The border-width length should be snapped to the nearest device pixel at computed value time
based on the following rounding formula:
  If the border-width length is greater than 0 device px and less than 1 device px
  it should be rounded up to 1 device px.

  If the border-width length is greater than 1 device px
  it should be floored down to the nearest device pixel.

The clarification of the rounding behavior has also been discussed in issue 2114

moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Oct 26, 2022
…dths before Layout, a=testonly

Automatic update from web-platform-tests
Snap Border, Outline, and Column-Rule Widths before Layout

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

This CL is also reverting the subpixel border width behavior of
https://codereview.chromium.org/2640143005

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.

While Column-Rule widths were already snapped before layout by
`StyleBuilderConverter::ConvertLineWidth`,
with this CL they will also use
`StyleBuilderConverter::ConvertBorderWidth`
in order to unify the snapping of widths behavior and code paths.

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

R=pdr

Change-Id: Ib32ba28e4f193ba79f90f96771378abaf0c589a8
Bug: 1120347, 1201762
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3717365
Reviewed-by: David Baron <dbaron@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Commit-Queue: Traian Captan <tcaptan@chromium.org>
Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
Owners-Override: Philip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1060652}

--

wpt-commits: 250c39d10718c061fa6640eeb6d64b66e0968681
wpt-pr: 36189
@dbaron
Copy link
Member

dbaron commented Oct 27, 2022

A few thoughts on a spec definition for this:

Given that it applies to multiple properties (I think border-*-width, outline-width, and column-rule-width), you want to have a definition in one place that can be referenced by the definitions of all three properties. So I'd suggest something like:

To snap a length as a border width means to convert that length (presumed to already be nonnegative) as follows:

  • if the length is greater than 0 and less than 1 device pixel, it should be rounded up to 1 device pixel;
  • if the length is greater than 1 device pixel, it should be rounded down to the nearest integer number of device pixels.

Given a definition like that, the "Computed value" lines could then say something like "absolute length, snapped as a border width" where "snapped as a border width" links to the above definition.

@dbaron dbaron added the Agenda+ label Oct 27, 2022
jamienicol pushed a commit to jamienicol/gecko that referenced this issue Oct 31, 2022
…dths before Layout, a=testonly

Automatic update from web-platform-tests
Snap Border, Outline, and Column-Rule Widths before Layout

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

This CL is also reverting the subpixel border width behavior of
https://codereview.chromium.org/2640143005

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.

While Column-Rule widths were already snapped before layout by
`StyleBuilderConverter::ConvertLineWidth`,
with this CL they will also use
`StyleBuilderConverter::ConvertBorderWidth`
in order to unify the snapping of widths behavior and code paths.

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

R=pdr

Change-Id: Ib32ba28e4f193ba79f90f96771378abaf0c589a8
Bug: 1120347, 1201762
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3717365
Reviewed-by: David Baron <dbaron@chromium.org>
Reviewed-by: Philip Rogers <pdr@chromium.org>
Commit-Queue: Traian Captan <tcaptan@chromium.org>
Reviewed-by: Xianzhu Wang <wangxianzhu@chromium.org>
Owners-Override: Philip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1060652}

--

wpt-commits: 250c39d10718c061fa6640eeb6d64b66e0968681
wpt-pr: 36189
@atanassov atanassov added this to Agenda+ in November 30 2022 Nov 16, 2022
@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css2?] Define when border rounding happens, and to which properties it applies, and agreed to the following:

  • RESOLVED: Add this definition to values-4 and evaluate new definition against existing test suite.
The full IRC log of that discussion <astearns> topic: [css2?] Define when border rounding happens, and to which properties it applies
<astearns> github: https://github.com//issues/5210
<fantasai> -> https://github.com//issues/5210#issuecomment-1292794138
<dandclark> dbaron: There have beeen differences in how border rounding works between impls.
<dandclark> dbaron: ??? landed change to make Chromium match webkit, gecko.
<dandclark> ...: we think border-rounding is interop now.
<dandclark> ...: given this, and that there's dependency on it which may increase, we should spec it.
<dandclark> ...: emilio opened this 2+ years ago, does he have anything to add?
<dandclark> emilio: <missed>
<dandclark> dbaron: In last comment I attempted to write definition in spec language. Other folks from other engines should look. If we're ok with it, lets move forward and try to spec it.
<fantasai> -> https://github.com//issues/5210
<dbaron> s/???/Traian/
<dandclark> emilio: I was misreading, I think that definition is correct.
<dandclark> astearns: This is matching existing tests?
<dandclark> dbaron: Yes there are various tests. I think there are a bunch of wpt tests for this behavior.
<dandclark> ...: I know when Trian was making chromium changes, making changes caused other engines to fail. Encouraged him to test only interoperable behavior.
<dbaron> s/other engines to fail/Chromium to fail some existing tests/
<astearns> ack fantasai
<dandclark> asterns: Proposed resolution: Add this definition to spec and evaluate new definition against existing test suite.
<dandclark> fantasai: Propose to add to values-4
<dandclark> dbaron: <missed> I don't strongly about which spec, I leave to editors.
<dandclark> asterns: Proposed resolution: Add this definition to values-4 and evaluate new definition against existing test suite.
<dandclark> RESOLVED: Add this definition to values-4 and evaluate new definition against existing test suite.
<dbaron> (and the issue should have links to the WPT PR)
@MrHBS
Copy link
Contributor

MrHBS commented Feb 27, 2023

@emilio @dbaron @fantasai Would one of you guys do the edit? Or I'll try to open a PR.

tabatkins added a commit that referenced this issue Feb 27, 2023
…e it in several properties to snap computed values. #5210
@tabatkins
Copy link
Member

Done! Sorry, the resolution came in while I was on birthday vacation, so I missed it.

@MrHBS
Copy link
Contributor

MrHBS commented Feb 27, 2023

@tabatkins Very nice! Thank you! Just 2 more things to mention:

1 - You might want to look at #7473 and #2114 to see if they are still relevant after this change.

2 - CSS Cascading and Inheritance says:

A used value is in principle ready to be used, but a user agent may not be able to make use of the value in a given environment. For example, a user agent may only be able to render borders with integer pixel widths and may therefore have to approximate the used width.

I think this needs a tweak since border widths are always integers now?

@tabatkins
Copy link
Member

For 1, thanks, I've commented or closed, as appropriate.

For 2, not necessarily - there's nothing in CSS requiring that a px is an integer multiple of device pixels, so that statement can still be reasonable. ^_^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment