Div divisiveness
The <div>
is the most versatile and used element in HTML. It represents nothing, while allowing developers to manipulate it into almost anything by use of CSS (for styling), JavaScript (for functionality) and ARIA (for accessibility information).
This versatility allows for <div>
s to be used for many purposes, but unfortunately this permissiveness can easily result in misuse. When not used carefully, the end result could either be <div>
soup, content missing semantic meaning, inaccessible interactive controls, or some combination of all.
It’s relatively straight forward to identify instances of flagrant misuse (more on that later). However, it has gotten to a point where people will come across entirely valid use cases, or at least instances where a <div>
’s use is benign, and it is pointed out as being an example of inaccessibility. “Someone should have used semantic HTML instead!”
Well. Hold up there a minute. Before we turn up our collective noses at the use of <div>
s, remember that context matters.
Yes, people should use semantic HTML whenever possible. But, let’s be careful about making it seem like any use of a <div>
is bad… or, if swapping one out for a more semantic element would actually even move the accessible needle.
Before we talk about that, let’s rewind a bit and briefly look at where the <div>
came from.
The semantic (de)evolution of <div>
Originally introduced in HTML 3.0, the <div>
element represented a “division” of content. As originally written:
The DIV element … represent[s] different kinds of containers, e.g. chapter, section, abstract, or appendix.
In HTML 3.2 <div>
and <center>
were defined as essentially the same element.
<center>
was treated as a "shorthand" for <div align=center>
, with the element becoming part of the HTML specification because Netscape had introduced the element prior to implementing the standardized <div>
element. Cow paths be paved... even if they eventually lead nowhere.
What’s interesting here is that <div>
’s original definition could be looked at as a very early idea of what would someday become sectioning content in later versions of HTML. I’m not saying that’s what the intent was at the time, but clearly HTML lacked specific elements for common sectioning/grouping containers. A <div>
or <center>
element served as an alternative to people chucking everything into <table>
elements, at least.
A <div>
in HTML 4.01
By HTML 4.01, the definition of <div>
had become less explicit in mentioning what it could represent, but rather was to be used as a general tool for structuring content. In HTML 4.01 we also saw the loss of <center>
(womp womp), but the introduction of the <span>
element. The <div>
being used for block-level structuring, while <span>
elements used as generic containers for inline content.
However, without any specific semantics for the elements, that meant there was no programmatic way to convey what the elements would be used for. At least not in a way that could be interpreted by assistive technologies. Keep in mind that HTML5 was where WAI-ARIA support was introduced, along with the newer sectioning (article
, section
, nav
, etc.) and grouping elements (main
) that can be used to structure pages, rather than just divs.
Modern <div>
-finition
You know… like “definition” but… with a <div>
… I’m sorry. I just can’t delete it…
With HTML5, and as it is today per the HTML Living Standard, a div
is defined as:
The
div
element has no special meaning at all. It represents its children. It can be used with theclass
,lang
, andtitle
attributes to mark up semantics common to a group of consecutive elements. It can also be used in adl
element, wrapping groups ofdt
anddd
elements.
HTML goes on to note:
Authors are strongly encouraged to view the
div
element as an element of last resort, for when no other element is suitable. Use of more appropriate elements instead of thediv
element leads to better accessibility for readers and easier maintainability for authors.
MDN provides further developer guidance for <div>
.
In HTML AAM, a <div>
is mapped to the generic
ARIA role. Similarly to HTML’s <div>
, ARIA defines generic
as:
A nameless container element that has no semantic meaning on its own.
Representing nothing
By representing nothing, a <div>
is free to be anything. A <div>
is essentially chaotic neutral and can easily pivot between valid and invalid use, per the whim of the developer that uses it.
Reasonably, this might be a bit hard to track for some who are expecting a clear right and wrong way to markup accessible content. For instance, consider the following:
<div>Hi there, I'm a paragraph of content!</div>
What sort of problem is using a <div>
as a ‘paragraph’ going to create? We’ll touch on that again later, but for now let’s look at some <div>
use cases that are more easily identifiable as invalid or not.
Clear misuse of <div>
The most common example for how not-to-div is when used to create interactive content such as “links” or “buttons”:
<div class=button onclick=foo()>
Click me!
</div>
Without getting too deep into it (you can read this role=button
MDN article for that), a <div>
is not an interactive element by default. Styling alone does not make a <div>
a “button”, for instance. Nor will even adding click handlers meet all the requirements for re-creating accessible buttons.
But, if someone goes to all the trouble to make their div-button
have all the necessary keyboard accessibility, expose itself as a “button” and any other applicable state (disabled, presed, expanded, etc.), and they even went to the trouble of making it behave nicely with Windows High Contrast Mode. Well, good on them. Sure, this was far more effort than using a native <button>
element. But if it’s done right, then there’s nothing really wrong about it, is there?
Structural misuse
Now, regarding structural content containers, a quick way to determine if a <div>
is being used in place of a more semantic element might be quickly determined by reviewing its visual representation. Alternatively, if looking at the underlying source code, the classes (as long as they’re not gobbledygook) or IDs that are used on the elements:
<body>
<div class=header>
...
</div>
<div id=main>
...
</div>
<div class=footer>
</div>
</body>
While incredibly simplified, there are websites being built today that resemble the above markup example.
These are instances of misuse that are both easy to identify, and rectify. Whether that be by changing the <div>
elements to their more appropriate HTML elements (e.g., <main>
). Or, by employing ARIA to assign any necessary role, state and property attributes where necessary (e.g., <div role=main>
).
This (<div>
) is fine
Let’s look at two examples of when a <div>
is perfectly acceptable to use.
To start, consider a series of paragraphs or other elements that are written in a language that differs from the primary document (web page). A <div>
could be used, with a lang
attribute specified with necessary the language tag, to contain all this content and identify it as being of the appropriate language.
<div lang=fr>
<h3>...</h3>
<p>...</p>
<ul>
<li>...
<li>...
<li>...
...
</ul>
...
</div>
In the above example, using the wrapping <div>
to specify the lang
attribute is far easier than specifying it on each individual element. Also, assuming this grouping of content is unique to the current page, a <div>
is a perfectly acceptable element to use here. More on that in a bit…
Next, a <div>
is also absolutely OK to use when structuring content for styling purposes. For instance,
<main>
<div style="display: flex; ...">
<div style="flex: ...">
<h1>...</h1>
<!-- sub-heading / meta data could go here -->
</div>
<div style="flex: ...">
<!-- social follow links -->
</div>
</div>
<!-- other semantic elements / content go here -->
</main>
In the above, <div>
s are used to contain the <h1>
and other intro-related content to the primary topic of the page. Flexbox is then used to layout the content as needed (style
attributes are used for simplifying the example).
“But wait”, you might say, “isn’t using <div>
s to structure content a bad thing? Shouldn’t those examples have used more accessible elements?”
Sometimes, sure. As mentioned, <div>
s are misused a lot, so it is not unreasonable for someone to initially think this. However, for the above examples… well, more context is necessary. This is accessibility related, after all.
A generic
by any other tag name…
Beyond <div>
, there are actually a good handful of more semantic HTML elements that are exposed as generic
. To name a few, <address>
, <kbd>
, <abbr>
, and <body>
are implicit generic
elements.
Going a step further, there are other elements such as <header>
, <footer>
and <section>
where under very common markup conditions, they too are exposed as generic
elements. The reason for this is because accessibility roles have very specific purposes. HTML elements also have well defined semantics to indicate how developers are supposed to use each element, but not all HTML elements have an exact one to one match with how their implicit ARIA semantics are defined.
For instance, a <header>
maps to role=banner
when scoped to the <body>
element. This means that so long as no <main>
element, sectioning content element, or sectioning root element comes between the <header>
and the <body>
, then <header>
will be exposed as a banner
landmark.
With HTML though, a <header>
is not always a banner
. A <header>
is perfectly valid and is semantically appropriate to use as a descendant of an <article>
or a <section>
. However, in that context it does not represent a landmark containing mostly site-oriented, rather than page-specific content.
Thus, if <header>
is not scoped to <body>
, it becomes a generic
element, just like a <div>
. This holds true for the <footer>
element as well.
<body>
<header> I'm a banner! </header>
<main>
<header> I am NOT a banner! </header>
...
</main>
</body>
Regarding the <section>
element, it actually starts off as a generic
. It can be exposed as a region
landmark, so long as the element is provided an accessible name. For instance:
<!-- a generic section -->
<section>
<h2>...</h2>
...
</section>
<!-- a 'region' landmark -->
<section aria-labelledby=h>
<h2 id=h>...</h2>
...
</section>
The reason <section>
behaves this way was due to rampant overuse / misuse of the <section>
element. “Section all the things!”
Landmarks are meant to define particularly important areas of a web page, and a region
landmark is really supposed to be used only when a more descriptive landmark is not appropriate.
Having a page full of region landmarks would make the accessibility of that page worse, as if “everything” is marked up as being important, then really, nothing is important.
Hmm… Sounds a bit like <div>
, huh?
The severity of semantics
Regarding the “fine” <div>
examples, sure those could have used a <section>
and <header>
element to be the containers for each of those examples, respectively. Semantically, that would have made sense. However, their use would not expose any role difference than the <div>
s already in use.
Similarly, let’s take a look at that question I raised about a <div>
serving as a paragraph of content.
If your initial thought was that it won’t programmatically be exposed as a paragraph to screen reader users. Well…
See the Pen i'm a paragraph by Scott (@scottohara) on CodePen.
In HTML a <p>
is but one way to define a paragraph. Implicit paragraphs are created with each new ‘block’ of text in the page. So, similarly, before playing the “use semantic HTML and you get accessibilty for free” card, it’s important to think about the reality of the user impact, and if that card is really worth playing at this time. Would using explicit <p>
elements be better? Yes. Would it help ensure user style sheets would have a consistent hook to modify paragraphs? Also yes. Is this what people are actually talking about when calling the use of a <div>
over <p>
? Generally not.
There are so many complex accessibility issues we need to be concerned about. Having developers swap out <div>
s for other equally generic elements, or elements that might provide minor improvements for users, when there is a backlog of far more pressing issues to resolve… I don’t know. I think there’s a severity level here that is being glossed over.
And to be absolutely clear, I am not advocating for the use of <div>
s when semantic elements would be more appropriate.
Use semantic HTML. Use semantic HTML as a default. Just maybe also don’t worry so much about if other people aren’t using semantic HTML if what they’ve built doesn’t actually result in accessibility issues? Or, if calling out the lack of semantic HTML, be very specific about what the actual problem is. The semantics of HTML are not just about accessibility. They’re useful for other tools that consume HTML, and can be far easier to understand for fellow developers modifying markup than a sea of never-ending <div>
s.
Remember, <div>
s are meant to represent nothing. They can be made into just about anything… just don’t make them into soup. I think we can at least all agree that’s not what <div>
s are for.
Post-outro: Concerning soup
In a previous draft I had called out Eric Bailey’s presentation on the intersection of performance and accessibility.
My post changed considerably and I couldn’t figure out where to put this without going onto some other tangent. So here it is anyway. I suggest reviewing his slides for more information on this particular topic - mostly because I don’t want to write about stuff Eric has already covered so well.
This ended well. I think this ended well…
yeah. It’s fine.