Skip to main content

Semantic HTML


As we discussed in the Introduction to Web Accessibility article, accessibility for web applications depends at its core in using the correct element for the job. Whereas in Windows development, the developer may write to the API to set the accessibility information on a control, in situations where the deployed browser and Assistive Technology (AT) base does not support ARIA, the HTML developer is limited to the intrinsic accessibility role information provided by the element. This aspect of accessibility is read-only for the web developer.

For more on ARIA, see the Introduction to ARIA article. For details on how to handle situations where some, but not all browsers and AT in your organization support ARIA, see the Accessibility and Legacy Browsers article.

The accessible role for an element defines what it is, whether it’s a table, a link, a textbox, or any of a number of other elements. This information is critical for assistive technology (AT). Absent the correct role, the AT user may well have no idea what the element in question is, or even that, say, a link is on the application page. In this sense, the role is a semantic or programmatic representation of what the visual user sees. Blue, underlined text means a link. Large text demarcating a section of a document means a heading. This semantic information tells the AT user what the application does and how it’s organized.In this article, we’ll talk about the important HTML elements to use to provide the proper role.

There is a second, crucial semantic piece of information, the accessible name. While the role tells AT what the element is, the name tells who it is. So, a checkbox with the associated text of “show details” tells the user two things: (1) that it is a checkbox, and (2) that checking it causes the application to show details. While the role is read-only and determined by the HTML element, the name must be explicitly provided by the user.In this article, we’ll also discuss setting the name on various HTML elements.


As mentioned above, the role of an element is provided intrinsically by the element itself. Properly specifying the role is entirely a question, therefore, of using the right element for the job. Fortunately, there is a fairly limited number of HTML elements for which role is crucial, generally falling in the categories of interactive elements (forms and links) and certain structural elements (lists, tables and headings). 

It’s important to emphasize that it’s the actual HTML element that matters, not how it appears visually. With CSS and script, it’s possible to make a generic container element, such as a span, look and act just link an HTML link (A HREF). No matter how hard the developer may work to apply CSS to make the span look like a link, and no matter how much script he may write for that element to make it respond to mouse and keyboard events, under the covers, it’s still a span, and that’s what gets reported to many AT devices. The AT user has no idea that it’s actually a link. The correct semantic HTML must be used , or added via ARIA where that is available.

Once the proper HTML is used, there is a great deal of visual “look and feel” that may be added using CSS. Special hover effects, font color and size, background colors, and such may be added to the HTML to give it just about any visual effect, but at its core, the element must be semantically correct. 

Before we go into detail on the various important roles, there are a few other benefits of using semantic HTML which should be mentioned. First, the element provides the appropriate intrinsic display characteristics “for free”.  A link specified with the A HREF element automatically gets the look, feel and behavior of a link, as well as the intrinsic CSS hooks for the various link states (hover, active, visited, etc), so the work that the developer has to do is minimized. Secondly, the element gets the right tab stop and tab order, right out of the bag, with no additional work required.  Thirdly, semantic HTML lends itself much better to automation, such as for testing.  If all subheadings in the document are specified with H2 and H3 elements, for example, then the developer just has to query the document for these elements or tag names  -- such as with document.getElementsByTagName(“H2”) – and he knows that he will get subheadings and nothing but subheadings.  Finally, using semantic HTML usually results in simpler HTML and smaller file sizes, as the elements require fewer CSS class names used as differentiators and fewer CSS rules and attributes, since the intrinsic display of the element provides quite a bit. 

Let’s now look at role information for the most important elements.


By far the most common interactive element in web applications, links provide the user with the ability to navigate from one page to another by clicking on some text and/or an image.  Links must be specified using the A HREF element, and not any other, such as SPAN (which has been more or less commonly done). 

Figure 1:  a link and a span styled and scripted to look and behave like a link

Two lines of blue underlined text.  The first line says I am a link and the second line says I am a span


While the two “links” look and behave the same way for a mouse user, the second is not actually a link, and will not work for a keyboard or screen reader user.

