Use valid markup in web pages

Applicable Role(s): Developer

Overview

Valid markup helps assistive technologies interpret your site correctly and predictably. Users might also have different versions of certain assistive technology, or choose different operating systems or browsers. Whatever tools they use, web content needs to be written validly so a variety of people can use your site.

Best Practices

Ensure that element ID attributes are unique

ID values must be unique and not be reused on the page. If you have elements that need to share a style or characteristic, the class attribute is a better choice for that need.

Include opening/closing tags on elements that require both

This ensures element are nested appropriately and styles don't get applied to other elements accidentally. If using a heading tag, a link tag, a paragraph, etc., these need to be closed with a corresponding tag with a slash (<h1>...</h1>)

Make sure elements are nested properly

Example: lists (ol/ul) can only contain list item (li) children, and no other element.

Don't use deprecated markup

Deprecated tags will not have as much support as HTML5 elements and may not convey your content correctly.

Pattern Examples

Self-Closing Tags in HTML5

Most elements require closing tags, unless they are one of the following tags:

<area />, <base />, <br />, <col />, 
<embed />, <hr />, <img />, <input />, 
<link />, <meta />, <param />, 
<source>, <track />, <wbr />

Example: Assigning IDs

Inaccessible Pattern 1

<nav aria-labelledby="example-nav">
  <h2 id="example-nav">First nav area</h2>
  (nav items...)
</nav>
...
<nav aria-labelledby="example-nav">
  <h2 id="example-nav">Next nav area</h2>
    (more nav items...)
</nav>

Using the same ID for multiple blocks can create issues for naming elements of a page correctly. In this example, if headings share an ID, each navigation region would likely be named "First nav area", even if it's not the first nav area.

Accessible Pattern 1

<nav aria-labelledby="example-nav-1">
  <h2 id="example-nav-1">First nav area</h2>
    (nav items...)
</nav>
...
<nav aria-labelledby="example-nav-2">
  <h2 id="example-nav-2">Next nav area</h2>
    (more nav items...)
</nav>

These headings IDs don't share the same value, which means the navigation can refer to its corresponding heading correctly. This means multiple regions of the page are uniquely named and reduces confusion for users.

Inaccessible Pattern 2

In an example form, with two separate inputs:

<label for="same-id">First Name</label>
<input type="text" id="same-id" />
...
<label for="same-id">Last Name</label>
<input type="text" id="same-id" />

Since these inputs have the same ID, assistive technology can't tell which label should be used for each input.

Accessible Pattern 2

<label for="id-1">First Name</label>
<input type="text" id="id-1" />
...
<label for="id-2">Last Name</label>
<input type="text" id="id-2" />

Because each input has a unique name, the label associations are clear and assistive technology can correctly provide the right information for the input.

Example: Naming IDs

Inaccessible Pattern

<label for="name">
 Name (4 to 8 characters):
</label>
<input type="text" id="Name" name="name"
 required size="10">

Some accessibility APIs may not associate this label to this input because 'name (lowercase)' in the label for="" attribute is not identical to 'Name (uppercase)' in the input ID. This means in those APIs, this input would not have a proper name.

Accessible Pattern

<label for="name">
 Name (4 to 8 characters):
</label>
<input type="text" id="name" name="name" 
 required size="10">

This label and input are properly associated, because the label for="" value and input ID are identical.