-
Notifications
You must be signed in to change notification settings - Fork 757
Description
Context
Elements with overflow: auto only get a scrollbar when the contents overflow. Classic scrollbars take some space, so this affects sizing this way:
When the box is intrinsically sized, this reserved space is added to the size of its contents. It is otherwise subtracted from space alotted to the content area. To the extent that the presence of scrollbars can affect sizing, UAs must start with the assumption that no scrollbars are needed, and recalculate sizes if it turns out they are.
<style>
div { overflow: auto; background: cyan; vertical-align: top; }
div::before { content: ""; display: block; height: 200px; width: 200px; }
</style>
<div style="display: inline-block; height: 100px; width: 100px"></div>
<div style="display: inline-grid; grid-template: 100px / 100px"></div>Note that only Blink has this behavior, Gecko (bug 764076) and WebKit don't: in the intrinsic case, the content area (without the scrollbar) is 100px tall indeed, but is less than 100px wide.
Tip: to force classical scrollbars if your UA uses overlay ones, in Firefox go to about:config and create a number pref ui.useOverlayScrollbars set to 0. In Blink/WebKit add this CSS:
::-webkit-scrollbar { background-color: #eff0f1; width: 12px; height: 12px; }
::-webkit-scrollbar-thumb { background: #898c8d; }Incompatibility with size containment
In short, with overflow: auto the contents can affect either the inner or the outer size of the element. This is a problem with size containment (when paired with layout containment), which should allow this optimization:
When the style or contents of a descendant of the containment box is changed, calculating what part of the DOM tree is "dirtied" and might need to be re-laid out can stop at the containment box.
This is not true if the element is sized intrinsically: a change in the descendants may trigger or untrigger a scrollbar, affecting the outer size, and potentially the ancestors.
Blink and WebKit assume it's fine to apply the optimization... with clear wrong results. See this testcase:
The testcase above won't work in Firefox due to bug 1488878, but the same problem can be seen with contain-intrinsic-size. CSS Sizing tries to define some interaction between contain-intrinsic-size and overflow: auto, but it has some problems (#7867, #7868) and I think the behavior should be the usual one, just with a custom intrinsic size. Here is the testcase with contain-intrinsic-size:
Circularity with container queries
So far, we have seen that we shouldn't allow the contents of an element with size containment to affect its outer size. Could we maybe say that the scrollbar should shrink the inner size to preserve the outer size, even when sizing intrinsically? No, because that would create a circularity with container queries, because of https://w3c.github.io/csswg-drafts/css-contain-3/#width
The
widthcontainer feature queries the width of the query container’s content box.
I have checked how Blink handles the circularity. It turns out it queries the size of the content area plus the scrollbar. Oddly, this happens even with overflow: scroll or when sizing intrinsically with overflow: auto. Testcase
- 1st is extrinsic
overflow: scroll. It matchesinline-size = 100pxdespite the content area being narrower. - 2nd is intrinsic
overflow: scroll. It matchesinline-size > 100pxdespite the content area being 100px. - 3rd is extrinsic
overflow: auto. It matchesinline-size = 100pxdespite the content area being narrower when there is a scrollbar. - 4th is intrinsic
overflow: auto. It matchesinline-size = 100pxwhen there is no scrollbar, and matchesinline-size > 100pxwhen there is a scrollbar despite the content area being 100px. Thus it would be circular, but due to the wrong optimization described above, the circularity is only apparent when forcing layout.
Well, I guess that does the trick to avoid circularities in practice, but all of this seems very buggy and hacky.
Possible solution
I'm leaning towards simply saying that size containment forces overflow: auto to behave as overflow: scroll.
Or maybe something like scrollbar-gutter: stable but without adding the gutter for overflow: hidden, and affecting both the inline and block axes.
CC @frivoal
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
Status