<p><a href="#" onclick="OnLinkClick()">I am a link</a></p>

<p><span class="link" tabindex="0" onclick="OnLinkClick()">I am a span</span></p>


HTML forms are the primary means by which users interact with the application data.Forms are ubiquitous across web applications, ranging from a single textbox and submit button to complex data entry forms with dropdown lists, checkboxes, radio buttons and multi-line textboxes.Using semantic HTML for forms is crucial for allowing AT users to interact with web applications. Each of the form elements has important accessibility information that is reported to AT devices. 

The form itself should always be specified with the FORM element. This wraps the form elements in a single unit which itself has intrinsic submission and keyboard behavior.Single-line textboxes should be INPUT TYPE=”text”, and multi-line textboxes, TEXTAREA.Radio buttons are INPUT TYPE=”radio” and checkboxes are INPUT TYPE=”checkbox”.  Dropdown lists use the SELECT element.  Forms should also always have a submit button, INPUT TYPE=”submit”.  A reset button, which sets all the form element values back to their default state is often very useful, INPUT TYPE=”reset”.  Finally, there is a grouping element for forms, the FIELDSET, which may be used to group related elements, such as a set of radio buttons.

A form with a dropdown labled Languge that is currently set ot English, a checkbox labled spell checker, a set of radio buttons labeled Color Theme with options red, white, blue, a textbox labeled special instructions, and submit and reset buttons




  <label for="lang">Language</label>

  <select id="lang"><option>English</option><option>French</option><option>German</option></select>



  <input type="checkbox" id="spell" onclick="ToggleTest(this);" /><label for="spell">Spell Checker?</label>



  <legend>Color Theme</legend>

  <input type="radio" name="theme" id="theme_red" checked="true" /><label for="theme_red">Red</label></select>

  <input type="radio" name="theme" id="theme_white" /><label for="theme_white">White</label></select>

  <input type="radio" name="theme" id="theme_blue" /><label for="theme_blue">Blue</label></select>


<div><label for="special">Special Instructions</label><input type="text" id="special"></textarea></div>

<div><input type="submit" value="Submit" /> <input type="reset" /></div>



Lists are fairly common and quite useful HTML groupings.While one might usually think of lists in terms of bulleted lists or numbered lists, the most commonly used, semantically speaking, a list is any set of grouped, hierarchically-related pieces of information. With this definition, a toolbar is a list of links, a menu is a list with (usually single) sub-lists, and a tree is a list with any number and depth of sub-lists. For a numbered list, use the OL (ordered list) element.For unnumbered “lists”, the unordered list, UL element provides the appropriate role.It both groups all the related elements together semantically, and also reports information about the depth and relative position of any item in that list.Many AT devices also provide special list navigation features that allow the user to quickly move around a list while keeping track of where he is, just as a visual user would. 

This toolbar is a good use of the grouping behavior of lists. 


The HTML for the tool bar introduces the model used in all list-based examples, a list element with a few child list items, each containing a link. This is a sound semantic approach to all hierarchical, flat or nested, groups of links, be they in a single list (toolbar), in popup child lists (menus) or in expandable lists (trees).

There is one WAI-ARAI role and one attribute for a toolbar. The "toolbar" role identifies the UL element as a toolbar to AT, and the aria-label attribute gives a friendly name ("Navigation Bar", in this case) to the toolbar for AT devices.

<ul class="toolbar" role="toolbar" aria-label="Navigation Bar"

  onkeydown="OnToolbarKeydown(event);" onclick="OnToolbarClick(event);">

  <li class="first"><a href="File.htm">File</a></li>

  <li><a href="View.htm">View</a></li>

  <li><a href="Settings.htm">Settings</a></li>



The CSS for the tool bar turns off padding margin and list-style for the list element. The list item elements are floated left, so that they appear horizontally rather than in the default vertical list layout. The display property on the links is set to block so that the entire tool bar item is hot.

ul.toolbar { margin:0; padding:0; list-style-type:none; }

