Rather than bore everyone with tedious code listings (yes, I'll have a few), I'm going to link to the proof-of-concept that will also have fully commented code, and here I'll give a general overview as well as a few things you'll want to notice along the way.
If this is your first foray into accessible coding, do yourself a favor and get the WAVE Evaluation Tool extension for Google Chrome, and if you're not already using the Mobile/Responsive Web Design Tester extension, get that as well.
As always, we first start with the markup and do the things we would normally do - add the
lang
attribute to the HTML
tag, add a descriptive TITLE
to the HEAD
, and add a descriptive H1
to the BODY
. Here's where I start my navigational menu code...inside the H1
. In addition to using the H1
as a banner, I'm adding a 'button' that will toggle the navigation menu (note that this is only for mobile devices). Since this is only a visual interface for the menu, I'm not adding anything to it - no ARIA role labels. The 'button' span is empty, so without ARIA labels or role, accessibility technology will ignore it (as it should). After the H1
, I'll add the actual menu...but more on that in a couple of paragraphs.The user interface for mobile users, when the navigation menu is closed, will show a button that will display a hamburger symbol and when it's open it will display the x typically used on close buttons.
Note that I'm not actually using a
BUTTON
tag but a SPAN
tag that acts like a button...and the primary reason for this is because the icon displayed inside the button is controlled using CSS and that's really impossible to do when you use a BUTTON
tag. By attaching an event listener to the click
event on the button SPAN
, I add (or remove) opened to (or from) the H1
tag. The opened H1
and an adjacent sibling selector for the menu will control whether the menu is seen or not. If you want to use a different device to toggle the menu, feel free - and simply change the CSS so that the 'opened' class is attached to the menu. Since the content is not in the markup, I don't need any ARIA attributes like aria-hidden
even though it's a control for the visual interface...and because the button in the H1
is only used on mobile, I wrap the styling in a media query using a mobile breakpoint.HTML
CSS
Now that we have the
H1
set, I'm going to add the navigation menu to the page. I'm choosing to add the navigation menu before the content because (1) it's easier to style that way and (2) when the links are at the top it's easier for someone to jump to another location before all the other content is read - and they don't have to take extra steps, like using their AT to step through a bunch of landmarks.HTML
There are a few things of note in the code. First, I've added a ARIA
role
(navigation) to the list. Rather than go into detail here about what a navigation role means, I'll instead point you to the W3 page about ARIA roles. Second, this example uses a sub-menu, which will become important when we talk about the CSS and the JavaScript. Additionally, I've identified LI
items that contain menu items as items, which enables me to add LI
tags that are used as separators. Each clickable item is wrapped in an anchor (A
) tag, which allows me to leave sub-menu headers in tags that aren't automatically identified as clickable, e.g., SPAN
. Finally, there is a SPAN
tag with the class indicator regardless of whether or not there is a sub-menu. This enables a sub-menu visual indicator, which is not needed by accessibility technology, which will read the submenu because it's hidden using clip
rather than a technique that would render the sub-menu invisible to AT.CSS
There are a few things of note about the CSS. First, the style rules for the sub-menu will drop the sub-menu below the primary menu and make it appear as wide as the primary menu. Although this approach is not ideal, we're going to fix it using JavaScript - which will hit most users and those who don't have JavaScript running (or those who have a page with borked JavaScript) will still have access to the navigation menu. If you're coding for a mobile device and are using a toggle button, you might want to consider how users will get to the menu if their JavaScript is borked - you might even consider using a
focus
or hover
pseudoclass.Second, the initial value of the
margin-left
and margin-right
is the border-width
on the primary menu (ul[role="navigation"]) multiplied by -1. This extends the left and right border to the full width of the primary menu.Third, by setting the
position
to absolute, we can change the left
and right
values and the menu will become more like a drop-down menu (remember that I said we'd fix the width of the menu with JavaScript just two paragraphs ago - well here it is, the initMenu function does it).JavaScript
Now, simply add a call to your JavaScript function to initialize the menu - something like
initMenu(document.getElementById('main-menu'));
- and you're done. The initMenu function will set the left
position of the sub-menu UL
to the left position of its LI
container, will set the right
value to auto (which shortens the width) and adjusts the margin
so that everything lines up neatly.So that's it. One last note - although I generally use a 'mobile first' approach (making the style sheet for mobile and then writing a media query for everything else) I didn't do it that way this time because the styles are different enough that they're difficult to re-use. In the proof of concept I've linked both stylesheets, but in your production code you might want to pursue an adaptive approach so only the mobile stylesheet is downloaded for mobile devices to minimize the payload - on the other hand, the stylesheets are pretty light as they are so it might not matter. Oh...and this is the proof of concept.
Happy coding.
No comments:
Post a Comment