January 10, 2016

Semantic HTML5 elements and the h1 element

Talk about a confusing combination!

Semantic HTML5 elements and the h1 element

Talk about a confusing combination!

While working on my capstone early in the morning (something I should never do but keep doing it anyway) on 16 October, 2015, I noticed the test <h1> headers I placed on a page were smaller than the <h2> elements and roughly the same size the <h3> headers! Despite not possessing complete clarity in thinking and logic, I decided to hunt down the culprit. Because the strange phenomenon was occurring in Firefox, Chrome, IE, and MS Edge as well as mobile browsers, I started the hunt by searching my site SCSS for something that could be causing it; perhaps I had written an overzealous selector. Though I surprisingly could not find any rogue styling, I was determined to find the cause. That was when I remembered something: I had dealt with certain headers being smaller than others a long time ago on a different project. I also remembered the culprits: the semantic elements newly introduced with HTML5 to help structure and layout a page (instead of using <div>s everywhere).

I quickly changed all instances of the new elements to “plain old” <div>s and reloaded the page. Suddenly, the faulty headers snapped back to their proper size. With the issue solved, I turned off my laptop and went to bed wondering what exactly was going on and what could be done to remedy it.

The next day I looked into the matter, whipping up a demo page to compute the font sizes of headers when contained in the various semantic elements and compare it to a div wrapper (as a baseline) and a semantic element nested in a semantic element. You can find the demo on CodePen. Throughout the rest of this admittedly more observational post, I will be frequently referring back to the demo as I discuss my findings, so keep that tab open! ;)

One thing I should note: I could be totally wrong about all of this. I am not an expert in any one topic or area. This is merely my deduction based on observations and experiments. If you do happen to be an expert and have an accurate explanation, feel free to state it and teach me a thing or two!

As we can see, our baseline <div> wrapper renders a h1 at 32px, a h2 at 24px, and a h3 at roughly 18.7px (do note all stated values may be slightly different depending on the browser you are using). We can notice the <header>, <footer>, and <address> wrappers behave the same way as a <div>. Upon reaching the <article> tag, we notice it and the remaining semantic elements render the <h1> at 24px, <h2> at 24px, and <h3> at 18.7px. This also happens when we wrap a <header> element in an <article> tag except in Internet Explorer and Microsoft Edge where it renders as the control <div> (note there are plenty more combinations I am not testing in this demo.) Upon reaching the final demo, wrapping <aside> in a <section>, we see the <h1> is now the same size as the <h3>. What gives?!

An h1 element in various wrappers, as rendered in Microsoft Edge

Now that we have proven the using the browser’s own APIs (see the “font-size calculation code” section of the demo) that most of the semantic elements are decreasing the size of our <h1> elements, we get to determine why this is happening. A quick search of the W3C and WHATWG HTML5 specs for the <article> tag (using this tag because it is the first one in the demo to exhibit the strange behavior) give no mention or implied reference (that I can see) to reducing the header sizes. That leaves us with devising our own reason.

Considering the purpose of the semantic elements is to logically divide page content into sections and the names of the available tags, we could assume <header> and <footer> do not affect the font size because they are “primary” page elements and the others are “secondary” elements and logically have a smaller font size so as to not appear larger or more important than the primary header. If you think of a newspaper, the paper name is the largest text on the page. The second largest text might be each article’s headline. If we imagine the paper name as an <h1> in a <header>, the rest of the page layout is in a <main>, then each article is wrapped in an <article> and each headline an <h1>, then shrinking of <h1> to the size of an <h2> makes sense.

But hang on for a second. In web design, you are not supposed to use the same header level for two items unless each item has equal importance. This is done for good a11y and screen reading support. Obviously an individual article’s headline is not near as important as the paper name, thus we are breaking semantics. The headline should use an <h2>, but that does not work because the headline is the most, not second, important thing in the article. Do you start to get the picture?

Because we technically should use an <h1> for the headline but not conflict with the paper name (or in the case of a website, the site name or logo), any <h1> element wrapped in an <article> or like tag is automatically downscaled to the proper size relative to the page layout. In this way, we are semantically correct in using an <h1> for the headline while not conflicting with the utmost important header. The same goes for nested elements (the final demo showing the <h1> to be the same size as an <h3>).

We now know why the semantic HTML5 elements decrease the size of the <h1> element. Looking at the reasoning behind it, it sure seems as if Internet Explorer and Microsoft Edge are not “doing it right”, huh? :P