<div> (& Friends) Shouldn't Affect Layout by Default
3 minutes read · 2021-04-13It’s hard to overstate how successful HTML and CSS really are. Having evolved dramatically since their humble origins in the 90s to allow for a wide range of interoperable, accessible and aesthetically rich documents and experiences, these two technologies are now the bread-and-butter that underpins the critical path of a double digit portion1 of the world’s economy.
With that said, it’s only natural that after nearly 30 years of standards development some non-optimal decisions have been made, particularly when it comes to default behaviors.
One example of such a decision is box sizing. Over time, web developers and designers have (somewhat reluctantly) come to agree that IE was right: Elements should be sized by their external bounds (including padding and border) and not by their internal content bounds. Nearly every modern CSS framework ships with something like:
* {
box-sizing: border-box;
}
Another example is text layout. Mark Dalgleish has called it2 that the way line height works by default will likely be regarded in the same way once the leading-trim
CSS property is implemented and widely supported. I think he’s likely going to be right.
After giving it some thought, I believe I found a third case in which the default behavior we get out of the box is unfortunate: <div>
elements are displayed as blocks by default. With the long-standing Chromium accessibility bug around display: contents
3 finally fixed, I think it’s now time to consider adding the following rule to your next CSS file:
div {
display: contents;
}
Or, if you’re feeling particularly adventurous:
div, main, aside, header, footer, nav {
display: contents;
}
Why should you do this?
Here’s why I think this is a good idea:
- Having wildcard elements that you can use as a parent anywhere without affecting layout is extremely useful, particularly when developing reusable styles and behaviors. You can now think of
<div>
elements as Document Fragments that are persistent and also support styles and event handlers; - From a semantic standpoint,
display: contents
is a much better fit for<div>
thandisplay: block
. The HTML spec states: βThe div element has no special meaning at all. It represents its children.β 4 If that is the case, why should it affect layout at all? - Elements that actually represent blocks of text (e.g.
<article>
,<p>
,<h1>
,<section>
,<ul>
,<ol>
) gain renewed prominence. If you have to add a class to your<div>
to get it to display as a block anyway, you might as well reconsider and use something more fitting; - The resulting layout hierarchy is much flatter, making the
order
property much more useful, and responsive layouts with CSS grids much more flexible. Want to move a specific item from your header to after the main page content depending on the screen size? Yes, you can do that; - If you’re concerned about compatibility with existing libraries or components, you can still opt in to the old behavior for entire document subtrees with a descendant selector (e.g.
.legacy-ui div { display: block; }
), with minimal specificity implication; - A significant portion of your
<div>
s will end up being styled withdisplay: flex
anyway. π€·ββοΈ
- Digital economy report “value creation and capture: implications for developing countries” (PDF). United Nations Conference on Trade and Development. New York. 2019. Page 4.
[return] - https://twitter.com/markdalgleish/status/1332312486826000388
[return] - https://bugs.chromium.org/p/chromium/issues/detail?id=835455
[return] - https://html.spec.whatwg.org/multipage/grouping-content.html#the-div-element
[return]