For the CSS overflow
property, should auto
or hidden
be the default instead of visible
?
If you write a lot of CSS, there is a good chance your immediate response would be “no way!” But hear me out! There are several awesome benefits to one of these being the default, and in my opinion, many or all of the drawbacks are based around the fact that it’s just not what we’re used to, rather than being real a problem once you adjust. Let’s look at the pros in cons in detail.
Why does this matter?
It matters because this is a real option for writing CSS today. It has become a common suggestion to put the following box-sizing CSS on your sites:
* {
box-sizing: border-box;
}
This basically says “hey, we don’t like the default behavior for box-sizing
, so lets use a different behavior by default for every element.” So, why not use this technique for other things? You could do this:
* {
overflow: auto;
}
It’s definitely a real option. You can’t just slap this on an existing site and have it work: you’d need to design things like this from the start. Let’s look at what would change if you did just that.
The Good
One thing that happens is that you can forget about clearfix. In IE7+ and all modern browsers, overflow: auto;
would automatically clearfix everything:
See the Pen zKusC by Greg (@incompl) on CodePen.
This results in more semantic markup that doesn’t have clearfixes everywhere.
Another thing that changes is the behavior of margins. Collapsing margins have often been a source of confusion, but they’re not all bad. For typography this actually makes sense:
See the Pen cBbDd by Greg (@incompl) on CodePen.
However, for many layout tasks collapsing margins really aren’t what we want:
See the Pen Lrcxm by Greg (@incompl) on CodePen.
overflow: auto;
changes the behavior of collapsing margins, but does not turn them off completely. Here is what happens:
See the Pen xKkop by Greg (@incompl) on CodePen.
This is actually quite convenient. Without this, you’d have to hack around with margins and paddings in a way that would result in less maintainable CSS.
The Weird
To explain what’s weird, first we have to understand what the default behavior that we’re changing is. The default value for overflow
is visible
. That means if an element’s content doesn’t fit, the content is still shown sticking out of the element.
See the Pen zxhbm by Greg (@incompl) on CodePen.
A lot of web designs rely on this behavior. This is the sort of thing you might see in the wild:
See the Pen rkAma by Greg (@incompl) on CodePen.
At a glance this looks fine, but you would notice something is awry if you were to add a background color to those menu items:
See the Pen DAjFq by Greg (@incompl) on CodePen.
In this case the layout would break pretty badly if you changed overflow
to auto
or hidden
.
See the Pen tILCz by Greg (@incompl) on CodePen.
However, isn’t it actually a good thing to make sure your elements fit their contents?
See the Pen FidKl by Greg (@incompl) on CodePen.
Or, better yet, drop the fixed widths altogether:
See the Pen qGFJj by Greg (@incompl) on CodePen.
Setting overflow
to auto
or hidden
forces you to be more diligent about sizing and using flexible sizing where possible. This might not be such a bad thing. However, there are cases where it’s a little bit more annoying:
See the Pen pJKmh by Greg (@incompl) on CodePen.
This is definitely unexpected at first. Where are the box shadows on the second two? Box shadows are treated as part of the element they decorate. With overflow: hidden;
it is hiding the box shadows since they would be outside of their container. With overflow: auto;
it’s a little more subtle: it is behaving like overflow: hidden;
because auto
has decided it’s not worth putting scrollbars for a box shadow (which is actually smart) so it hides them instead.
How do you fix this? The same way we fixed that menu bar earlier: by making the container big enough to fit the content:
See the Pen cKmdq by Greg (@incompl) on CodePen.
That wasn’t so bad. Or was it?
Auto or Hidden?
Everything we just discussed applies to both auto
and hidden
. So which is a better default?
Well, auto
sort of “feels” right. It has intelligent behavior that seems to do an OK job deciding what to do based on the situation. On the other hand, auto
can create situations where scrollbars show up in unexpected places. Nothing is more annoying than unexpected scrollbars.
On the other hand, hidden
does make sense in its own way. Why should an element allow its content to be displayed outside of itself?
For now I’m leaning toward auto
, but I’m willing to be convinced the other way.
OK, what now?
I’m thinking about using * {overflow: auto;}
on my next personal project to see how it goes. It’s fun and interesting do this kind of academic cogitation, but what really matters is how it goes down in practice. Would you consider trying this out? Is it not worth the trouble? What if it turned out great and became an idiom that was used more and more commonly? Let me know what you think in the comments!
Comments
We moved off of Disqus for data privacy and consent concerns, and are currently searching for a new commenting tool.
Seriously thinking I’ll have to try this on an upcoming project.
In some instances, overflow auto creates scrollbar. For browsers that show scrollbar, it is ugly. For browsers that don’t, the transparent scrollbar flashes for a millisecond. I am not sure why but this is one of those stupid CSS behaviors, about 2px is added to the bottom of the element and makes it scrollable.
Neat idea. About the whole * thing. Why not use inherit? It\u2019s awesome.
Will overflow: auto give me scrollbars all over the place on Windows machines?
Inherit is interesting, but I’m not sure where it’ll be useful in this case. Can you give an example where it might be useful?
The behavior will be the same on Windows. This is a concern of if the area is considered \”scrollable\” or not. The appearance of scrollbars may differ from platform to platform when they are needed, but it’s not an issue since we’re preventing the need for scrolling.
Inherit leaves the door open. It is useful when you need the behavior to change, say, for a third-party component that relies on the absence of
box-sizing: border-box
oroverflow: auto
.This makes sense. It seems very plausible that you might want to use a 3rd party library that would be built on the overflow: visible; assumption. Good call.
In my initial testing, every element on the page started getting scrollbars in Windows.
http://i.imgur.com/UWYxjrH.png
Scrollbars on an H1 and P in Windows when overflow is auto.
I have not seen this in the Windows configurations I’ve tested. Can you provide your CSS / HTML, OS version, browser vendor, and browser version?
[Edit] Also, I want to point out that you can’t expect this to work by just changing overflow for an existing page, a lot of sites were built on the overflow: visible; assumption, but they don’t have to be.
It\u2019s triggered whenever a font\u2019s internal leading does not fit within its line height.
In practice, you would get scrollbars with headings using a tight line-height of 1 to 1.2.
For testing purposes, you should observe scrollbars with the following CSS:
This is a good point, but it’s unrelated to Windows. The behavior is the same on any platform.
This is similar to the box-shadow thing: you’d have to write styles wherein fonts must fit inside their containers. I don’t think this is too crazy though. How often do you want fonts to leak out of their containers? Would they be overlapping other elements? Those are the types of questions I posed in the article, but I don’t want any confusion about if this works on Windows. It does.
Again, this is really neat idea, and I can appreciate the tradeoffs, so let\u2019s not downplay them.
It is related to Windows in that Windows does not hide OS scrollbars. I\u2019m not sure what you mean by \u201cworks\u201d. I had not said before, but if you mean that it works without scrollbars in most instances, then I disagree.
There is a very real tendency to see scroll bars on certain elements on Windows machines, or to experience minute shifting on Macs when scrolling over certain elements. Those certain elements are defined as elements without the necessary vertical padding to cover their line-height, even if by one pixel. That\u2019s a rather unforgiving quirk.
If you\u2019re suggesting that tight line heights are unreasonable, or that they are reasonable as long as we add the padding needed to prevent any unwarranted overflow, then this might be a matter of preference. I could understand if other developers consider this a useful feature to detect all of the overflows (although this would require they unhide scrollbars or use Windows, right?).
Either way, I do hope you experiment some more to address the line height issue in an update, and I do appreciate the back and forth. I\u2019m still provoked by this idea and I keep toggling it on and off in my current project.
I don’t mean to downplay the tradeoffs: in fact, the main motivation for this article was to have a discussion about those tradeoffs. What I mean is that the technique as described isn’t broken or less feasible on a particular platform. The Mac hidden scrollbars that flash for a second are just as terrible as full-on Windows-style scrollbars if you don’t want them. The only way to use this technique properly is to have neither. The tradeoffs are all concerning changes in your workflow that would be needed to accommodate that. There is definitely a matter of preference there, and that’s the conversation I’m most interested in.
I’m interested in your experience using tight line heights. It seems I don’t really cut back my line heights, so I’m curious to know more about how you use them in your designs. I’m definitely not suggesting they’re unreasonable.
One more thing to throw into the mix, as if it wasn’t complicated enough already, is that you can always opt back in to overflow: visible;. I’d only want to change the default if it was clear that the new default was what you \”usually\” wanted, which is subtle. I’m definitely in favor of using overflow: visible; where appropriate, but this seems to be more about typography than layout. So that’s a funny thing right there: maybe if this is useful or not depends on if your design is primarily typographical vs. laying out of blocks and buttons and such.
Just found this post, so apologies for being late to the party, but I want to add this screen shot I just took on the latest version of Chrome on Windows. It’s definitely broken.
http://imgur.com/hIyEnyu
Nice writeup! I agree that overflow: hidden or auto make more sense as a default behavior. I think I prefer hidden, because I hate scrollbars, and it just makes sense that things would not be visible outside their containing element.
I’d like to point out that you should be VERY careful when applying a style that can change default layout behavior to all elements using the * selector. If you have third-party libraries or widgets on your site, this can totally mess things up. I witnessed this issue recently with `box-sizing: border-box`.
Please don’t! I am working on an app right now where the previous developer has applied overflow: hidden to all divs, and it’s a *huge* pain. Any time we want to add a dropdown or alert element that needs to be positioned outside of its parent containers, we have to specify overflow: visible in 5 different places, which often has repercussions on the layout. Unlike box-sizing, the browser default of overflow: visible actually makes sense.
Box-sizing: border-box makes us all back to the times of IE5 overnight.
The difference is that now it is deterministic: every browser will treat it in the same way.
In IE5 it was a bug (not the intended behaviour), now it is a feature. 🙂
My very basic understanding is that many things in IE5/6 were actually ahead of their time… they implemented awesome stuff before they were standardized, but then the web moved in another direction and we had years of having to deal with two different box models. Standardizing on one was the right approach, but border-box is easier / more intuitive to style, especially when things are width: auto or 100% (the most common case I can think of is when you’re trying to make things the same width as fluid form inputs – tricky with content-box, easy with border-box).
I’m curious to learn more about the dropdowns / alerts. Maybe show in a codepen? Should these elements really be inside of those containers if they’re displayed elsewhere?
Here you go: http://codepen.io/anon/pen/…
Yes, absolutely they should. In many cases, you want a dropdown or alert to be styled in relation to its parent (same width, or in this case positioned directly below it).
This is the strongest argument against it that I’ve seen and I appreciate that you provided a concrete example to back it up. Thanks!
You’re very welcome.
Sounds like an exageration of modular development concept. You can style related elements without put them together.
Of course I can, but I don’t want to be forced to. There are plenty of good use cases for overflow: hidden, it just does not make sense as a default applied to every element.
Or just remove position:absolute?
Not sure what that would accomplish. Typically with dropdowns you want them to appear above other content, not push it down:
http://codepen.io/anon/pen/…
Can you fork my example and show me what you mean?
It accomplishes exactly what you asked for. If you move the goalpost then another solution is required.
If your .dropdown needs to appear \”above other content\” then it needs to be out of the flow itself. Something like this maybe? http://codepen.io/Sinetheta…
It doesn’t though. My first post says \”dropdown… positioned *outside* of its parent containers\”. Removing position absolute on the dropdown (ul) doesn’t work unless you make .dropdown position absolute instead of relative (which you did) and that can have other consequences on the design.
Even when it works, a single fixed height container anywhere higher up in the hierarchy that is shorter than your dropdown (e.g. a Twitter Bootstrap-style navbar) crops the dropdown and you’re back to square 1.
Anyways, I appreciate the suggestion. It’s certainly possible to find workarounds, but you have to weigh those against the convenience of overflow: auto/hidden as a default. In my experience, it’s not worth the trouble.
I think we can both agree on that. The question becomes what’s a more reasonable default?
I’d be interested in other examples where overflow:auto falls down, because if I had to choose between \”floated content\” and \”positioned things\” I’d lean towards the former as *normal* web.
A lot of libraries like bootstrap require that these elements should be inside those containers
The biggest draw of overflow: auto/hidden seems to be clearing floats. I would highly recommend reading \”Giving floats the flick\”, which outlines many awesome alternatives to floats: http://www.sitepoint.com/gi…
I had this pain when I started on a project once that had been fully developed by more junior developers thinking of it as a quick fix without realising the implications. overflow:hidden is powerful but dangerous, with great power comes great responsibility
Well, this makes perfect sense!
Making the overflow of :before or :after hidden would be fine.
If you’re curious if this is possible, I updated a site to do this:
Code diff: https://github.com/incompl/…
Updated site: http://static.incompl.com/n…
The things I had to fix were:
* Applying line-height globally was causing some elements to overflow, so I only added it where it was actually needed.
* I had to fix a couple inline-block elements because of the .25em margin between inline-block elements. overflow: auto; exposed that I wasn’t fixing this issue.
* Some of the layout was relying on the different collapsing margins behavior, so I just tweaked the margins. I don’t see this as really better or worse, just different
It seemed like too much work just to remove clearfixes. I don’t think I’d want to update an existing production site to use this technique. I still think it might be interesting to build something new like this from the start.
Have you studied the performance costs of setting this? I am not sure there are any, but, still, this needs to be studied. Basically global (*) rules have memory and performance implications (small or large – I am not sure). I noticed that when I added it to an existing page (I took plus.google.com as an example) and activated the Layers panel in the Google Chrome Developer Tools (you must have chrome://flags/#enable-devtools-experiments enabled and enable it through the Settings>Experiments screen of the Developer Tools) – it created much more layers. Layers are definitely expensive. However, those layers were probably created due to the fact that elements had scrollbars, so if you fix your styles so that scroll bars are not visible, no new layers would be created and it would probably not be expensive. I read that overflow: hidden has performance costs, though – http://stackoverflow.com/qu… – so that should probably be avoided.
Would like to see more on \”making the container big enough to fit the content\” – did you have to add extra mark up to achieve this?
I’ve encountered the same issue with child elements positioned absolutely outside the parent being hidden when overflow:auto is applied. It’s still not a catch-all solution for me yet.
The same goes for pseudo elements positioned outside the parent element.
Pseudo selectors are people too!
I would suggest that you start this outside the body otherwise for a fixed width site you will lose the horizontal scrollbar on the bottom of the viewport and it will hug the content instead resulting in a scrollbar near the top of the page on short content or way at the end of the document on tall content.
e.g. http://codepen.io/paulobrie…
Use body ‘* (overflow:auto)’ instead.
I just started styling a new site yesterday and tossed this in and have to say, I like the way it’s shaping up. I used the HTML { overflow:auto} and * {overflow: inherit} method with HTML5 in Chrome and IE11 on Windows 8.1. I noticed that emulating to IE-9 I get a number of scrollbars, but they’re due to height issues that are easy to fix.
Over-all, I think that the scrollbars are an easy way to make those overflow issues obvious.
I’m using :overflow:inherit\” to limit browser impact, but will have to keep in mind that if I set an element to \”overflow: hidden\” its an experiment.
By the way, I’ve been using this method for the box model for a year and as jonathantneal said, it works well. If I have to do IE7 styling, I can just change the rule (box-model) )in HTML and it inherits down.
So the reason this does what it does (which is often left unexplained) is because an overflow set to something other than visible establishes a new block formatting context. A block formatting context is actually very similar to microsoft’s hasLayout, if you remember that. You can effectively think of a block formatting context as being a containing box responsible for all of it’s children. Things inside a BFC must be contained by the BFC. For that reason, margins aren’t collapsed, floats are contained, etc. Just like hasLayout, there are many properties which implicitly trigger a new BFC so it helps to be aware of what those properties are.
More info: https://developer.mozilla.o…
I found, that using a google-font (roboto) caused overflow in
tags. Also, giving a button top: 1px on active also causes overlfow scrollbars. Adding 1px padding fixed this, though changing the overlfow on the parent will tool
I’m not sure I’d go so far as to place it on all, but my convention is definitely to use `overflow: hidden` on anything that contains a floated element so that I don’t need HTML-level clearfixes.
Placing it selectively is a better choice for both selector efficiency and preventing css bloat (you’d likely use `overflow: hidden` in fewer places than you’d otherwise have to reapply `visible` or decent `line-heights` to.)
I’m a follower of the \”don’t override yourself\” school of thought\u2014if you have to undo something you’d done, you’ve probably done it too soon and too broadly.
As far as the example with `margin-bottom` goes, I’d place `padding-bottom` on the container along with (global) `box-sizing: border-box` instead; after all, it’s likely you’d want that same spacing no matter what the last content-level HTML tag was. No need to apply consistent `margin-bottom` to links, `span`s, paragraphs, quotes, and `small` tags, (etc.) alike.
I shall challenge this star madness! I will say that I greatly dislike the border-box rule as I do dislike any reset, but I do have a proposal that gives the clearfixing advantages: display: inline-block;
address, article, aside, audio, blockquote, canvas, dd, div, dl, fiedlset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, hr, noscript, ol, output, p, pre, section, video {
display: inline-block;
width: 100%;
}
The element list are all the block level elements you want to target anyway. This is safer to use even on existing site as most of the changes to make things work again are quite minimal. Also you don’t get the disadvantages of hidden overflow, box-shadow and positioning content outside the container will work as normal.
And if you like border-box you can use it here to make things more convenient for you. Personally I’ve noticed I need border-box very rarely and I do take advantage of the default content-box behavior when doing layout so I’ve just grown to like it more.
In addition, I was able to give this rule to this site, remove pseudo element clearfixes and then use text-align: center; instead of margin: auto to center content… maybe changes to six or seven places to get the layout to look exactly as it is without the rule above.
Made a pen: http://codepen.io/Merri/det…
You said `overflow: auto` changes the behavior of collapsing margins, but does not turn them off completely. So how does this work exactly? When does it collapse and when doesn’t it collapse?
how make color the black box or use gradient in color ?
http://www.araicompvpn22.ir
What Cory Kaufman-Schofield is saying makes a lot of sense. These could become maintenance nightmare.
I’d say, it might be a good behavior.
But maybe we should change to.
This might be more of a drawback performance-wise (if CSS performance matters), but it might perhaps lessen the overflow resets.
Think hidden would be my preferred choice, then look for the bad sizing when testing. But can see the benefit of auto, sitting on a fence hurts in reality and metaphorically!