Building Accessible Static Navigation with CSS

By Frank M. Palinkas

Overview

When building a navigation menu for a web site, steps should be taken to ensure that it is accessible, and degrades gracefully in older browsers with lesser CSS support. In this article we will explore one such implementation. The navigation menu you see in this example is built with valid, semantic HTML and CSS - no JavaScript is involved, as I felt this was unnecessary. The static (non-expanding/collapsing) nature of the example suits a web site comprised of twenty or less target pages.

This article is divided into the following sections.

  • Nav Container - The nav container (<div id="nav"></div>) contains the following three areas of the navigation, and is placed in each web page of the document collection.
    • Skip to content styled button - This is placed directly at the top of the nav container, and is an accessibility feature for users with visual impairments.
    • Area headings - This defines the structure and presentation of the area headings that separate each section of the navigation container.
    • Link state symbols area - This is a legend consisting of symbols that define the state of a hyperlink as a user traverses the document collection. It is an accessibility feature for users that are visually impaired, color blind, or suffer from short term memory loss or dyslexia.
    • Topics area - As it says, here is where all topic web pages are listed and hyperlinked for surfing through the document collection.
  • Currently open page - Here I discuss another aspect of my navigation which you may find useful, namely the "Currently open page" feature.

Each topic will be explained, and accompanied by the markup and css used to create it. You can download the complete code example here.

Nav container

The nav div container acts as a wrapper for and defines the overall position of the navigation areas. It is absolutely positioned at the top and left sides of the web page by a rule in the external style sheet.

Nav container markup

<div id="nav">
    <h4 class="skip">
        <a href="#a1">skip to content</a></h4>
    <hr />
    <h4>link state symbols</h4>
        <ul class="linkstate">
            <li><img alt="Ball symbol." class="state" src="images/hover.gif" width="16" height="16" /><span class="focus">Focus/Hover</span></li>
            <li class="unvisited"><img alt="Chain link symbol." class="state" src="images/link.gif" width="16" height="16" />Unvisited</li>            
            <li class="visited"><img alt="Check mark symbol." class="state" src="images/visited.gif" width="16" height="16" />Visited</li>            
            <li class="currently"><img alt="Star symbol." class="state" src="images/star.gif" width="16" height="16" />Currently Open</li>            
        </ul>            
    <hr />            
    <h4>topics</h4>            
        <ul class="linkstate"
            <li><a href="home.htm">Home</a>
            <ul>
                <li><a href="Topic1.htm">Topic 1</a></li>
                <li class="topic2"><a href="Topic2.htm" title="This page is currently open.">Topic 2</a></span>
                    <ul>                
                        <li><a href="Topic2a.htm">Topic 2a</a></li>                
                        <li><a href="Topic2b.htm">Topic 2b</a></li>                
                        <li><a href="Topic2c.htm">Topic 2c</a></li>
                        <li><a href="Topic2d.htm">Topic 2d</a></li>
                        <li><a href="Topic2e.htm">Topic 2e</a></li>
                        <li><a href="Topic2f.htm">Topic 2f</a></li>
                    </ul>
                </li>    
                <li><a href="Topic3.htm">Topic 3</a></li>
                <li><a href="Topic4.htm">Topic 4</a></li>
                <li><a href="Topic5.htm">Topic 5</a></li>
            </ul>
        </li>
    </ul>
</div>

Nav container CSS

Here we define the presentation code used to position and style the Navigation container div in the browser window:

