Overflow scroll on scaled child: different behavior on X and Y axis
Overflow scroll on scaled child: different behavior on X and Y axis
Here is a code showing my issue
.container 
 width: 200px;
 height: 200px;
 overflow: auto;
.child 
 width: 400px;
 height: 400px;
 /* When scaling down, no more X scrolling because size is 200px, but still Y scrolling :( */
 transform: scale(0.5);
 /* Both axis working the same (no more scrolling) when absolutely positioned */
 /* position: absolute; */
/* Irrelevant styling */
.container 
 border: 2px solid palevioletred;
 position: relative;
.child 
 background-color: pink;
 transform-origin: top left;
<div class="container">
 <div class="child">
 Child
 </div>
</div>
Try to scroll down or right within the box.
Then I scale down the child with a transformation, halving its size.
I can somewhat understand the behavior of each axis, but not why they're acting differently.
Ideally I'd like the Y axis to act like the X axis.
If I set position:absolute on the child, then the Y axis acts as the X axis (Both scrolls disappears).
position:absolute
.container 
 width: 200px;
 height: 200px;
 overflow: auto;
.child 
 width: 400px;
 height: 400px;
 position:absolute;
 transform: scale(0.5);
/* Irrelevant styling */
.container 
 border: 2px solid palevioletred;
 position: relative;
.child 
 background-color: pink;
 transform-origin: top left;
<div class="container">
 <div class="child">
 Child
 </div>
</div>
Try to scroll down or right within the box.
Same thing when I set display:inline-block. Both axis behave the sames (Both scrolls aren't affected by scale)
display:inline-block
.container 
 width: 200px;
 height: 200px;
 overflow: auto;
.child 
 width: 400px;
 height: 400px;
 display:inline-block;
 transform: scale(0.5);
/* Irrelevant styling */
.container 
 border: 2px solid palevioletred;
 position: relative;
.child 
 background-color: pink;
 transform-origin: top left;
<div class="container">
 <div class="child">
 Child
 </div>
</div>
Try to scroll down or right within the box.
Why in the initial case, we have a different behavior? And why in some cases, the scale change the scroll (when we used position:absolute) and in other cases it doesn't (when we used display:inline-block).
position:absolute
display:inline-block
As a side note, transform is a visual effect that doesn't affect the layout so logically the scroll shouldn't change in all the cases.
transform
Hehe nice find :)
– Renaud
Sep 3 '18 at 19:42
I edited the question to add more details ;) let's hope it will attract more attention
– Temani Afif
Sep 3 '18 at 20:11
Thanks :) I forgot to mention it's working as intended on Edge (scrolling is never affected)
– Renaud
Sep 4 '18 at 8:23
 2 Answers
 2
 
I've found a few confusing statements in w3.org website about scollable overflow that might explain why the implementation is inconsistent. They look more like TODO marks, since it's a draft:
ISSUE 1:
There’s disagreement on the scrolling model. 2.1 apparently defined
 that you scrolled the content area; the content would overflow the
 content-box, and you would union that overflow with the content box to
 find the scrollable area. In particular, this means that the content
 would be offset by the start-sides padding, but if it overflowed, it
 would go right to the edge on the end sides. This is what Firefox and
 IE do. At least some authors (and spec authors) instead have the
 mental model that the padding box is what’s scrollable, so when you
 scroll to the end of the overflow, there’s the right/bottom padding.
 Chrome/WebKit do this for the block axis, at least. They’re somewhat
 inconsistent for the inline axis; there’s something weird about how
 they handle lineboxes.
It seems that the block-axis padding is probably web-compatible to
 honor. It’s unclear that the inline-axis padding will be. Further
 experimentation is needed.
ISSUE 2:
Is this description of handling transforms sufficiently accurate?
Note:
The scrollable overflow rectangle is always a rectangle in the
 box’s own coordinate system, but might be non-rectangular in other
 coordinate systems due to transforms [CSS3-TRANSFORMS]. This means
 scrollbars can sometimes appear when not actually necessary.
Anyway, it seems that we need to rely on "position:absolute" as a workaround for Chrome. Or transform the container instead of the child. Or even create an extra cointainer level.
Hope it helps!
The first issue seems only about padding, not about transforms. The second issue needs a little context. Could you please elaborate on that? The note seems only applicable on other coordinate systems and not on this question.
– JoostS
Sep 5 '18 at 22:14
Issue 1 refers to padding as it is described by w3c's "scrollable overflow" definition: "The scrollable overflow of a box is the set of things extending outside of that box’s padding edge for which a scrolling mechanism needs to be provided."
– Fabio Manzano
Sep 5 '18 at 22:24
Issue 2 refers to part of the scrollable overflow region: "the border boxes of all boxes for which it is the containing block and whose border boxes are positioned not wholly outside its block-start or inline-start padding edges, accounting for transforms by projecting each box onto the plane of the element that establishes its 3D rendering context."
– Fabio Manzano
Sep 5 '18 at 22:25
In general, I'm trying to point references proving that there's no solid definition for transformation behavior inside scrollable overflow.
– Fabio Manzano
Sep 5 '18 at 22:29
Thanks... good job!
– JoostS
Sep 5 '18 at 22:36
I believe the discrepancy in behaviour is linked to the transform-origin. When the origin is adjusted so that the child is placed to the right rather than the left (and the inline-block display removed), the horizontal scroll reappears and the child is only visible on scroll-over (see code snippet). As the child's default 'static' position (even without being transformed) would display from the top of the container, this is why it doesn't affect the vertical scroll in the same manner as I understand it.
As others have pointed out, there are outstanding tasks regarding CSS transforms. I would't regard it as a bug (although I see your point). Perhaps better explanations/more clarity will become available in future from the w3c.
.container 
 width: 200px;
 height: 200px;
 overflow: auto;
 border: 2px solid palevioletred;
 position: relative;
.child 
 width: 400px;
 height: 400px;
 transform: scale(0.5);
 background-color: pink;
 transform-origin: top right;
<div class="container">
 <div class="child">
 Child
 </div>
</div>
Transform-origin changed to top right (as opposed to top left)
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
 By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
 
here is another one: make the child element inline-block and the scroll will not change at all
– Temani Afif
Sep 3 '18 at 0:38