Part 5: Accessibility, SEO, and Modern HTML5

Introduction

Accessibility and SEO are not afterthoughts you bolt on at the end. The structural and semantic choices made in the first four parts of this series β€” using <nav> instead of <div class="nav">, writing meaningful alt text, labelling every input β€” are already accessibility and SEO wins. This part covers the remaining layer: ARIA attributes, meta tags, structured data, and modern HTML5 features that make pages more robust.

I built several static documentation sites and tool pages over time. The improvements in discoverability and usability that came from getting these details right were consistent and measurable.


Accessibility (A11y)

Why It Matters

Accessibility means building pages that work for people who use keyboard navigation, screen readers (NVDA, JAWS, VoiceOver), voice input, switch access, and other assistive technologies. In practical terms, accessible HTML is also more robust HTML β€” it works even when CSS or JavaScript fail to load.

Most accessibility in HTML comes from using the right elements. A <button> is already focusable, keyboard-operable, and announced as a button by screen readers. A <div> with an onclick handler requires significant extra work to replicate that behaviour.


ARIA (Accessible Rich Internet Applications)

ARIA attributes extend HTML's accessibility semantics. The first rule of ARIA: use it only when a native HTML element cannot do the job.

role

Overrides the element's implicit role when a semantic element cannot be used:

<!-- Avoid: use <button> instead -->
<div role="button" tabindex="0" onclick="doThing()">Click me</div>

<!-- Prefer: native element -->
<button onclick="doThing()">Click me</button>

When you genuinely need a custom component:

aria-label

Provides an accessible name when visible text is absent or insufficient:

Without aria-label, a screen reader would announce the navigation elements as "navigation", "navigation", "navigation" with no differentiation.

aria-labelledby and aria-describedby

Link elements to labels or descriptions elsewhere in the DOM:

aria-hidden

Hides elements from the accessibility tree (screen readers) while keeping them visible:

Do not use aria-hidden="true" on elements that receive focus.

aria-expanded

Indicates whether a collapsible element is open:

JavaScript toggles aria-expanded between "true" and "false" and removes/adds the hidden attribute.

aria-live

Announces dynamic content changes to screen readers:

  • polite β€” waits for the user to finish their current action before announcing

  • assertive β€” interrupts immediately (use sparingly, only for errors)


Keyboard Navigation

All interactive elements (<a>, <button>, <input>, <select>, <textarea>) are focusable by default. Tab moves focus forward, Shift+Tab moves backward.

tabindex

Value
Behaviour

tabindex="0"

Element enters the natural tab order

tabindex="-1"

Element can receive focus programmatically but is not in tab order

tabindex="1" (or any positive value)

Avoid β€” disrupts natural tab order

Allow keyboard users to jump past repetitive navigation:

The link is visually hidden until focused by keyboard navigation.


SEO Meta Tags

Essential Meta Tags

Title tag rules:

  • 50–60 characters for search results

  • Most important keyword near the start

  • Unique per page

Meta description rules:

  • 150–160 characters

  • Accurate summary of the page content

  • Not a ranking factor directly, but affects click-through rate

Canonical URL: Tells search engines the definitive URL for the page β€” prevents duplicate content issues when the same page is accessible at multiple URLs (e.g., with/without trailing slash, HTTP/HTTPS).

Open Graph Tags

The recommended OG image size is 1200Γ—630 pixels. It appears when links are shared on Slack, LinkedIn, Facebook, iMessage, and other platforms that render previews.

Twitter Card Tags


Structured Data (Schema.org)

Structured data provides machine-readable context about page content. Search engines use it to generate rich results (star ratings, FAQ dropdowns, breadcrumbs, etc.) in search results.

Structured data is embedded in a <script type="application/ld+json"> block:

Common @type values:

Type
Use case

Article

Blog posts, documentation articles

BreadcrumbList

Navigation breadcrumbs

FAQPage

Pages with Q&A content

SoftwareApplication

Tools and applications

Person

Author profiles

WebSite

Site-wide metadata


Modern HTML5 Features

<details> and <summary>

Native disclosure widget β€” no JavaScript required:

Add open to make it expanded by default:

<dialog>

Native modal element:

When opened with showModal(), the browser traps focus within the dialog and adds an ::backdrop pseudo-element for the overlay. This is full modal behaviour natively, without JavaScript libraries.

<output>

Represents the result of a calculation or user action:

<progress> and <meter>

<meter> changes colour automatically based on low, high, and optimum thresholds.

<template>

A client-side content template β€” not rendered, but available to JavaScript for cloning:

data-* Attributes

Store custom data on elements without abusing class or id:


Performance Attributes

loading on <img> and <iframe>

defer and async on <script>

Use defer for application scripts. Use async only for independent scripts (analytics, tracking) that do not depend on other scripts or the DOM.

Tell the browser about critical resources early so it can start fetching them sooner:


Final Checklist

Before shipping any HTML page:

Document

Structure

Images

Forms

Accessibility

Performance


Summary

Feature
Key Point

ARIA roles

Use only when native elements cannot do the job

aria-label

Name elements without visible text

aria-live

Announce dynamic content to screen readers

Skip links

Let keyboard users bypass navigation

Meta description

150–160 chars, unique per page

Canonical URL

Prevent duplicate content in search indexing

Open Graph tags

Control social share previews

Structured data (ld+json)

Rich search results

<details> / <summary>

Native disclosure without JavaScript

<dialog>

Native modal with focus trap and backdrop

data-* attributes

Custom data storage on elements

defer / async

Non-blocking script loading


Series Complete

This series covered the full HTML foundation:

Part
Topic

Document structure β€” DOCTYPE, head, body, metadata

Semantic HTML β€” headings, text content, section elements

Links, images, and media

Forms and user input

Accessibility, SEO, and modern HTML5

From here, CSS handles visual presentation and JavaScript handles behaviour β€” but both build on the structural and semantic foundation covered in this series.

Last updated