#nav {
width: 23em; - gives the navigation div container a relative horizontal size
position: absolute; - removes the navigation div container from the natural flow of the document.
top: 1em; - sets the distance from the top of the browser window
left: 1em; - sets the distance from the left side of the browser window
margin: 0em; - shorthand for the margin property - removes all margins in the order of top, right, bottom and left
padding: 0em 0.5em 1em 0.5em; - shorthand for the padding property - sets the padding in the order of top, right, bottom and left:
border: 1px solid #ffd505; } - shorthand code for the border property - defines the width, type, and color of the border surrounding the nav container:
#nav ul {
margin: 0em; - shorthand for the margin property - removes all margins in the order of top, right, bottom and left
padding: 0em; - shorthand for the padding property - removes all padding in the order of top, right, bottom and left
list-style-type: none; - removes the list-styles: discs, squares, circles, etc.
color: #fff; - sets the color of white to the text characters
background: inherit } - sets the list to inherit the container background color
&#035nav ul li {
margin: 0em; - shorthand for the margin property - removes all margins in the order of top, right, bottom and left
padding: 0.4em 0em 0em 0.5em; - shorthand for the padding property - sets padding in the order of top, right, bottom, and left:
list-style-type: none; } - removes the list-styles: discs, squares, circles, etc.
&#035nav ul ul li {
padding: 0em; - shorthand for the padding property - removes all padding in the order of top, right, bottom and left
margin-left: 2em; - sets the left margin padding to 2em
list-style-type: none; } - removes the list-styles: discs, squares, circles, etc.
&#035nav ul ul ul li {
padding: 0em; - shorthand for the padding property - removes all padding in the order of top, right, bottom and left
margin-left: 1.4em; - sets the left margin padding to 1.4em
list-style-type: none; } - removes the list-styles: discs, squares, circles, etc.

Skip to Content area

Following accessibility guidelines, I have included a "skip to content" link (styled button) on each web page to allow users to bypass the navigation section and skip to the beginning of the page content. I have designed the button using CSS to be visible to all users by default, making them aware that this accessibility tool is available. It is made fairly small, and in line with the design of the web page so as not to be too obtrusive to the page design. If a client specified it should not be visible, it could be moved off the visible page using CSS absolute positioning (Important Note: visibility: hidden; should not be used as this makes it invisible to assistive technologies.) This way, it wouldn't be seen at all by sighted users, and users employing screenreaders (or other assistive technologies) could activate it through the keyboard. This eliminates the repetitive spatial navigation or tab key actions needed to manually bypass the navigation and arrive at the first section of content.

Skip to content area markup

As shown in the following code sample, the markup of the styled button (h4 class="skip") links the anchor element and its href attribute value (a href="#a1") with the id attribute value of the first content heading (h2 id="a1"). I do not employ any access keys/character keys to achieve this because the majority have already been pre-assigned by the operating system, the user agent/browser, and any assistive device which may be installed, notwithstanding those few available which a user may have assigned themselves.

<h4 class="skip">
    <a href="#a1">skip to content</a>
</h4>

Skip to content area CSS

I have defined the following styles in an external style sheet to style and position the "Skip to Content" button hyperlink just how I want it:

#nav h4.skip {
font-size: 1.1em; - sets the font-size to a relative size of 1.1em
font-weight: bold; - sets the font-weight to bold
font-variant: small-caps; - sets the font-variant to small-caps
margin: 1.8em 0em 0em 0em; - shorthand for the margin property in the order of top, right, bottom and left
padding: 0.5em; - sets all padding (top, right, bottom, and left) to 0.5em
color: #fff; - sets the font color to white
background: none; - removes any background and image attached to the anchor hyperlink
text-decoration: none; } - removes the default underline from the anchor hyperlink
#nav h4.skip a:link, #nav h4.skip a:visited {
color: #000; - sets the font color to black
background: #ccc; - sets the background color of the button
padding: 0.2em 1em; - shorthand code for padding in the order of top and bottom, then right and left
border-top: 0.15em solid #fff; - top border shorthand: sets the thickness, type and color for the unvisited and visited state of the top border of the button
border-left: 0.15em solid #fff; - left border shorthand: sets the thickness, type and color for the unvisited and visited state of the left border of the button
border-bottom: 0.15em solid #aaa; - bottom border shorthand: sets the thickness, type and color for the unvisited and visited state of the bottom border of the button
border-right: 0.15em solid #aaa; } - right border shorthand: sets the thickness, type and color for the unvisited and visited state of the right border of the button
#nav h4.skip a:hover, #nav h4.skip a:active, #nav h4.skip a:focus {
color: #fff; - sets the font color to white
background: #454545; - sets the background color of the button
padding: 0.2em 1em; - shorthand code for padding in the order of top and bottom, then right and left
border-top: 0.15em solid #fff; - top border shorthand: sets the thickness, type and color for the hover, active and focus states of the top border of the button
border-left: 0.15em solid #fff; - left border shorthand: sets the thickness, type and color for the hover, active and focus states of the left border of the button
border-bottom: 0.15em solid #aaa; - bottom border shorthand: sets the thickness, type and color for the hover, active and focus states of the bottom border of the button
border-right: 0.15em solid #aaa; } - right border shorthand: sets the thickness, type and color for the hover, active and focus states of the right border of the button

