Borders scale differently than other sizes (e.g. margins, content-sizes, backgrounds), under full-page-zoom or HiDPI
Categories
(Core :: Layout, defect)
Tracking
()
People
(Reporter: dholbert, Assigned: emilio)
References
(Blocks 2 open bugs)
Details
(Keywords: perf-alert, Whiteboard: [webcompat])
Attachments
(6 files, 1 obsolete file)
STR: 1. Load attached testcase 2. Zoom in and out, examining output at various zoomlevels EXPECTED RESULTS: No red should be visible, at any zoom level. ACTUAL RESULTS: Many zoomlevels show red slivers, between the divs and on their edges. Basically, this indicates that we aren't scaling background-rects and border-rects in the same way, during full-page-zoom. (We're rounding in a different way, or something like that.) I'm pretty sure this is the same issue I described in bug 472769 comment 43 and bug 472769 comment 44.
Reporter | ||
Comment 1•12 years ago
|
||
Reporter | ||
Comment 2•12 years ago
|
||
I can reproduce this, zooming in 1x, with both Firefox 3.0.5 and with the latest mozilla-central nightly. Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008121711 Ubuntu/9.04 (jaunty) Firefox/3.0.5 Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2a1pre) Gecko/20090205 Minefield/3.2a1pre
Reporter | ||
Comment 3•12 years ago
|
||
Here's a reference case. It just differs from the testcase in that it uses a *background* instead of a *border* to draw the blue rectangles. (It's the same size in both cases, so in theory, they should behave the same) I get no red at any zoomlevel using this reference case. (I tested it with both Firefox 3.0.5 and with my mozilla-central nightly.)
Reporter | ||
Comment 4•12 years ago
|
||
Here's a simple reftest for this bug.
Reporter | ||
Comment 5•12 years ago
|
||
Here's what we get from this reftest right now. In the failure reftest-snapshot, it looks like the rectangle is at least 1px shorter & skinnier than its reference case, and the bottom & right edges look grayish, when they should be solid black.
Reporter | ||
Comment 6•12 years ago
|
||
Note also that in the attached reftest patch, the testcases 477157-1a.html and 477157-1b.html look identical to each other when viewed at zoomlevel 1.0 (i.e. if you view the files directly).
This is probably intentional. Border widths are always adjusted to be exact multiples of device pixels, in the style system. This ensures that border lines with the same specified width are always rendered with the same width in device pixels after the border line rectangles are snapped to device pixels. Backgrounds are just snapped to device pixels. I think the border behaviour explains why at some zoom levels borders aren't covering the set of pixels you expect.
Reporter | ||
Comment 8•12 years ago
|
||
See also 499821, which only uses 'background' (no borders) and has "seams" similar to those in this bug at various zoom levels, breaking wiki.mozilla.org
Reporter | ||
Comment 9•12 years ago
|
||
(In reply to comment #8) > See also 499821 Sorry -- I meant "bug 499821" Bugzilla, linkify!
Comment 10•12 years ago
|
||
I run into this problem with Ext toolkit, but I am sure that they are not the only one affected. Up until now on all browsers the "correct" way to get numeric value from "computed style" was to use "parseInt( ... )" (to get rid of "px" suffix). This is how it is coded in endless number of existing applications. As you can imagine with border width been reported as fractional, results are far from expected. Considering the fact that no other browsers (have not tried Chrome) behave differently, was it really good idea to "scale" width like this? Other thing which makes this questionable is the fact that it "breaks" relations between "offsetWidth/offsetHeight", "clientWidth/clientHeight" and "border width/height", padding. Out of these 4 sizes, border width is the only "scaled" value. So as soon as you are using non-default zoom level, formula: offset == client + border + padding is not true. It is my understanding that this formula is part of a standard.
Comment 11•12 years ago
|
||
Sorry, second paragraph should read: Considering the fact that no other browsers (have not tried Chrome) behave like this, ...
![]() |
||
Comment 12•7 years ago
|
||
Regression-range good http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/2007/10/2007-10-25-04-trunk/firefox-3.0a9pre.en-US.win32.zip bad http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/2007/10/2007-10-26-05-trunk/firefox-3.0a9pre.en-US.win32.zip http://bonsai.mozilla.org/cvsquery.cgi?treeid=default&module=all&branch=HEAD&branchtype=match&dir=&file=&filetype=match&who=&whotype=match&sortby=Date&hours=2&date=explicit&mindate=2007-10-24-01&maxdate=2007-10-26-01&cvsroot=%2Fcvsroot It's more obvious when zooming with Ctrl+Mousewheel instead of Ctrl+NumPad+/- due to the smaller intervals. Note: Before 2007-10-26, the testcase isn't zoomable at all.
Comment 13•3 years ago
|
||
Dholbert, is this a valid bug? Comment 7 suggest that it isn't. We hit this regularly: https://bugzilla.mozilla.org/buglist.cgi?query_format=advanced&longdesc=bug%20477157&product=Firefox&product=Toolkit&longdesc_type=substring It would be good to know if we should accept this as a fact of life and keep working around it or whether we can expect this to be fixed some day.
Reporter | ||
Comment 14•3 years ago
|
||
[CC'ing some other folks who work in pixel-snapping-related code] (In reply to Dão Gottwald [::dao] from comment #13) > Dholbert, is this a valid bug? Comment 7 suggest that it isn't. I'm not sure. Per comment 7, our current behavior is the least-bad solution we had come up with at the time. Though: that comment & its reasoning predated ubiquitous HiDPI screens (which are like an always-on full-page-zoom, which therefore can make this much easier to trigger, particularly for intermediate HiDPI scale factors like 125%). > It would be good to know if we should accept this as a fact of life and keep > working around it or whether we can expect this to be fixed some day. For now, I think this is a fact of life -- but I'm not confident enough to close it as WONTFIX or INVALID. It's possible we'll eventually come up with a better solution that addresses the tradeoffs somehow, but I'm not seeing one at the moment.
Reporter | ||
Updated•3 years ago
|
Reporter | ||
Updated•3 years ago
|
Reporter | ||
Comment 15•3 years ago
|
||
Apparently the google.com and amazon.com front-pages have some minor visual :hover glitches that are caused by this bug on some HiDPI configurations (175% in particular) & also with high full-page-zoom-levels, as discussed over in bug 1399577. Also: bug 332275 will potentially open up another way for users to hit versions of this bug more frequently across the web. (by letting users set a value other than 100% as their default full-page-zoom value) We're not entirely on our own in our current behavior, FWIW -- Safari 11 matches us on this behavior (i.e. it shows red when you scale attachment 360825 [details] up or down with full-page-zoom, and it has the same issues described for us over in bug 1399577). But Edge and Chrome have taken a different approach and have none of these problems (though presumably their approach causes different problems). It'd be worth investigating what Edge/Chrome do here and seeing if it'd be worth changing, since this is a bit of a webcompat issue (at HiDPI, per bug 1399577), and it's an unintuitive/unexpected behavior for web developers to have to worry about coding for.
Comment 16•3 years ago
|
||
"But Edge and Chrome have taken a different approach and have none of these problems (though presumably their approach causes different problems)" Daniel I think I may have found one of these such issue: both Edge and Chrome have this issue when system scaling is 175%, but Firefox doesn't https://bugs.chromium.org/p/chromium/issues/detail?id=793060 If changing Firefox to behave like Chrome and Edge would result in Firefox also having that issue on twitter.com, maybe Firefox made the right choice.
Comment 18•2 years ago
|
||
Migrating Webcompat whiteboard priorities to project flags. See bug 1547409.
Comment 19•2 years ago
|
||
See bug 1547409. Migrating whiteboard priority tags to program flags.
Comment 20•1 year ago
|
||
This problem can also occur for the widely used shapes defined with css.
For example the following will result in gaps for Firefox' max zoom of 300%:
<div style="width: 16px; height: 16px; border: 1px solid red">
<div style="border: 8px solid red; border-color: transparent red; width: 0"></div>
</div>
It is possible to work around the issue by not defining the outer size and using display: inline-block
.
I found the behaviour unexpected though.
Comment 21•1 year ago
|
||
I could also reproduce this with display: inline-block
. A minimal testcase is attached; it originally broke on a real site, with a demo about mazes (https://www.jamisbuck.org/mazes/).
Note that the testcase will render correctly at the default zoom level, but there will be discontinuities in the background as well as in the width of the maze.
Comment 22•1 year ago
|
||
Assignee | ||
Comment 23•1 year ago
|
||
So, borders are snapped to device pixels here: https://searchfox.org/mozilla-central/rev/9b99e1d9c6cf83539674cb016c7373f549ba59ca/servo/components/style/properties/gecko.mako.rs#516
It doesn't seem like other browsers do this anymore... We should probably change this. David, is there any good reason for this behavior nowadays? I always found the "round to dev-pixels" pretty weird.
Assignee | ||
Comment 24•1 year ago
|
||
I guess the most useful feature of this is making border: 0.3px
and such not round down to 0px
...
Assignee | ||
Comment 25•1 year ago
|
||
The most reduced test-case would be data:text/html,<div style="border: 0.1px solid;">Foo
, I suspect. getComputedStyle(document.querySelector("div")).borderTopWidth
would return 0.1px
in other browsers, and 0.5px
in Firefox (in a HiDPI display, 1px
in a regular display, I guess).
Assignee | ||
Comment 26•1 year ago
|
||
Let graphics snap as it wants before doing so. Rendering of small borders looks
fine in here even with this patch.
This enables further cleanups too.
Assignee | ||
Comment 27•1 year ago
|
||
I sent a patch removing this, and confirmed it fixes both test-cases, but I haven't submitted it for review yet (so take it as a WIP). Let's see what does CI say: https://treeherder.mozilla.org/#/jobs?repo=try&revision=f591313619e690ee25703f5da15fb80a43dc67aa
Comment 28•1 year ago
|
||
I think there still is good reason to do this snapping. It produces better visual results; without this, some widths of borders are different widths in device pixels depending on their position, which produces very bad effects. There's a much longer explanation somewhere that I'd like to find later.
Comment 29•1 year ago
|
||
I guess the most useful feature of this is making border: 0.3px and such not round down to 0px...
The rounding code to do this at least used to explicitly round anything between 0 and 1 device pixels up to 1.
Assignee | ||
Comment 30•1 year ago
|
||
(In reply to David Baron :dbaron: 🏴 ⌚UTC-5 from comment #28)
I think there still is good reason to do this snapping. It produces better visual results; without this, some widths of borders are different widths in device pixels depending on their position, which produces very bad effects. There's a much longer explanation somewhere that I'd like to find later.
While that may be true, that's also an issue for a bunch of other stuff like backgrounds and such, right? I think it's mostly graphics' job to snap pixels to device position. Asymmetric borders are not great though.
In any case I think rounding at computed-value time is pretty weird... The fact that the computed style is affected by your DPI has always looked like a bug to me.
(In reply to David Baron :dbaron: 🏴 ⌚UTC-5 from comment #29)
The rounding code to do this at least used to explicitly round anything between 0 and 1 device pixels up to 1.
Yeah it still rounds anything non-zero to 1 dev px.
Assignee | ||
Comment 31•1 year ago
|
||
Also, don't you have the same issue anyway with border widths depending on position if you have a subpixel width between them?
Assignee | ||
Comment 32•1 year ago
|
||
From the CI run in comment 27, a bunch of tests fail:
- Vast majority of them testing for our current snapping in particular (not too concerned about those).
- Some of them are minor antialising bits which can be trivially fixed (the fragmentation and pagination-related ones).
All in all those are fixable, but I think if we landed my patch at the very least should not just remove the code, but keep it disabled only on Nightly for quite a bit to watch for regressions...
Comment 35•1 year ago
|
||
I am running into this issue when I create buttons with borders that are only enabled when you hover over the button. This is using Firefox 75.0 on Windows 10. Here is a simple test case:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Firefox border bug</title>
<style>
.button {
background-color: black;
font-family: Arial, sans-serif;
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
color: white;
}
.button:hover {
border: 2px solid black;
color: black;
background-color: white;
width: 96px;
height: 46px;
line-height: 46px;
}
a {
text-decoration: none;
}
td {
padding: 5px;
}
</style>
</head>
<body>
<table>
<tbody>
<tr>
<td>
<a href="http://www.example.com">
<div class="button">
Click Here
</div>
</a>
</td>
<td>
<a href="http://www.example.com">
<div class="button">
Click Here
</div>
</a>
</td>
</tbody>
</table>
</body>
</html>
If you view this in Firefox 75.0 with the Windows scale set to 125%, then the borders when the button is hovered over will display as 1.6px (instead of 2px). The borders will also show with incorrect sizes if the Windows scale is set to anything other than 100%. As a result, if you hover over the left button in this example, the right button will shift slightly to the left, because the width of the left button (including border) is reduced to 99.2px instead of 100px. If you view this in Firefox with the Windows scale set to 100% it displays correctly, and it displays correctly in all other browsers I have tested (Internet Explorer 11.778.18362.0, Chrome 81.0.4044.122, Edge 44.18362.449.0, Opera 68.0.3618.56).
Assignee | ||
Comment 36•11 months ago
|
||
David, Mats: Phabricator-bugzilla integration seems slow / broken today, but what do you think of https://phabricator.services.mozilla.com/D75360?
It seems closer to what other browsers are doing based on the discussion in the linked Chromium bug, and allows subpixel borders to work as expected.
Assignee | ||
Updated•11 months ago
|
Assignee | ||
Comment 37•11 months ago
|
||
Daniel, your feedback on the above revision would also be appreciated.
Assignee | ||
Comment 38•11 months ago
|
||
I'm thinking maybe we should ceil rather than floor the border line width, so that we don't ever leave gaps. But on the other hand that can cause borders to overlap.
Assignee | ||
Comment 39•11 months ago
|
||
This seems to match what other browsers do, and seems saner layout-wise,
at least.
Comment 40•11 months ago
|
||
So if you're flooring at paint time, which edge are you aligning with (for the cases where the paint-time flooring changes the number of pixels actually covered)? (top/left edge? outer edge?) And what do other browsers do?
It seems to me that aligning with the outer edge would be most desirable since that would avoid having a device pixel of background visible outside the border in those cases.
Assignee | ||
Comment 41•11 months ago
|
||
We align to the outer edges, yeah. I believe other browsers do the same.
Updated•11 months ago
|
Comment 42•11 months ago
|
||
(In reply to Emilio Cobos Álvarez (:emilio) from comment #25)
The most reduced test-case would be
data:text/html,<div style="border: 0.1px solid;">Foo
, I suspect.getComputedStyle(document.querySelector("div")).borderTopWidth
would return0.1px
in other browsers, and0.5px
in Firefox (in a HiDPI display,1px
in a regular display, I guess).
Does the approach decided, if decided, i.e "snapping?" to outer edges - does this eliminate the "leak" of the devicePixelRatio (as per email mid January). Or is this still layout-exposed?
Assignee | ||
Comment 43•11 months ago
|
||
(In reply to Simon Mainey from comment #42)
Does the approach decided, if decided, i.e "snapping?" to outer edges - does this eliminate the "leak" of the devicePixelRatio (as per email mid January). Or is this still layout-exposed?
It's still exposed as we round up to at least one device pixel, and that is still exposed in getComputedStyle and other layout APIs. It's a bit less visible though.
Reporter | ||
Comment 44•11 months ago
|
||
(In reply to Emilio Cobos Álvarez (:emilio) from comment #37)
Daniel, your feedback on the above revision would also be appreciated.
I may not have time to look closely at this before you're ready to land it, but I'll bet mats' feedback likely captures any objections/concerns that I might have on the approach.
(I'm happy that we're addressing this compat issue & minor footgun - thanks for tackling it!)
Comment 45•10 months ago
|
||
Pushed by ealvarez@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/5df17ecbcaa1 Ceil border and outline widths to 1 dev px at computed value time, but don't floor others to dev pixels until paint time. r=mats,dbaron
Comment 46•10 months ago
|
||
Pushed by emilio@crisal.io: https://hg.mozilla.org/integration/autoland/rev/04543b8ded50 Annotate one more test as passing, and fix build in older compilers.
Comment 47•10 months ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/5df17ecbcaa1
https://hg.mozilla.org/mozilla-central/rev/04543b8ded50
Assignee | ||
Updated•10 months ago
|
Assignee | ||
Comment 48•10 months ago
|
||
I reverted this change, see https://hg.mozilla.org/integration/autoland/rev/e9818ea993d02a724e56da4dd9167fc1179de68f / bug 1645008.
Though that means that probably we should just WONTFIX this.
Updated•10 months ago
|
Backout merged: https://hg.mozilla.org/mozilla-central/rev/e9818ea993d0
Updated•10 months ago
|
Comment 50•10 months ago
|
||
Alert before backout:
== Change summary for alert #26249 (as of Wed, 17 Jun 2020 06:18:53 GMT) ==
Regressions:
10% facebook-cold Similarity2D android-hw-p2-8-0-android-aarch64-shippable opt 0.77 -> 0.69
8% facebook-cold Similarity android-hw-p2-8-0-android-aarch64-shippable opt 0.78 -> 0.71
For up to date results, see: https://treeherder.mozilla.org/perf.html#/alerts?id=26249
Assignee | ||
Updated•1 month ago
|
Description
•