Consider disabling overlay scrollbars if a `-webkit-scrollbar` style rule is specified with nonzero width and height
Categories
(Core :: Layout: Scrolling and Overflow, enhancement, P3)
Tracking
()
People
(Reporter: dholbert, Assigned: hiro)
References
(Blocks 3 open bugs)
Details
(Keywords: webcompat:platform-bug)
User Story
user-impact-score:166.5
Attachments
(8 files, 1 obsolete file)
|
567 bytes,
text/html
|
Details | |
|
568 bytes,
text/html
|
Details | |
|
661.60 KB,
video/mp4
|
Details | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review | |
|
48 bytes,
text/x-phabricator-request
|
Details | Review |
We've got at least two cases where it seems like a Google site is trying to provide a thickness for scrollbars, which (in Safari and Edge with overlay scrollbars enabled) also successfully makes the scrollbars be "non-overlay-style", which happens to be a usability win in these cases:
bug 1836872
bug 1973196
I know we've already investigated and opted not to implement -webkit-scrollbar in general (bug 1432935). We might want to investigate doing a limited intervention for cases like this to at least take certain bundles of styles as a signal that we should switch to traditional scrollbars, though... Since that's how they end up working in Chromium and WebKit right now at least.
As an example, here's a testcase where the upper block uses scrollbars if they're enabled, and the lower two use ::-webkit-scrollbar to toggle non-overlay scrollbars with specified thicknesses in Chromium and WebKit:
https://jsfiddle.net/dholbert/L83ejpvd/
Updated•6 months ago
|
| Reporter | ||
Comment 1•6 months ago
|
||
(In reply to Daniel Holbert [:dholbert] from comment #0)
As an example, here's a testcase where the upper block uses scrollbars if they're enabled, and the lower two use
::-webkit-scrollbarto toggle non-overlay scrollbars with specified thicknesses in Chromium and WebKit:
https://jsfiddle.net/dholbert/L83ejpvd/
Here's that fiddle as a bugzilla attachment, for convenience/better-archival.
| Reporter | ||
Comment 2•6 months ago
|
||
Here's a testcase to demonstrate how this affects Gmail (bug 1973196).
A) In Firefox with overlay scrollbars, you can't scroll to reach SUCCESS. The inner area's overlay scrollbar isn't shown (it's covered up by the outer area's scrollbar, so you can't horizontally-scroll the inner area to see SUCCESS at all (unless you have some mechanism for touchpad/wheel-based horizontal scrolling).
B) In Firefox with legacy scrollbars, this is fine; you can scroll; you can see the two horizontal-scrollbars stacked and everything is fine.
C) In Chromium/WebKit, this is fine & you can scroll. This is true regardless of whether they're configured to use overlay scrollbars -- they react to the -webkit-scrollbar styles here by disabling overlay scrollbars and honoring the specified scrollbar width.
In this bug, I'm arguing that we should react to the prefixed scrollbar styles just like Chromium/WebKit do, and just activate legacy scrollbars (matching our (B) rendering).
We could do this on the level of the entire document, if that's easier to do (rather than turning overlay-scrollbars on/off for certain elements). Basically: whatever styles might deactivate overlay scrollbars in Chromium/WebKit should probably do the same for us (whether or not they also add additional fanciness in other browser-engines that we can ignore).
| Reporter | ||
Updated•6 months ago
|
| Reporter | ||
Comment 3•6 months ago
|
||
Here's a screencast showing the behaviors A/B/C from the previous comment.
Behavior (A) at the beginning is the problematic one -- that's where we're leaving content unreachable, basically.
Updated•4 months ago
|
Comment 4•4 months ago
|
||
testcase 2 shows different behaviors between OSes.
On macOS (with default settings), we're always showing both toolbars with both being reachable and not placed on top of each other (on the z-axis). There seems to be no "always show scrollbars" setting available in the settings.
On Windows 11, I'm seeing the behavior as shown in the screencast in comment #3 with the setting "always show scrollbars" not available.
On Linux (Ubuntu 24.04, X11), I'm seeing the behavior as shown in the screencast in comment #3 with the setting "always show scrollbars" available.
Comment 5•1 month ago
|
||
(In reply to Alex Jakobi [:ajakobi] from comment #4)
On macOS (with default settings), we're always showing both toolbars with both being reachable and not placed on top of each other (on the z-axis). There seems to be no "always show scrollbars" setting available in the settings.
On macOS this setting is in the OS settings: https://www.macrumors.com/how-to/make-scroll-bars-always-visible/
On Windows 11, I'm seeing the behavior as shown in the screencast in comment #3 with the setting "always show scrollbars" not available.
Same on Windows (https://www.windowscentral.com/how-always-show-scrollbars-windows-11)
| Assignee | ||
Comment 6•12 days ago
|
||
There are 6 test cases;
- webkit-scrollbar.html has
::-webkit-scrollbar { width: 8px; height: 8px; } - webkit-scrollbar-zero-width.html has
::-webkit-scrollbar { width: 0px; } - webkit-scrollbar-no-width-height.html has
::-webkit-scrollbar { background-color: #aaa; } - disable-horizontal-scrollbar-dynamically.html has no
::webkit-scrollbar styles, checks non-overlay scrollbars
properly disappear once after the contents in the scroll container
does no longer overflow - webkit-scrollbar-focus.html has
:focus::-webkit-scrollbar { width: 8px; height: 8px; } - webkit-scrollbar-display-none.html has
::webkit-scrollbar { width: 8px; display: none; }
As of now 6) doesn't work as expected.
| Assignee | ||
Comment 7•12 days ago
|
||
This change does;
- not make the current <scrollbar> element be a ::-webkit-scrollbar
pseudo element - rather, while traversing <scrollbar> element for its styling,
additionally collect ::-webkit-scrollbar rules and match them
as if the <scrollbar> is a ::-webkit-scrollbar pseudo - then if we found
width > 0orheight > 0styles on any
non-root <scrollbar> element, disable overlay scrollbar globally per
document, and kicks a media feature change evaluation
There are some restrictions;
- The machinery for property restrictions doesn't work for
::-webkit-scrollbar since it's not implemented as a genuine psuedo
element - ::-webkit-scrollbar is not applicable to the root scroll container
I haven't figured out how to obtain the originating element, i.e. the
<html> or <body>, while traversing the root <scrollbar> - Disabling overlay scrollbars does just work on the entire document,
it doesn't disable overlay on an individual scrollbar. We may be able
to do it by adding inline styles such asopacity: 1 ! importantto
each <scrollbar> to negate overlay styles defined in a UA style sheet
[1] with-moz-overlay-scrollbarmedia query.
| Assignee | ||
Comment 8•12 days ago
|
||
I think I am being stuck at finding ways to apply property restrictions to ::-webkit-scrollbar styles.
The current approach (written in D280698) is to not make <scrollbar> be a ::-webkit-scrollbar, it just additionally collects ::-webkit-scrollbar styles while traversing <scrollbar>. The current D280698 works in most cases, but if there's any CSS property other than width and height for ::-webkit-scrollbar, the property is also applicable to <scrollbar>, thus it will break <scrollbar>, one observable result I have seen is an assertion for cached scrollbar styles hits.
Emilio, do you have opinions on this issue? I'd personally like the original approach that is to make <scrollbar> be a ::-webkit-scrollbar pseudo element since the machinery for property restrictions works as-it-is. And the current approach also has a couple of hacks in selector matching.
Comment 9•12 days ago
|
||
Yeah, adding a SetPseudoElement(webkitScrollbar) to the scrollbar node seems more straight-forward, but that said, that's gonna break the scrollbar caching as well. also, we should disable overlay scrollbars only on that particular scroll container.
Updated•6 days ago
|
| Assignee | ||
Comment 10•6 days ago
|
||
Most of the remaining call sites of nsPresContext::UseOverlayScrollbars
for scrollbar parts' frames will be replaced by a new function in the
next change.
Updated•6 days ago
|
| Assignee | ||
Comment 11•6 days ago
|
||
There remain some direct call sites of
nsPresContext::UseOverlayScrollbars.
-
two call sites in nsCSSFrameConstructor::GetAnonymousContent [0]
These call sites for used for scrollbar style caching stuff,
thoguh I am not 100% sure whether these two call sites needs to be
replaced, in the next patch only width/height are applicable to
::-webkit-scrollbar pseudo elements and those properties are flagged
as has_effect_on_gecko_scrollbars=false, so it's okay-ish?
anyway the first one can not be replaced since it gets called before
styling the <scrollbar> itself -
in Element::GetClientAreaRect [1]
it's for an optimization to avoid layout flush on the root scroll
container, we will not apply ::-webkit-scrollbar to the root one, so it
doesn't matter -
in Gecko_GetScrollbarInlineSize [2]
it's used only for internal CSS env scrollbar-inline-size, so it
doesn't matter unless we use ::-webkit-scrollbar internally -
in nsTreeBodyFrame::Init [3]
it's XUL we won't use ::-webkit-scrollbar in chrome contents -
in Gecko_MediaFeatures_UseOverlayScrollbars [4]
it's used for-moz-overlay-scrollbarsmedia query, we leave the
styles in the media query, to disable overlay we will setactiveto
the scrollbar element.
[0] https://searchfox.org/firefox-main/rev/33fd6bd39c625067a29f153adce6a4646e45750f/layout/base/nsCSSFrameConstructor.cpp#3964,4035
[1] https://searchfox.org/firefox-main/rev/e480af4adea0d838f97b105d7efdd32fa18b73c1/dom/base/Element.cpp#1057
[2] https://searchfox.org/firefox-main/rev/e480af4adea0d838f97b105d7efdd32fa18b73c1/layout/style/GeckoBindings.cpp#317
[3] https://searchfox.org/firefox-main/rev/e480af4adea0d838f97b105d7efdd32fa18b73c1/layout/xul/tree/nsTreeBodyFrame.cpp#293
[4] https://searchfox.org/firefox-main/rev/e480af4adea0d838f97b105d7efdd32fa18b73c1/layout/style/nsMediaFeatures.cpp#112
| Assignee | ||
Comment 12•6 days ago
|
||
While traversing ::-webkit-scrollbar pseudo element for its styling,
additionally collect rules for <scrollbar> defined in UA style sheet
and match them.
There are two caveats;
- we tell a lie in
@supports selectoras if we don't handle
::-webkit-scrollbar at all - only width and height properties are applicable to ::webkit-scrollbar
pseudo elements, but these values are never used for <scrollbar>
elements becasue of the nature of our scrollbar implementation, i.e.
it rather respects scrollbar-width.
There's a restriction;
- ::-webkit-scrollbar is not applicable to the root scroll container
I haven't figured out how to obtain the originating element, i.e. the
<html> or <body>, while traversing the root <scrollbar>
| Assignee | ||
Comment 13•6 days ago
|
||
To disable scrollbars on a given scrollbar we set active attribute to
the vertical and horizontal scrollbar elements as if the user is
hovering over the scrollbars so that we don't specifically need to
cancel out styles in @media (-moz-overlay-scrollbars) query in
scrollbars.css even though the media query is document wide.
Updated•6 days ago
|
| Assignee | ||
Comment 14•6 days ago
•
|
||
Thank you, Emilio. I've somehow managed to make it happen. I am still not confident scrollbar style caching, I've written what I am thinks is in the commit message of D281571. I hope it does make sense to you!
Comment 15•4 days ago
|
||
Hmm, looking a bit closer at this and all the special cases that were needed, I wonder if it'd be easier to just add a RefPtr<ComputedStyle> ScrollContainerFrame::mWebKitScrollbarStyle; and update it in DidSetComputedStyle, via ProbePseudoElementStyle... Seems that'd work and wouldn't be a penalty for pages that don't use ::-webkit-scrollbar (we don't selector-match / compute a style at all in ProbePseudoElementStyle...)
It might be faster than breaking the scrollbar style caching perhaps? Hiro, that seems like a maybe easier approach? I think we didn't consider this approach when discussing it (only either "adding more NAC" or "turning scrollbar element into ::-webkit-scrollbar").
Assuming it'd be fast enough to probe on a page with no ::-webkit-scrollbar rules, and that we only probe one style (::-webkit-scrollbar really has some extra pseudo-classes too like ::-webkit-scrollbar:horizontal etc, not sure if they work now), it might be faster and less invasive.
Updated•2 days ago
|
| Assignee | ||
Comment 16•2 days ago
|
||
Thank you, Emilio! With the new approach the code change became much simpler!
Description
•