Area headings

Each area of the navigation <div></div> container begins with a heading using the <h4></h4> element.

The Area Headings markup

<h4>Area Name</h4>

The Area headings CSS

#nav h4 {
    font-size: 1.5em;
    font-variant: small-caps;
    text-align: center;
    margin: 0em;
    padding-bottom: 0.3em;
    color: #fff;
    background: inherit; }

Link state symbols area

This legend defines the current state of all hyperlinks. In the Topics area of the navigation container, the current state of each link is represented by a different symbol positioned to the right of the hyperlink text - these are summarized in the table below. This is important to users that are color blind, visually impaired, or suffer from short term memory deficiency. It eliminates link state color, gives them the ability to identify if they have or have not visited a topic, and also allows them to identify a hyperlink by keyboard or mouse navigation.

Hyperlink State Symbols
State Symbol Description
Focus/Hover ball symbol Ball - signifies the focus, hover and active pseudo-classes
Unvisited chain link symbol Chain link - signifies an unvisited link, the link pseudo-class
Visited check mark symbol Check mark - signifies a visited link, the visited pseudo-class
Currently Open star symbol Star - signifies a topic web page which is currently open and being viewed

Link state symbols area markup

The legend is constructed using a simple unordered list, containing image elements with relative paths to the symbol graphics. alt attributes give a short description of the symbols. Please note that this legend gives a static rendering of the symbols - purely for identification purposes. The symbols will become dynamic through CSS image replacement in the Topics area hyperlinks, when the linkstate class attribute is added to the opening tag of the root unordered list element.

<h4>link state symbols</h4>
    <ul class="linkstate"> 
        <li class="focus"><img alt="Ball symbol." class="state" src="images/hover.gif" width="16" height="16" />Focus/Hover</li> 
        <li class="unvisited"><img alt="Chain link symbol." class="state" src="images/link.gif" width="16" height="16" />Unvisited</li>
        <li class="visited"><img alt="Check mark symbol." class="state" src="images/visited.gif" width="16" height="16" />Visited</li> 
        <li class="currently"><img alt="Star symbol." class="state" src="images/star.gif" width="16" height="16" />Currently Open</li> 
    </ul>

Link state symbols area CSS

The Link State Symbols area presentation code is defined as follows:

#nav .linkstate {
font-weight: bold; } - sets all characters to bold
#nav .state {
padding-right: 1em; - sets the symbol image space to the right of the text
vertical-align: top; } - sets the symbol image to the top of the text baseline
#nav .focus {
color: #fff; - sets the text color to white
background: transparent; - sets the background color to transparent
text-decoration: underline; } - sets the underline beneath the hyperlink
#nav .link {
color: #a4d3ee; - sets the text color to light blue
background: transparent; } - sets the background color to transparent
#nav .visited {
color: orange; - sets the text color to orange
background: transparent; }
#nav .currently {
color: yellow; - sets the text color to yellow
background: transparent; } - sets the background color to transparent

Topics area

The Topics area contains the global navigation for the pages in the web site. Each topic is hyperlinked to its individual web page and is activated either by spatial keyboard navigation, tab key or mouse.

In this code I have dynamically employed the symbols I identified earlier in the Link state symbols area legend. Identification of the current state of any link in the Topics area is achieved by inserting a class attribute with its value of linkstate in the root unordered list element opening tag (<ul class="linkstate">). The link state symbols, as previously defined in the legend, now become dynamic though image replacement using external CSS. All hyperlinks in the Topics area now show their current link state via the symbol at the end of their link text. Links that are not in the hover, active or focus state will show the unvisited chain link symbol, the visited check mark symbol, or the star symbol which signifies that the page is currently open and being viewed.