ul.toolbar li { float:left; border:1px solid; border-left:none;

  background-color:menu; color:menutext; }

ul.toolbar li.first { border-left:1px solid gray; }

ul.toolbar li a { color:black; text-decoration:none; width:100%; height:100%;

  padding:0.2em 2em 0.2em 0.5em; width:8em; display:block; }

ul.toolbar a:hover { text-decoration:underline; }

ul.toolbar a:focus { color:highlighttext; background-color:highlight; }

The Accessibility and Legacy Browsers article includes additional examples of lists used for grouping.


Tables differ from lists in that there are multiple columns, and the data in each column is of the same data type and description.  For lists of data with no columnar information, an HTML list should be used.  When there is columnar data, the TABLE element should be used.  Table headings, whether column or row, should be identified using the TH element, and table cells, using the TD element. Many AT devices provide special table navigation functionality, allowing the user to move about the table cells, with header information available for every cell.

A table of employee information has a caption of employee information, and headings of Name and Hire Date.

<caption>Employee Information</caption>


  <tr><th>Name</th><th>Hire Date</th></tr>



  <tr><td>John Smith</td><td>09 Nov 2007</td></tr>

  <tr><td>Jane Doe</td><td>10 Nov 2007</td></tr>




Headings demark and identify sections of a document or application.  For the visual user, headings are a critical means of quickly scanning a document’s main sections, perhaps locating a specific section of interest, and jumping to it quickly, without having to read the entire document. HTML provides the H1 to H6 elements, each number indicating a level of hierarchy.  Just as the visual user uses the visual cues – font size and color – to identify headings, AT users rely on the semantic HTML to do the same thing. Many AT devices provide a list of navigable headings, either in a tree or flat format, so that the user may quickly scan the document or application and jump to a section. Semantic headings are so useful that many search engines use them to list results.

stylized headings with different colors, font treatments, and alignment


<h1 role="heading" aria-level="1">Widget Project Proposal</h1>

<h2 role="heading" aria-level="2">Contoso Corporation</h2>

<h3 role="heading" aria-level="3">Project Summary</h3>

<h3 xrole="heading" xaria-level="3">Delivery Schedule</h3>


div.demo h1 { background-color:silver; color:gray; padding:0.3em; }

div.demo h2 { text-align:right; color:silver; background-color:gray; padding:0.3em; }

div.demo h3 { color:black; text-transform:uppercase; background-color:silver; padding:0.3em; }


As mentioned above, the accessible name, unlike the role, is explicitly specified by the developer. While the role identifies what the element is, the name indicates who the element is, in a manner of speaking. 

Missing or inappropriate names are one of the biggest sources of accessibility problems. A classic example, and one that resulted in legal action, is a missing name on an image link (a link composed on just an image, no text).  An image with no name provides no meaningful information about the image to AT. Although the image may visually indicate “Purchase”, in the absence of a name, that information is not available to AT users. All they see is a “blank” link (or, in the case of some AT which attempts to provide some information when the name is missing, a file path). 

The lack of a name on any element, especially any navigable element, should be considered a top-priority bug.  

Before getting into some details, let’s summarize how various elements have their name set. Text elements, such as links and headings, just take the inner text of the element itself.  TABLE elements use the CAPTION child element to set the name for the table. Table headers (TH) get their name from the inner text.  For images, the ALT attribute on the image sets the name.  For form elements, there are three types: buttons, INPUT TYPE=”button” and BUTTON, use the value attribute or the inner text, respectively. FIELDSETS use the LEGEND child element.  All other form elements, checkboxes, radio buttons and textboxes, require the LABEL element associated with the form element by the FOR attribute on the LABEL. 

Here are some more specific guidelines for setting the name on a number of elements, along with a few other tips along the way:


Make sure to use the CAPTION element to give the TABLE a name.  If the design does not call for a visible heading for the table (and it probably should), then the CAPTION may be positioned off-screen using CSS. Make sure that you have column (or row, if appropriate) headers, using the TH element, whose inner text gives the name to all the cells in that row (or column). An AT user can query this header information from any cell, just as a visual user might look up (or across) to see this. 

