CSS Overflow-x and the Clipping of Borders
published on
I was playing around with CSS transforms on an element with a border, where as a result the border would then overflow the page body. Usually this would not be an issue that the CSS property overflow
couldn’t solve. To be more precise, in my case the correct property to use was overflow-x
with the value of hidden
to avoid horizontal scroll, since by using overflow: hidden
the main page content, which is (likely) longer than the viewport, would stop scrolling vertically. And that would be bad.
After adding overflow-x: hidden
to my transformed element, I started testing in different browsers. It seemed to work just fine, but after deploying I noticed that Safari and Chrome on iOS as well as Firefox, rendered the page with horizontal scrolling. I was a little surprised and at first, I thought that it had to be a bug with overflow-x
.
I went on to check the examples on MDN and all of them worked fine in either browser. I then started to read the specification for the hidden
value of overflow
and there I found the solution:
hidden
This value indicates that the box’s content is clipped to its padding box and that the UA must not provide any scrolling user interface to view the content outside the clipping region, nor allow scrolling by direct intervention of the user, such as dragging on a touch screen or using the scrolling wheel on a mouse. However, the content must still be scrollable programatically, for example using the mechanisms defined in [CSSOM-VIEW], and the box is therefore still a scroll container.
The specification says “fit the padding box”. To understand the problem, we need to take a look at the CSS basic box model.
When laying out a document, the browser's rendering engine represents each element as a rectangular box according to the standard CSS basic box model. CSS determines the size, position, and properties (color, background, border size, etc.) of these boxes.
Every box is composed of four parts (or areas), defined by their respective edges: the content edge, padding edge, border edge, and margin edge.
As visible in the above diagram, the border edge lies outside the padding edge and because of that, the clipping of overflow didn't work as expected. I then refactored the element to use a margin
instead of border
and it now works as expected. Another positive side effect of changing the border to a margin is that it removes some rendering issues (in Safari) on the border which can appear when an element is transformed.
After so many years of working with CSS I didn’t think there was something new to learn about the overflow
property, but oftentimes a language specification will surprise you in the most unforeseen ways ;) I recommend taking a peek once in a while, because there’s always something new to learn and it’s absolutely worth it.