Doctype declaration
Older sites were built using XHTML or HTML4. The current standard for web development is HTML5. At the top of your page template your HTML page must have the HTML5 doctype declaration:
<!DOCTYPE html>
Using a proper doctype declaration is important because it ensures that web pages are rendered in "standards mode" for consistent and predictable results across all browsers guaranteeing support for the latest CSS styling techniques and feature rendering.
HTML tag and the "lang" attribute
Every page must have a page lang="en" language attribute on the html tag (external link). The lang attribute identifies the primary language of the page content, which helps screen readers pronounce content correctly and assists browsers with translation features.
<html lang="en">
Dynamically updating the lang attribute
If your page provides a user interface control (such as a language selector dropdown or button) that allows users to change the page language, the lang attribute value on the <html> tag must be dynamically updated to match the selected language. This ensures that assistive technologies correctly identify and announce the page content in the appropriate language.
The following JavaScript sets the lang attribute on the HTML element to Spanish:
document.documentElement.lang = "es"; // Update to Spanish
Character encoding meta tag
Every HTML page should include a character encoding declaration in the <head> section. This ensures that special characters, symbols, and international text display correctly across all browsers and devices.
<meta charset="UTF-8">
Viewport meta tag
The viewport meta tag is essential for responsive design. It controls how your page is displayed on mobile devices and ensures proper scaling when users zoom. Include this tag in the <head> section of your page template.
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Theme color meta tag (optional)
The theme-color meta tag allows you to customize the browser's user interface color on mobile devices. This creates a more integrated experience by matching the browser's toolbar to your site's color scheme. Note that this feature is only supported by some devices and browsers. See the theme-color browser support list (external link) for details on which browsers and devices support this feature. Include this tag in the <head> section of your page template.
<meta name="theme-color" content="#003366">
Canonical link tag
The canonical link tag helps prevent duplicate content issues by specifying the preferred URL for a page. This is particularly important if the same content can be accessed through multiple URLs (for example, with or without "www", with or without trailing slashes, or with URL parameters). Search engines use this tag to determine which version of a page to index and rank. Include this tag in the <head> section of your page template. The canonical URL value will be dynamically populated on each page using the template's canonical URL variable.
The canonical tag should consistently reflect the URL version that your server is configured to serve and redirect to via a 301 permanent redirect.
Example 1: using www or subdomain prefix for your website
The server is set up to redirect all traffic to the site using "www" or another subdomain prefix.
<link rel="canonical" href="https://www.example.com/page-url">
or:
<link rel="canonical" href="https://my.example.com/page-url">
Example 2: without "www" prefix for your website
The server is set up to redirect all traffic to the site without using "www".
This only applies to root or primary domain names. When using a subdomain refer to example 1.
<link rel="canonical" href="https://example.com/page-url">
Important: The canonical URL should always be the absolute URL (including the protocol and domain) and should point to the preferred version of the page. Each page should have only one canonical tag.
Title tag
Every page must have a unique title tag. The <title> tag appears in the browser tab, search engine results, and is the first thing announced by screen readers when a page loads. Make your titles descriptive and unique for each page. Include this tag in the <head> section of your page template. The title tag value will be dynamically populated on each page using the template's title variable.
<title>Creating accessible HTML page templates - Mass.gov</title>
Best practice: Title tags typically include the page name first, followed by a separator (such as a dash or pipe), and then the company or website name. For example: "Shop – example.com" or "Contact Us | Company Name". Keep titles under 60 characters for optimal display in search results and browser tabs.
Meta description
Each page that can be indexed by search engines should have a meta description. This description appears in search engine results and helps users understand what the page is about before clicking. Keep descriptions between 150-160 characters for optimal display in search results. Include this tag in the <head> section of your page template. The meta description tag value will be dynamically populated on each page using the template's meta description variable.
<meta name="description" content="Learn accessibility best practices for creating HTML page templates that meet WCAG 2.1 Level AA standards.">
Open Graph meta tags for social media (optional)
Use Open Graph meta tags for web applications and pages that might be shared across social media. Open Graph (OG) meta tags control how your content appears when shared on social media platforms like Facebook, LinkedIn, and messaging apps. These tags ensure your links are displayed with the correct title, description, and image. Include this tag in the <head> section of your page template. Only use template variables for the OG values if you are planning on using this tag on additional pages other than the home page.
The following are the essential Open Graph tags you should include:
<meta property="og:title" content="Creating accessible HTML page templates">
<meta property="og:type" content="website">
<meta property="og:url" content="https://www.example.com/page-url">
<meta property="og:description" content="Learn accessibility best practices for HTML page templates.">
<meta property="og:image" content="https://www.example.com/image.jpg">Best practice: The og:url value should match your canonical URL to ensure consistency across search engines and social media platforms.
There are many Open Graph protocol documentation (external link). For X-platform-specific tags, see X Cards documentation (external link).
Favicon (optional)
Including a favicon is considered a good practice because it allows sighted users to quickly recognize your brand. After creating the favicon image file and placing it into the root directory of your site or application, you can reference the file location inside the <head> tag using the following HTML code:<link rel="icon" href="/favicon.ico" type="image/x-icon">
Favicons support different sizes and have embedded metadata, after creating the Favicon image use a favicon generator like Faviconer to generate the favicon.ico file (external link).
"Skip to main" link
Your page template must contain a "skip to main" link. This link allows keyboard and screen reader users to bypass repetitive navigation and jump directly to the main content. The link should be the first focusable element on the page.
HTML for skip link
Place the skip link as the first element inside the <body> tag, before the <header> element. The link should reference the ID of your main content area.
<a href="#main-content" class="ma__skip-link">Skip to main content</a>
CSS for skip link
The skip link is visually hidden until a keyboard user tabs to it. When focused, it becomes visible at the top of the page. This CSS ensures the link is accessible but doesn't interfere with the visual design.
.ma__skip-link {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
.ma__skip-link:focus {
position: static;
width: auto;
height: auto;
}
Proper page structure using header, nav, main, and footer tags
Your page template needs to consist of proper structure using semantic HTML5 landmark elements. These tags serve as page "regions" for screen reader users, allowing them to quickly navigate to different sections of the page. The basic structure should follow this order:
<header>tag contains your site logo, navigation, and other header content<main>tag contains the primary content of the page<footer>tag contains footer information, links, and copyright
The "header" tag
The <header> tag typically includes your site logo, the main <nav> element, and other global header content that appears on every page. There should only be one main <header> tag per page.
<header>
<img src="/logo.png" alt="Company Name">
<nav aria-label="main">
<!-- Navigation links here -->
</nav>
</header>
The "nav" tag
The <nav> tag identifies groups of navigation links. Use it for major navigation blocks but not for every group of links on a page.
- The main navigation
<nav>tag should be nested inside the<header>tag when you have multiple navigation links. If your header contains only a single link, you don't need to use the<nav>tag. - Links inside a
<nav>tag need to be wrapped inside a<ul>tag and<li>tags. This provides proper list semantics for screen readers. - The current page link must have the
aria-current="page"attribute, indicating to screen readers that this link points to the page they are currently on. Use a page template variable to set this attribute. - Each
<nav>tag on the page needs a uniquearia-label(i.e.,aria-label="main"for the main nav,aria-label="footer"for the footer links). This text will be announced by the screen reader to identify the link grouping. - Important: Don't include the word "navigation" as part of the
aria-label, this will cause duplication when announced by screen reader technology. The<nav>tag is already announced as "navigation" by the screen reader. - The main navigation needs to work with browser zoom 400% and on mobile. This is typically achieved by showing a mobile menu button using a hamburger icon and the visible text label "Menu". When activating the mobile menu, the same navigation elements and order as on desktop should be displayed.
Navigation code example
<nav aria-label="main">
<ul>
<li><a href="/" aria-current="page">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/services">Services</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>Alternative for aria-label using aria-labelledby
You can also use aria-labelledby to reference the ID of a heading as an alternative to aria-label. This approach is particularly useful when a visible heading precedes the link grouping. The screen reader will announce the heading text as the navigation label.
<h2 id="footerLinks">Quick Links</h2>
<nav aria-labelledby="footerLinks">
<ul>
<li><a href="/privacy">Privacy Policy</a></li>
<li><a href="/terms">Terms of Use</a></li>
</ul>
</nav>
The "main" tag
The <main> tag contains the primary content of the page. This is where all page-specific content goes. There should only be one <main> tag per page. The <main> tag must have an id attribute that matches the skip link target.
If there are breadcrumbs, they should be part of the page template and be located at the beginning inside the <main> tag followed by the <h1> heading.
<main id="main-content">
<!-- Breadcrumbs if applicable -->
<h1>Page Title</h1>
<!-- Page content here -->
</main>
The "aside" tag
If you have global content that is repeated on each page that is only indirectly related to the page's main content, for example a side menu or related links section, you can include it within your <main> tag using the <aside> tag as a landmark. If your <aside> tag includes side navigation, follow all best practices outlined in the <nav> tag section.
<main id="main-content">
<h1>Page Title</h1>
<p>Main page content...</p>
<aside>
<h2>Related Links</h2>
<!-- Side content here -->
</aside>
</main>
Breadcrumbs
Breadcrumbs should follow best practices and a breadcrumb pattern (external link) that includes the following:
- Always wrap your breadcrumbs inside a
<nav>tag using the customaria-label="breadcrumb"to serve as a landmark for screen readers. - The
<nav>tag contains an<ol>(ordered list) tag, followed by<li>(list item) tags that wrap each breadcrumb link. - The current page link must have the
aria-current="page"attribute, indicating to screen readers that this link points to the page they are currently on. The current page can either be an<a>(link) tag or a<span>tag. Both are acceptable. Use a template variable for setting the current page attribute. - To separate each breadcrumb link, use a visual separator (i.e., forward slash, right arrow chevron). If you use an icon for the separator, make sure you add
aria-hidden="true"to the icon itself so that it doesn't get announced by screen readers. You can also use CSS styling to create a visual separator that won't be announced to screen readers. - Set up the breadcrumb text and links as variables in your page template.
Breadcrumb HTML code example
<nav class="ma__breadcrumb" aria-label="Breadcrumb">
<ol class="ma__breadcrumb-list">
<li class="ma__breadcrumb-item">
<a href="/" class="ma__breadcrumb-link">Home</a>
</li>
<li class="ma__breadcrumb-item">
<span class="ma__breadcrumb-current" aria-current="page">Services</span>
</li>
</ol>
</nav>Breadcrumb CSS code example
/* ===== Breadcrumbs ===== */
.ma__breadcrumb-list {
display: flex;
flex-wrap: wrap;
list-style: none;
padding: 0;
margin: 0;
gap: 0.5rem;
align-items: center;
}
.ma__breadcrumb-item {
display: flex;
align-items: center;
}
.ma__breadcrumb-item:not(:last-child)::after {
content: "/";
margin-left: 0.5rem;
color: #4a4a4a;
}
.ma__breadcrumb-link {
text-decoration: underline;
}
.ma__breadcrumb-link:hover {
text-decoration: none;
}
.ma__breadcrumb-link:focus {
outline: 3px solid #000;
outline-offset: 2px;
border-radius: 2px;
}
.ma__breadcrumb-current {
color: #4a4a4a;
}
The "h1" heading
<h1> headings should summarize the page content, must be unique, and there must be one <h1> heading per page. The <h1> is typically the first heading inside the <main> tag (after breadcrumbs if applicable). Use a variable for your h1 text if you include the <h1> tag in your page template.
<h1>Creating Accessible HTML Page Templates</h1>
The "footer" tag
The <footer> tag is where you include your global footer elements including images, links, and copyright statement. If you include links, make sure you wrap them in a unique <nav> tag. Each <nav> tag on the page needs a unique aria-label (i.e., aria-label="footer" for the footer links).
<footer>
<nav aria-label="footer">
<ul>
<li><a href="/privacy">Privacy Policy</a></li>
<li><a href="/terms">Terms of Use</a></li>
</ul>
</nav>
<p>© 2025 Company Name. All rights reserved.</p>
</footer>
Understanding headings and lists
While headings and lists are page-specific content rather than template elements, they are essential to understand when building accessible pages. These semantic HTML elements provide structure and meaning to your content, making it easier for all users to navigate and understand your pages.
Why use headings
Headings are essential for creating accessible and well-structured content. They provide a hierarchical outline of your page that helps all users, especially those using screen readers, navigate and understand your content.
When to use headings
Use short and descriptive headings to summarize the content of each section. Headings should only be used at the beginning of sections to identify content that follows. Don't use heading tags simply to style text that appears in the middle of a paragraph or isn't introducing a new section.
Heading hierarchy
Headings need to be ordered following their hierarchy (h1 through h6). Screen reader users navigate by headings to quickly find content. Skipping heading levels (e.g., going from <h1> to <h3>) can be confusing. Maintain a logical heading structure throughout your page.
- Every page must only have one
<h1>heading - Use
<h2>for main sections - Use
<h3>for subsections under<h2> - Continue this pattern through
<h6>as needed - Don't choose heading levels based on styling; headings must follow proper nesting rules and be used for structure, not visual design. Use CSS styles to control how headings appear visually.
Lists
Use semantic HTML list elements to structure related items. Screen readers announce the number of items in a list, helping users understand the content structure.
- Unordered lists use
<ul>and<li>tags - Ordered lists use
<ol>and<li>tags
<ul>
<li>First item</li>
<li>Second item</li>
</ul>
Template variables for page-specific content
When using a page template, certain elements need to be dynamically populated for each unique page. Setting up these elements as variables in your template allows for efficient page generation while maintaining consistency across your site.
Template variables
The following element values should be set as variables in your page template:
- Unique
<title>tag text - Canonical URL in the
<link rel="canonical">tag - Page meta description
- Open Graph meta tags for social media sharing (og:title, og:type, og:url, og:description, og:image)
- Current page link and
aria-current="page"attribute for navigation links - Breadcrumb links, current page link and
aria-current="page"attribute for breadcrumb links - Unique
<h1>heading text
Adding page-specific content
How you add page-specific content depends on your site architecture. There are two primary approaches:
Multi-page websites
For traditional multi-page websites where each URL represents a separate HTML page, page-specific content is typically managed through:
- Server-side templating: Use template engines (e.g., PHP, JSP, ASP.NET, Django templates) to dynamically inject content into your HTML template based on the requested page.
- Content management systems: CMS platforms automatically populate template variables from content stored in a database.
- Static site generators: Tools like Jekyll, Hugo, or Eleventy build static HTML pages from templates and content files during the build process.
Single page applications
For single page applications (SPAs) where content updates dynamically without full page reloads, page-specific content is managed through:
- JavaScript frameworks: Use frameworks like React, Vue, or Angular with client-side routing to dynamically update the HTML DOM (Document Object Model) including title tags, meta descriptions, and aria-current attributes as users navigate.
- API-driven content: Fetch page-specific data from APIs (Application Programming Interfaces) and inject it into your template structure.
- Important: Ensure single page applications (SPAs) update the document title using JavaScript (
document.title) and manage focus appropriately when content changes to maintain accessibility. Focus should be programmatically moved to the h1 heading tag showing a visible focus outline when new page content is loaded and the page title gets updated. Addtabindex="-1"to the<h1>tag so that it can receive programmatic focus.
Testing your page template
As a developer or tester, you can perform the following checks to ensure your page template is accessible.
Testing responsive layout
Test your page template using browser zoom up to 400% to guarantee proper "reflow" of all content and use the browser's developer tool to emulate mobile devices and tablets to ensure your content layout works for all test cases (desktop, tablet, mobile, browser zoom up to 400%).
Testing only using the keyboard
Tab through the page and make sure every interactive element (links, buttons, input fields, etc.) has a visible focus indicator (should be a rectangular shape around the element) that meets the 3:1 non-text contrast (external link) requirement. Verify that the skip link appears when you press Tab for the first time.
- Activating the "skip to main" link at the top of the page using the keyboard will move focus to the
<main>tag and show a visible focus outline around the main content. - Using the Tab key to navigate through the page template, verify that each interactive element (links, buttons, input fields, etc.) can be accessed and activated using the keyboard, is in the correct tab order, and has a visible focus outline that meets the 3:1 non-text contrast requirement.
Testing page structure
Use browser developer tools or accessibility testing tools to verify:
- The page has exactly one
<h1>heading - Heading hierarchy is logical (no skipped levels)
- All
<nav>elements have uniquearia-labeloraria-labelledbyattributes - The current page has
aria-current="page"on navigation and breadcrumb links - Landmark regions (
<header>,<main>,<nav>,<footer>) are present and properly structured
Testing with the ANDI tool
Using the ANDI tool (external link), you can test how a screen reader may announce your page structure, headings, and navigation. The tool helps identify issues with landmark regions, heading hierarchy, and link purpose.
Testing using a screen reader
Screen reader testing to be performed by accessibility subject matter experts.
Additional Resources
For help including design reviews, code reviews, or additional training contact the ACCESS team using the ACCESS team’s intake form.
- Accessible Page Template CodePen example (external link)
- Skip to Main Content CodePen example (external link)
- WCAG 2.1 Success Criterion 1.3.1 Info and Relationships (Level A) (external link)
- WCAG 2.1 Success Criterion 2.4.1 Bypass Blocks (Level A) (external link)
- WCAG 2.1 Success Criterion 2.4.2 Page Titled (Level A) (external link)
- WCAG 2.1 Success Criterion 3.1.1 Language of Page (Level A) (external link)
- WebAIM: Semantic Structure - Regions, Headings, and Lists (external link)
- MDN: HTML elements reference (external link)
- WebAIM Contrast Checker (external link)
- ANDI Accessibility Testing Tool (external link)