In addition, as a user navigates through the Topics area hyperlink list via keyboard or mouse and gains focus on each link, the link will become underlined, and a ball symbol will replace either the chain link (unvisited) or check mark (visited) symbols. This ball symbol represents the hover, active, and focus pseudo-classes of the anchor link element. Please note that the star symbol which signifies a currently open page, will remain static and not change (this is an optional feature which I'll describe later in the article).

Topics area markup

<h4>topics</h4>
    <ul class="linkstate">
        <li><a href="home.htm">Home</a>
            <ul>
                <li><a href="topic1.htm">Topic 1</a></li>
                <li><a href="topic2.htm">Topic 2</a>
                    <ul>
                        <li><a href="subtopic2a.htm">Subtopic 2A</a></li>
                        <li><a href="subtopic2b.htm">Subtopic 2B</a></li>
                        <li><a href="subtopic2c.htm">Subtopic 2C</a></li>
                        <li class="subtopic2d"><a href="subtopic2d.htm" title="This page is currently open.">Subtopic 2D</a></li>
                        <li><a href="subtopic2e.htm">Subtopic 2E</a></li>
                        <li><a href="subtopic2f.htm">Subtopic 2F</a></li>
                    </ul>
                </li>
                <li><a href="topic3.htm">Topic 3</a></li>
                <li><a href="topic4.htm">Topic 4</a></li>
                <li><a href="topic5.htm">Topic 5</a></li>
            </ul>
        </li>
    </ul>

Topics area CSS

The presentation code for the Topics area is defined in the following manner:

#nav .linkstate {
font-weight: bold; } - sets all link characters to bold.
#nav .linkstate a:link {
text-decoration: none; - removes underlining from hyperlinks
color: #a4d3ee; - sets the font color to a light blue
padding-right: 1.7em; - creates space on the right side of the Topic for the linkstate image
vertical-align: bottom; - positions the image at the bottom of the text line
background: #000 url(images/link.gif) no-repeat right; } - shorthand for the background property, defined as follows:
  • #000 - sets the background color to black
  • url(images/link.gif) - sets the relative path to the images folder containing the link icon image
  • no-repeat - sets the image to a single and not a multiple rendering
  • right; - positions the image to the right of the hyperlink
#nav .linkstate a:visited {
text-decoration: none; - removes underlining from hyperlinks
color: orange; - sets the font color to orange
padding-right: 1.7em; - makes space on the right side of the Topic for the linkstate image
vertical-align: bottom; - positions the image at the bottom of the text line
background: #000 url(images/visited.gif) no-repeat right; } - shorthand for the background property, defined as follows:
  • #000 - sets the background color to black
  • url(images/visited.gif) - sets the relative path to the images folder containing the link icon image
  • no-repeat - sets the image to a single and not a multiple rendering
  • right; - positions the image to the right of the hyperlink
#nav .linkstate a:hover {
text-decoration: none; - removes underlining from hyperlinks
color: #fff; - sets the font color to white
padding-right: 1.7em; - makes space on the right side of the Topic for the linkstate image
vertical-align: bottom; - positions the image at the bottom of the text line
background: #000 url(images/hover.gif) no-repeat right; } - shorthand for the background property, defined as follows:
  • #000 - sets the background color to black
  • url(images/hover.gif) - sets the relative path to the images folder containing the link icon image
  • no-repeat - sets the image to a single and not a multiple rendering
  • right; - positions the image to the right of the hyperlink
#nav .linkstate a:active {
text-decoration: none; - removes underlining from hyperlinks
color: #fff; - sets the font color to white
padding-right: 1.7em; - makes space on the right side of the Topic for the linkstate image
vertical-align: bottom; - positions the image at the bottom of the text line
background: #000 url(images/hover.gif) no-repeat right; } - shorthand for the background property, defined as follows:
  • #000 - sets the background color to black
  • url(images/hover.gif) - sets the relative path to the images folder containing the link icon image
  • no-repeat - sets the image to a single and not a multiple rendering
  • right; - positions the image to the right of the hyperlink
#nav .linkstate a:focus {
text-decoration: none; - removes underlining from hyperlinks
color: #fff; - sets the font color to white
padding-right: 1.7em; - makes space on the right side of the Topic for the linkstate image
vertical-align: bottom; - positions the image at the bottom of the text line
background: #000 url(images/hover.gif) no-repeat right; } - shorthand for the background property, defined as follows:
  • #000 - sets the background color to black
  • url(images/hover.gif) - sets the relative path to the images folder containing the link icon image
  • no-repeat - sets the image to a single and not a multiple rendering
  • right; - positions the image to the right of the hyperlink

