Don't Rely on HTML Tags for Styling

When stepping into the world of frontend web development, it's easy to develop the habit of using headings (<h1>, <h2>, <h3>, etc...) to give text a font size.

It's a very quick pitfall web devs and designers fall into. While this may seem okay at first, you're digging yourself a hole by doing that. Your HTML tags are not your stylistic saviors.

While some tags gracefully balance semantic meaning with visual representation, others might lead you down a path of accessibility pitfalls.

Cases where it's okay to rely on the tags for styling

There are several HTML elements that serve a good semantic meaning for their corresponding style. The easiest example (that you'll most likely never screw up) are the superscript (<sub>) and subscript (<sup>) tags.

Superscript and Subscript tags (<sub> & <sup>)

Their semantic element gives them the visual meaning immediately. They are supposed to be used for presenting text as subscripts and superscripts (looking at you, using plain <span> elements for doing subscript styles!), which act as subtext descriptive to the text connected to it.

Strikethrough tag (<strike>)

Another good and common example is the (<strike>) for striking through text. Here, we'll also notice visuals match semantic meaning; you'll usually reach out and grab this element for decorating text with a strikethrough to indicate its outdated-ness irrelevance.

Don't base your heading levels on styling

One very common mistake I observe is relying on heading tags (<h1> through <h6>) for styling.

It's easy to get into the habit of doing that, since most web browsers, by default, style the font sizes of h tags from the largest to smallest. This causes us to naturally reach for the tag based on its font size to match a specific design.

Visually, this would seem fine, but it comes at the cost of accessibility and HTML semantics.

One of the crucial rules of web accessibility is that each page must have one and only one <h1> element on any given page.

Typically, the <h1> would be for the main heading of your page, usually in the hero section.

NEVER skip a heading level

Do not skip heading levels: always start from <h1>, followed by <h2> and so on.

The above is quoted from MDN's page on heading tags. It indicates that that you should always start with an <h1>. Then, when you start to have more headings, use <h2> elements after that. Then, if there are other headings that are lower level than <h2>, start using <h3> elements for those, and so on...

So, you let the document's semantic hierarchy decide your use of h tags. Then you style each according to your needs, not the other way around.

Example from Tailwind's landing page

There might be, in fact, some rare cases where you might want to use smaller font sizes for higher level headings. Take Tailwind's landing page as an example.

screenshot from Tailwind's landing page, annotated to show that a small heading is an h2 with larger text below it as a p tag

Here, the smaller text at the top - if we ignore the font sizes - sounds like the title of the section, more so than the larger text in the middle. Many people naturally will use <h2> for the larger text and an <h3> or <p> for the smaller text at the top.

In the above example, we notice something else...

Headings are rarely right next to each other

Since headings are realistically like bookmarks that mark specific sections or subsections of a document, it would usually not make sense to have headings directly beside each other without content in between. However that's not always the case, since sometimes you would want to start a new section with no paragraphs before your first subheading.

To end this post, I'd like to clarify that the rules that I mentioned are not hard rules, but accessibility guidelines.

This does not mean, though, that we should care less about these guidelines. Not caring for such issues will cause a sub-optimal experience for screen-reader users.