csswg-drafts
csswg-drafts copied to clipboard
[mediaqueries] Scroll bar type query
(spawned from Firefox discussion)
We (noVNC) need to be able to tell what kind of scroll bars the browser is presenting as we override some of the other methods for scrolling. For some cases, we then need to change the layout and behaviour of the page to return some scroll ability to the user. As this is about how the browser presents things, a media selector seems like the obvious choice of API.
noVNC is a VNC client, i.e. a way to access another (remote) computer. As such, it does some things that interfere with scrolling:
- It sends all mouse wheel events to the remote computer, prevent wheel scrolling
- It sends all touch events to the remote computer, preventing touch-and-drag scrolling
- It sends all keyboard events to the remote computer, preventing keyboard scrolling
The only scroll method left is to use the scroll bar. However, this is not always available. We historically saw two types of scroll bars:
- Gutter scroll bars
- Purely visual scroll bars (no way to interact with them)
So, we found a method to detect the gutter, and if it wasn't present, we assumed a purely visual scroll bar and enabled some alternative methods for scrolling in our UI.
But there is now a third type of scroll bar:
- Overlay scroll bars
We are currently misdetecting these as purely visual scroll bars, as they have no gutter. Meaning, we activate our fallback methods needlessly.
Initially, only macOS had overlay scroll bars, but they are broken¹, so this misdetection turned out to be a feature there. However, Firefox now has properly working overlay scroll bars on Windows and Linux, causing practical issues for us.
¹ They only appear when another scrolling method is used, and as stated above, all other methods are overridden
A selector seems circular:
:overlay-scrollbar::-webkit-scrollbar {
/* This forces classic scrollbar on WebKit and Blink */
width: 12px;
height: 12px;
background-color: #aaa;
}
But it would be possible to have a media query to detect the default/preferred scrollbar type (even if it may be different in some elements).
A different layout issue caused by this unexpected change in scrollbar layout:
https://bugzilla.mozilla.org/show_bug.cgi?id=1790747
(content is now obscured by the scrollbar as the browser no longer allocates separate space for it)
Being able to style overlay vs gutter scrollbars differently could give page authors the tool to handle this.
A selector seems circular:
Sorry, confusion on my end. A media query was what I meant. Should I update the title?
Changed the title now.
This might fit even better with the upcoming container queries, but I'll go with the classic method for now.
This type of media query came up during https://github.com/web-platform-tests/interop-2022-viewport/issues/15
Combined with env(scrollbar-inline-size) – which would return the default classic scrollbar size – authors could combine both in order to work around the “100vw is causing pointless horizontal scrollbars” problem:
@media (scrollbars: overlay) {
--100vw: 100vw;
}
@media (scrollbars: classic) {
--100vw: calc(100vw - env(scrollbar-inline-size));
}
el {
width: var(--100vw);
}
This “solution”, however, does assume that the root element is currently showing a vertical scrollbar.
@bramus At that point just use scrollbar-gutter: stable?
I am uncertain if that was a general or suggestion for this issue or not, but scrollbar-gutter unfortunately isn't able to disable overlay scrollbars. At least not for Firefox on Linux.
Not a general suggestion for this issue, just for bramus' testcase. scrollbar-gutter: stable having no effect with overlay scrollbars matches the @media logic.
@bramus At that point just use
scrollbar-gutter: stable?
Using scrollbar-gutter: stable currently does not affect the size of 100vw (ref. https://github.com/w3c/csswg-drafts/issues/5254), so you still need to subtract env(scrollbar-inline-size) from it. When using stable both-edges you even need to subtract it twice. Also see this thread with some of my findings.
But you wouldn't use 100vw, you would just use 100% or the initial auto and let it stretch.