It’s also best to avoid using empty cells for padding (CSS padding on the cells is a great alternative),  to avoid nested tables, and to keep related content in the same table. 


Make sure that all form elements have names, especially those requiring a LABEL for this.  Missing name information on form elements can cause confusion, and many AT devices will default to using the “closest” text to provide the name, which at times gives entirely the wrong name.  As with table captions, if there is no visible text in the design for an element, then the LABEL may be positioned off-screen using CSS.  The TITLE attribute may be used, in a pinch, but please see the note on TITLE below. 

Wrapping the form elements in a FORM element, along with submit and reset buttons give the form the appropriate default navigation and keyboard support.  If possible, avoid using auto-postbacks (submitting a form when a value is changes) as this causes problems for a number of classes of AT users. 


As mentioned earlier, missing names on images are a common (and potentially expensive) source of accessibility problems.  The ALT attribute is required on every image specified using the IMG element.  The ALT text should describe the image, just as it appears visually.  For logo images that have “text” in them, the ALT text should be the very “text” in the image.  Where an image is not contextually important, either because it’s purely decorative or because it’s in a link with text also, the image may be “hidden” from AT by setting the ALT attribute to an empty string (“”).We’ll have more on this later, but background images should be specified in CSS. 

Another issue with images is the use of CSS background-image to add images that are not really backgrounds. Windows High Contrast mode, and some AT products, remove backgrounds, including background-image, to improve readability. It is important that images that are part of the meaning or functionality of the content are created with <img> elements with appropriate @alt attributes, rather than with CSS background-image. Examples include images used in links and buttons, icons, figures in a document, or photographs in a newspaper article.


Like other text element, such as headings, the name for a link comes automatically from its inner text. Because many AT devices present lists of links apart from the document, it’s important that links have names that can stand alone and that aren’t redundant (such as a list of “details” links).If design requirements are such that “duplicate” links names are called for, then the TITLE attribute may be used to disambiguate these. Where there is a link with an image and text, it’s important to wrap both in a single A HREF element to avoid redundancy (imagine having to read the same link twice). If the image is not contextually important to the link and there is text, the ALT may be set to the empty string. 

A Note on TITLE

There are times when the use of the TITLE attribute is useful, such as when there is no visual text for a form element that would require a LABEL to set its name (and positioning the LABEL off-screen is problematic). The TITLE may be used here, but be aware that browsers render the TITLE as a tool tip, so it may end up visually occluding part of the control in question or being generally undesirable esthetically. 

It’s also important to distinguish between ALT and TITLE, although earlier versions of Internet Explorer show both as a tool tip.  ALT provides the accessible name for an image. TITLE provides additional information about an element that is not important enough to display be default. The ALT on the IMG element should not be replaced by TITLE.Think of TITLE as a tool tip, and an emergency accessible name for form elements when LABEL isn’t feasible. 

Windows and Frames

Windows (parent documents) and Frames get their name from the TITLE element in the HEAD section of the document in the window or frame. Make sure that all HTML documents have a good TITLE set. 


The building block of web accessibility is semantic HTML, using the right element for the job.A web application that is built on good HTML is well on its way to being accessible.  Conversely, an application built on inappropriate HTML cannot be made accessible. Start with the right elements, and you’re building on a solid foundation. 

When planning the development of your application, it is good to think semantically and hierarchically from the start.Some questions to ask include: Where do natural sections and sub-sections (and hence sub-headings) occur?  Where do groups of hierarchically-related items appear (use list elements), such as toolbars, menus, trees, and lists? What names are needed for each element and sub-element? It may be useful to think of your application as a giant tree. Think structurally, and map UI controls to semantically-appropriate HTML.In addition to a solid foundation for accessibility, in letting the intrinsic HTML do the work for you, you get: simpler templating, easier and lighter CSS, better automation support, and lighter HTML.