Building a more accessible web with semantic HTML
Broadly speaking, developers don’t look forward to accessibility audits. Nor do we purposefully build tools and sites that are harder to use for some people than others. Most of us would admit that we know we should learn more about accessibility when we have time. Today I want to make a case for semantic HTML as a way to unlock the door to building accessible apps from the ground up. Accessibility is something that we must get better at slowly, not overnight, and if we do, we will end up saving time and become stronger developers.
Semantic HTML is the fancy way of saying you’re using HTML purposefully and that the elements you're using are named for their use cases, making it easy to read. You’re probably writing some already—when you use an unordered list (
<ul>) or a
<nav> element for your site navigation are good examples. Beyond that, if we reference MDN’s cheat sheet of available elements we’ll see that there’s something for almost every part of a view you’ll ever write that can better describe what it is you are doing besides the all encompassing
To start, we have our HTML elements that will classify areas of the page—these are called content sections. If we look at our view as an outline for a term paper, these sections will guide your intro, body, conclusion—regardless of where they are on the page. By using these elements to organize our views we’re telling screen readers where they are in the app logically AND we’re giving search engines valuable information to help users find our sites.
An example of this would be using a
<main> tag, which is semantically signifying the main area of your page. By using this instead of
<div id=”main”> we’ll see a few different benefits. The first is letting screen readers navigate with their preferred tooling. This is important because it allows them to skip any unnecessary content above this point to get to the purpose of their visit.
The other quick benefit of this is that it helps the rest of our team know where they are in the code. Semantic HTML by definition allows us to logically name things according to their uses, so
<main> becomes very clear that you’re in the central area of your page without any other indicators or wondering if that
#main id is the main navigation or the main post. Now imagine if we follow this pattern for all our markup! In a small but meaningful way, doing this throughout our HTML we’ll help readability internally as well as for users.
We can also have an immediate positive impact with our headings. Even though it’s common knowledge that a page should have one h1 and that it should be the most important bit of info on that page, a surprising number of sites still use an image for the h1 and leave out the text completely! While this is fine for our sighted users, it’s far from ideal for screen readers, translations, and web scrapers. The reason it’s so important to stick to this heading structure is ultimately so more people find your site and when they get to it, they are told, whether that’s visually or auditory, where they are.
Think of it like a table of contents for your site. Most of us aren’t writing Wikipedia clones or blogs where outlines are more straightforward with the content. But, if we start to try and accurately create these tables of contents for our work, we’ll start seeing the organizational efforts pay off. Ultimately, we are all telling stories with our UI and to tell them effectively we need to not skip sections, which is essentially what we are doing when we jump from h1 to h3 so that we can have the right “size” heading visible on the page.
When we skip around like this we’re blocking out context for anyone using a site any way other than exactly like you are and preventing organic SEO from getting a nice boost. Instead, we should make sure we’re going in order with our given heading tags and using css to style the heading how we see fit. Rather than having
.sectionHeading. This will allow your classes to flexibly relate to your heading structure without getting tied to their element name, giving us leeway to keep our headings in order and read as what they truly are in any method of accessing them.
To really drive this idea home, try scraping some websites’ heading structures using this HTML outliner tool from gsnedder, or grab an extension like ‘headingsMap’ for your preferred browser and see how your understanding of the site changes based on what that output is. Some sites that structure HTML well are Wikipedia, Pitchfork, and Rotten Tomatoes; conversely almost any news site or local dog grooming WordPress site does less well. Since we are all learning I’m not going to include links to poorly done outlines, but I trust you will discover things on your own.
By just inspecting sites you visit throughout the day you’ll start to see patterns and how, if we pay attention to headings and sketch out importance levels with our UX pros, designers, and content writers, we’re going to have a better understanding of the app holistically that will enable all of your teams to be more cohesive.
Finally, I’d like to mention buttons. I know sometimes we inherit a design where something’s clickable, but doesn’t look like a button, so we use a
<div> because it’s easier for us to style. However, we need to remember that buttons are there for very specific reasons that we shouldn’t neglect! Let’s look at the below code—you’ll see a
div that’s mocked up as a button as well as a native HTML
To achieve the same functionality that’s native to the
<div> must have a whole slew of things added to it. By just using the
<button> element instead we’re writing a lot less code and ensuring that browsers support keyboard and screen readers for it inherently. Who doesn’t want that? So while yes, you will have to write some style overrides, it’s not that bad if you consider how much extra you get out of it.
Using semantic HTML like this for better accessibility might sound overly simplified, but the more we exercise these muscles the better off we are as developers. If we can start with these base areas we’ll naturally expand to write more inclusive forms, modals, and accordions, and we’ll be that much more inclusive. By doing this, we’re giving ourselves a fundamental understanding of how elements are intended to work in browsers. This will open doors for us to comprehend the world of
- Aria (semantic aria from Google)
- A11y best practices (WCAG standards)
- Focus traps (keyboard trappings explained on WCAG)
- Screen readers (Codeacademy)
All while making our code more inclusive to our fellow developers who have to read what we write and as a bonus, it’ll improve SEO! By taking a little extra care as you build your components to use named elements, you’re going to cut out much more time in upkeep and potential auditing bugs.