Firefox's border pixel-snapping behavior causes thin borders to disappear entirely when scaled down (e.g. via CSS Transform or print-preview)
Categories
(Core :: Graphics: WebRender, defect)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox154 | --- | fixed |
People
(Reporter: hildobijl, Assigned: gw)
References
(Blocks 2 open bugs)
Details
(Keywords: reproducible, testcase, webcompat:platform-bug)
User Story
webcompat:blocked-resources user-impact-score:15
Attachments
(5 files)
Updated•10 years ago
|
Updated•10 years ago
|
Comment 3•4 years ago
•
|
||
Clarifying what sorts of outcomes are realistic here:
(In reply to Hildo Bijl from comment #0)
Expected results:
The borders should all ... remain visible
Let's focus on this^ request; I think this is the least-controversial expectation here.
To be
precise, when a border of "0.8px" is scaled by a factor "0.5", the resulting
border should look exactly like it would've looked when given the width
"0.4px" without scaling.
This is a reasonable intuition but it's a non-goal and is not actually how borders work in any browser.
In the absence of transforms, I think all browsers snap borders to whole-number display-pixel-values (at least, they do for borders less than 1px) -- so e.g. 0.4px will just round up to one display-pixel (and so will 0.01px), at computed-value-time (i.e. and it actually reserves & occupies that much layout space, rather than the specified tiny-fraction-of-a-pixel). This is interoperable and required for compatibility; you can try e.g. data:text/html,<div style="border: 0.01px solid black">Hi in various browsers and see that it occupies a full display-pixel (e.g. it's equivalent to border:1px solid black on a traditional non-HiDPI display resolution).
In contrast, transform:scale(0.5) is a paint-time effect and we don't get the opportunity to make the border specially-reserve-and-occupy a full display pixel of layout space when we apply a scaling transform. Chrome seems to use antialiasing to paint the scaled-down partial-pixel-width-border, whereas Firefox seems to still try to paint a whole number of pixels (possibly 0); we round down to 0px for sufficiently-small scales / sufficiently-thin borders. This outcome is not-great; ideally we should allow ourselves to paint fractional-width-borders as antialiased partial-pixels when we're scaling them, I think.
Comment 4•4 years ago
|
||
Also FWIW, I can see that the original testcase here renders without a top black border in old Firefox nightlies e.g. Firefox Nightly 48.0a1 (2016-03-19), but the whole black border paints in current Firefox Nightly (2022-06-21).
But if I reduce the scale to e.g. 0.2 or 0.5, I can still reproduce (the black border disappears).
I've got a clearer/more-comprehensive testcase on my dupe bug, which I'll repost here for clarity/convenience.
Updated•4 years ago
|
Comment 5•4 years ago
|
||
Comment 6•4 years ago
|
||
screenshot of reduced testcase 1 in Firefox vs Chrome: https://bugzilla.mozilla.org/attachment.cgi?id=9282271
Updated•4 years ago
|
Updated•3 years ago
|
Comment 11•3 years ago
|
||
The severity field for this bug is relatively low, S3. However, the bug has 5 duplicates.
:emilio, could you consider increasing the bug severity?
For more information, please visit auto_nag documentation.
Comment 12•3 years ago
|
||
Other browsers are going to match our behavior here and it's not clear there's a terribly-better behavior around. We could make WebRender force 1 dev px borders at paint-time too, but...
Comment 13•2 years ago
|
||
(In reply to Emilio Cobos Álvarez (:emilio) from comment #12)
Other browsers are going to match our behavior here and it's not clear there's a terribly-better behavior around
Do we know if/when that's going to happen? I think some of it was happening in https://issues.chromium.org/issues/40178820 for a little while, but I'm still seeing Chrome and WebKit both render my attached reduced testcase 1 with fuzzy antialiased borders. I'm not sure if that's because they have special-cases for borders less than 1px wide, or if they never finished implementing this change, or something else.
Even if other browsers do end up matching us here, we might want to add some sort of mitigation for print-preview in particular (like the WebRender mitigation in comment 12), to avoid having borders mysteriously disappear in print-preview, per the last bit of bug 1775345 comment 0 (see screenshot https://bug1775345.bmoattachments.org/attachment.cgi?id=9282272 ).
(This came across my radar again today because I was print-previewing a page that had a <table> with 1px-thick borders, with some bordered empty cells on the final page. That final page just looked entirely blank in print-preview, which was confusing & looked like Firefox was mistakenly generating a final blank page.)
Comment 14•2 years ago
•
|
||
Looking at the Blink bug about border-snapping, it seems their feature-flag for this was called SnapBorderWidthsBeforeLayout which shipped to release in v109 per https://chromestatus.com/feature/4651561863610368 and seems to have stuck. I think that (and the associated WebKit changes) are the thing that Emilio was referring to in comment 12 as other-browsers-going-to-match-us (correct me if I'm wrong though).
I think the last paragraph of my comment 3 is still an accurate description of the compat situation here -- Firefox optimizes for keeping borders crisp, even in the face of transform with fractional scales, whereas other browsers do not (and hence scaled-down borders still show up [albeit in a fuzzy/antialiased form] for them, whereas they entirely disappear for us).
Comment 16•2 years ago
|
||
I think we should move this to graphics given the comments above. If we were to fix this, it should be by antialiasing borders, not by changing layout / style computation.
Updated•1 year ago
|
Comment 17•1 year ago
|
||
I noticed today that this affects Responsive Design Mode as well, which I think uses CSS Transforms to apply a viewport scale-factor for mobile devices (for content that lacks a meta-viewport tag).
Loading this testcase in Firefox Nightly on my Ubuntu 24.10 machine in responsive-design-mode, some of the border-sides fail to render. (The sides that are missing are variable; it depends on the exact device/viewport-size that I've chosen in RDM.) For example, when I choose "Galaxy Note 20 Android 11", the bottom and right border-side are missing.
Comment 18•1 year ago
|
||
| Assignee | ||
Comment 20•1 year ago
|
||
Consider decreasing the webcompat priority of this because it's a cosmetic glitch only that is unlikely to affect a large number of users regularly.
Comment 21•1 year ago
|
||
(In reply to Glenn Watson [:gw] from comment #20)
it's a cosmetic glitch only that is unlikely to affect a large number of users regularly.
That's an accurate statement, I think.
For the record, I think the current user impact here is as-follows:
- We have one report of a site that's currently got some cosmetic breakage from this (bug 1926453).
- Outside of that, I suspect that the places where users are most-likely to encounter this would be when Firefox itself is scaling down content that happens to have 1px-wide borders (e.g. a form control or an underline) -- for example, when viewing non-mobile-optimized content on Android (dupe bug 1784322) or when print-previewing (dupe bug 1775345).
Updated•1 year ago
|
Comment 22•1 year ago
|
||
it's a cosmetic glitch only that is unlikely to affect a large number of users regularly.
While it may be accurate, it can still produce a bad user experience in some specific applications.
I'm leading an open source project, Sirius Web, used to build complex diagrams for major corporations. Our end users are constantly zooming in and out of diagrams with tons of divs with borders. With Firefox it can very quickly become unusable (especially on windows from what I've seen). Our diagram elements can lose their borders quite easily and, in complex diagrams, it becomes impossible to see where some of our element are.
I've made a small video showing the difference between Firefox and Chrome here on a simple diagram, if you want to see the impact on use cases such as ours. Some of our users just have to barely zoom out to see all borders disappear.
Updated•10 months ago
|
Comment 23•9 months ago
|
||
The severity field is not set for this bug.
:gw, could you have a look please?
For more information, please visit BugBot documentation.
| Assignee | ||
Updated•9 months ago
|
Updated•2 months ago
|
| Assignee | ||
Comment 24•10 days ago
|
||
A border edge is composited onto its layout-space rect, so a transform makes a
1px border a fractional device thickness. Two symptoms follow:
- Under a downscale (e.g. scale(0.5)) the edge shrinks below a device pixel and
edge antialiasing fades it away entirely, until whole sides of the border
disappear (bug 1258112). - At other scales (e.g. scale(0.5) on a devicePixelRatio 2 display, or at
fractional zoom) the four sides land at different sub-pixel phases and render
with visibly uneven thickness - right and bottom look thicker than left and
top (bug 1950029).
The cached border texture is already floored to a device pixel; the collapse is
only in the on-screen composite geometry, which was never snapped. In
NormalBorderData::update, snap each edge thickness on the true world scale that
drives the composite: round a border the author declared at >= 1 CSS pixel to
the nearest whole device pixel, floored at 1 so a real border can't vanish. With
the outer box already device-snapped, this grid-aligns the inner edges too, so
every side renders as a consistent whole-pixel width. Genuinely sub-CSS-pixel
edges are left untouched. This mirrors how line decorations snap their thin axis
(bug 1783779), one layer deeper (a border is a single prim rather than a thin
rect).
Updated•10 days ago
|
Comment 25•7 days ago
|
||
Comment 26•6 days ago
|
||
| bugherder | ||
Description
•