Currently open page feature

This is an accessibility navigation feature I've found to be helpful to some users, and which I believe enhances their experience. Sometimes, a user may forget which page they have open and are viewing. Unwittingly, they may go to this specific page in the Topics area navigation and activate it, causing a page refresh. Some confusion may follow until they realize that this is the page they have open and are currently viewing.

To eliminate the possibility of this happening, you need to identify the hyperlink in the Topics area nav list of the page that is currently open. I do this by dynamically attaching a star symbol to the end of the link text and color the link text bold yellow, visually identifying this topic link as the page that is currently open. This feature can be employed in both static and dynamic navigation lists.

Currently open page feature markup

The first step is to open each page in a text editor and assign an id to the <body> element of each web page in the document collection (if one is not already present). For example:

  • home.htm web page: <body id="home">
  • topic1.htm web page: <body id="topic1">
  • topic2.htm web page: <body id="topic2">
  • etc.

The second step is to find that same page listed in the Topics area unordered list (in that page), and add a class attribute and value to the list item containing its hyperlink. The value of this class attribute can be exactly the same as the one used for the id attribute in the opening <body> element. For example:

  • home.htm web page, Topics area unordered list: <li class="home">
  • topic1.htm web page, Topics area unordered list: <li class="topic1">
  • topic2.htm web page, Topics area unordered list: <li class="topic2">
  • etc.

The following markup sample of the site's home page illustrates both the <body> element id of "home", and the Topics area unordered list item class of "home" being added to the markup. This is one rare occasion where I will add a title attribute and value of "This page is currently open." to the anchor element.

<body id="home">
    <div id="nav">
        <ul class="linkstate">
            <li class="home">
                <a href="Home.htm" title="This page is currently open.">Home</a>
            </li> 
        </ul>
    </div>

Currently open page feature CSS

Now that we have the markup of the home page adjusted to identify it as being currently open when a user is viewing it, the final step is to create the CSS to make this happen.

Each web page in the document collection will have its own group of four CSS type selectors in this specific order, in the external style sheet:

  • #home: id selector of the page <body> element
  • #nav: id selector of the Topics area nav div element
  • .home: class selector of the Topics area unordered list item element
  • a: anchor element selector

An example of the collection of web pages and their selectors in the style sheet will look like the following:

  • #home #nav .home a,
  • #topic1 #nav .topic1 a,
  • #topic2 #nav .topic2 a,
  • #topic3 #nav .topic3 a,
  • etc.

Remember to add a comma after each a element type selector before starting the next group of selectors. The final group of selectors does not get a comma after the a element type selector. Lastly, in the following CSS, we define the appearance of the topic hyperlink when a topic web page is currently open.

#home #nav .home a, 
#topic1 #nav .topic1 a,
#topic2 #nav .topic2 a,
#topic3 #nav .topic3 a {
    color: yellow;
    background: transparent url(images/star.gif) no-repeat center right;
    cursor: default;
    padding-right: 1.7em;
    text-decoration: none;
    font-weight: bold; }

Summary

This article highlighted several techniques to add accessibility to a simple, static, navigation menu. It aims to enhance the user experience regardless of their (dis)ability through a Skip to Content facility, a Link State Symbol legend, and the dynamic employment of these link states through their associated symbols. Please feel free to add, change, and experiment with the code, according to your needs. Thanks for your time and attention!

Frank is an American working in Sunnyvale, California with Google Motorola Mobility, Inc. as a Senior Technical Writer, Web Standards & Accessibility Designer.

He authors all markup, presentation, behavior code and content using (X)HTML, HTML5, CSS, and Unobtrusive DOM/JavaScript. His technical writing incorporates web standards, accessibility, and semantics. Frank enjoys creating tutorials which are offered free of charge to the Help Authoring and Technical Writing community.

He is happily married to his wife Wanda (Lighterian Reiki Master/Instructor and Hand Embroidery Instructor), and they have two sons, Gregory (MCSD and Computer Animator) and Andre (Sound and Recording Engineer). Frank and Wanda live in Sunnyvale, California, USA.


This article is licensed under a Creative Commons Attribution, Non Commercial - Share Alike 2.5 license.

Comments

The forum archive of this article is still available on My Opera.

No new comments accepted.