ARIA Slider, Part 2

In my previous post I gave an example for a very minimalistic ARIA slider, with the intention of demonstrating how simple it is to add ARIA using only a few attributes. I know there are some developers out there who wishfully think that, in order to make their rich interface widgets accessible, all they have to do is add ARIA to it. Others are skeptical about ARIA for that very reason. The truth is of course that ARIA is only part of the effort, and work is required to make any widget accessible (whether you’re using ARIA or not). In this post I want to cover some of those issues and give an overview of what else to think about when creating an accessible slider.

Example

Throughout this article I will be referring to a slider component I am currently working on myself, which for lack of a better name I will just call the TPGi slider. The TPGi slider sample page contains examples of the different types of sliders that can be created using this component. The implementation for the TPGi slider was inspired by two two excellent slider related articles: Unobtrusive Slider Control Revisited by Brian McAllister and Developing an accessible slider by the Filament Group. Both articles provide a similar slider component that also supports ARIA.

What to Think About When Creating an Accessible Slider

Starting with the Basics: Fallback Content

Since HTML does not provide us with a native slider component, we’ll have to start with a form control that HTML actually does provide. In the case of a slider, the most suitable input control is a select element. The select element prevents the user from entering an incorrect value, without having to rely on validation scripts. Additionally, it allows a value to be quickly selected using the mouse or by typing in the first digits or letters.

For certain value ranges it might be a bit ‘too much’ to use a select element though. For example, a slider which ranges from 0 to 1000 units would have 1000 <object> elements, which might make the selection process a bit tedious for certain people ( and lead to bloated markup). For this reason, the TPGi slider also allows a text input element to be the fall-back element. This requires a lot less HTML code to start with, but it does require the user to understand the constraints of an acceptable value. If you want offer a solution that does not depend on client side scripting, you would have to include a server-side validation process to fall back on. This goes beyond the scope of this article though.

Using Unobtrusive Scripting to Build and Configure the Slider

If client side scripting is available on the user agent, your slider script should kick in to start building the actual slider DOM elements. If not the user will have to use the fallback control instead. The TPGi slider consists of two parts: the Slider class and the Slider manager. When the page has loaded, the manager scans the document structure for text input or select controls with a class name of ‘tpgSlider’. For each found element, a new instance of the Slider class is created, which then proceeds to create the actual slider adjacent to the fallback control.

To make a widget accessible to different users it can be useful to make it configurable. The TPGi slider can be configured by specifying name-value pairs in the original form control’s class name. Additionally, these parameters can be stored in a different location ( a cookie, a preferences database, etc.), and sent as a JavaScript object when the slider is constructed.The parameters let you control aspects like the slider’s size and value range, and also let you specify some ARIA properties.

For example, to recreate the volume slider used in my previous post, I would need a label element and either a select control or a text input control with class name parameters:

<label id="s1Lbl"  for="s1">volume: </label>
<input id="s1" type="text" maxlength="4" 
class="tpgSlider tpg_thickness-1em tpg_railLength-15em 
tpg_range-0-100 tpg_valueText-percent tpg_labelledby-s1Lbl" />

Each parameter consists of a prefix (‘tpg_’), followed and a name-value pair (separated by a dash). If the value is omitted, the parameter will be considered to be a boolean with a value of ‘true’. If a values is split up using multiple dashes (as is the case for the ‘range’ parameter), the parameter is considered to be an array. The only parameter that is absolutely requried is ‘tpg_labelledby‘, which must point to the id of an existing label element.

The advantage of a parameter system is that it lets developers to create a preference system, which allows users to choose how they want their widgets to appear. Throughout the rest of this article I will highlight some of the more commonly used parameters.

Adding the Slider to the Document Structure

When the slider is constructed, you have to decide what to do with the original form input control. In the TPg slider, the ‘tpg_removeInput‘ parameter can be used to optionally remove the original text input or select element after the slider is created. Whether or not to remove the fallback element is up to the developer, but it is important to consider the following:

  • Certain users may have capable technology that supports client side scripting, but still be more comfortable using traditional form controls. For example, not all screen reader users will know and understand that they have to switch to non-virtual mode in order to be able to interact with the slider.
  • Other users may find it pleasant to be able to use both a slider and an input control.
  • Yet other users may prefer to only interact with a slider, because they prefer to use the mouse or prefer to keep the tab order as short as possible.

For these reasons it is recommended to let the user choose whether to leave in the original control or have it removed. When the control is removed, the ‘for’ attribute of the associated label element will be updated so that it now points to the slider element. One advantage of this is that clicking on the label will move focus to the slider (but only when the slider is marked up with a natively supported form control).

Dealing with Focus and Tab Order

As I mentioned in my previous slider post, a slider can either receive focus on its rail or its thumb. Placing focus on the thumb can makes your slider more backwards compatible. For example, in the TPGi slider, the thumb is implemented as an image input control, which is focusable and part of the tab order by default. This ensures that the slider is keyboard accessible , even in browsers that do not support the extended use of the tabindex attribute (such as current versions of Safari) . The advantage of using the rail as the focusable slider part is that screen magnifier users will have the entire slider scrolled into view when using a relatively high magnification factor. To choose which part of the slider should be focusable, the TPGi slider allows you to set the tpg_thumbFocus parameter to either true or false. The TPGi Sider Demo Page shows examples of both settings.

Those interested in creating similar widgets should note that getting, setting, and removing tabindex values with JavaScript in a cross browser friendly way requires some additional thought.

Providing a visual indication for focus is a requirement of an accessible application. It is important to note that not all browsers will draw the default focus indication (usually a dotted rectangle) on elements that are not focusable by default, such as a ‘div’ element. For this reason, you must always provide your own styles for focus indication. Ideally we would use the ‘:focus’ pseudo selector, but since this is not widely supported by Internet Explorer 7 and below you will have to add and remove a custom CSS class name on the element’s focus and blur events. In the case of the TPGi slider, I have used a combination or borders and negative margins to visualize focus:

.focused {
 border: 0.1em solid #fff500;
 margin-top: -0.1em;
 margin-left: -0.1em;
}

Note that the border width is specified using relative values, so that it will increase when the user increases the browser text size. Also note that a more ideal (but less backwards compatible) way to visually indicate focus is to use the ‘outline’ style, which is now supported by the latest (beta) versions of all major browsers.

Keyboard Accessibility

For ARIA to have effect, and for any widget to be accessible, it needs to be keyboard accessible. In the case of a slider, make sure that the slider’s value is easy to change using the keyboard and does not require too many keystrokes. When in doubt, consult  WAI-ARIA Authoring Practices. Besides using the arrow keys for single increments, also implement the home and end keys to move the thumb to the minimum and maximum value. Page Up and Page Down should allow the user to change the value using larger steps.

Scaling and Sizing

One aspect of accessibility that is often neglected in the development of rich interface controls is their scalability. Although all latest generation of major browsers supports zooming, there will still be users who prefer to browse their web applications using an increased text size. For this reason, your slider must always inherit the user’s selected text size. This means that either the whole slider must resize, or at least its textual parts. Also, the slider’s behavior must not break, and still give a correct indication of the currently selected value when text size is changed.

The key to achieve this level of scalability is to ensure all positioning and sizing is done using relative units. This must also apply for the slider’s dynamically created units and coordinates, which is tricky as JavaScript generally only provides such dynamic information as pixel values. In order to convert these to relative units, the TPGi slider manager creates a hidden <div> element that has a width and height of 1em. As the user increases the browser’s text size, this element will grow along with it. Whenever the slider needs to know the current size of 1 em in pixels, this hidden element is measured using its clientWidth property. This number is then used to convert any pixel value the slider uses into em values. For example, to position the slider thub when the slider value changes, you can use the following (simplified) code:

myThumb.style.left = px2Em(newPosition) + "em";

In this snippet, the ‘newPosition’ variable is the pixel value calculated by the slider script. To ensure that the thumb will remain correctly positioned when the slider resizes due to a change in text size, we convert the value to ems by sending it to a function which simply divides the number by the number of pixels that currently fit in 1 em.

The TPGi slider’s scalability depends on two parameters, which can be specified using absolute or relative units:

tpg_railLength
This specifies the slider’s width (for horizontal sliders) or height (for vertical sliders). If specified using relative units, The slider will get longer when the browser’s text size increases.
tpg_thumbThickness
This specifies how ‘thick’ the slider should be. To make this dimension scale, provide a relative unit. If specified using relative units, The slider will get thicker when the browser’s text size increases.

How far should your slider be able to scale without making a mess of the rest of the page? WCAG 2.0 mentions a scale factor of 200%, so try to at least support that. If your design does not permit for sliders to grow in size, at least use the parameter system to provide the user with a preference that enables a large font version of your application. This way, you can manually ensure that the large slider will fit using a customized stylesheet.

As shown in this example, using an image input control as the slider’s thumb also has the advantage that you can have your image based control scale along with increases in text size, something you simply cannot do with CSS backgrounds. To prevent pixellation, it is recommended to make the original image a bit bigger than the default size.

Applying the ARIA

There is a lot of information regarding best practices for applying ARIA, and I will probably do a separate post just for that topic some day. For now, let’s just cover some basic points about how the ARIA is applied in this component. First of all, if you are dealing with a complex web application it is recommended to dynamically apply the ARIA role and state attributes using scripting rather than hardcoding them into the HTML source. The ARIA syntax has settled down a lot, but there is always the possibility that things may change. Using a centralized function to apply an ARIA attribute means you will only have to make that change once rather than many times. This will keep your ARIA much easier to maintain, update or disable when needed needed. For example, in order to make the TPGi slider compatible with Firefox 2, a simple browser check is performed to determine whether ARIA properties need to be namespaced or not. As the correct and current syntax for ARIA must be without namespaces, this browser check will be easy to phase out once Firefox 2 becomes less used. This will take a lot less work than having having to update every ARIA attribute individually.

Additional Features

One important aspect of a slider is that it’s easy to read and understand. Visually you can achieve this by adding a value scale adjacent to the slider. In the TPGi slider such a scale can be enabled by specifying the tpg_showScale-true parameter. Ideally a scale is included as actual text rather than an image, so that it inherits any accessibility theme the user might have enabled. At the same time, the scale should not make navigation more difficult for screen reader users browsing in virtual mode. In he TPGi slider, the scales are marked up as a definition list, making it easy for screen reader users to identify and skip past the scale. It must be noted though that a slider is a typical web application control, which means that it is meant to be used in a non-virtual screen reading mode.

Additionally, screen magnifier users may have problems perceiving the slider value while dragging the thumb. For this purpose the TPGi slider can be shown using a dynamic label, which moves along with the thumb while it is being dragged.

About the Code

The TPGi slider is still a work in progress, and should be considered as a proof of concept for making accessible widgets with ARIA. Here are some of the issues that have not been resolved yet.

  • As mentioned in my previous post, the alt attribute used for the slider’s thumb currently overrides the aria-labelledby property, making it difficult to store additional information in the alt attribute for backwards compatability. For this reason, I currently give the alt attribute the same label as the actual slider. Additionally, I use the title attribute to specify extra information about the currently selected value. Unfortunately, most screen readers will not read this property as the alt attribute is already present, so it is always important to give users the option to keep all original form controls which are fully accessible. Additionally, IE8 beta 1 incorrectly exposes the image’s ‘src’ attribute as the slider’s value.
  • Opera does not seem to cancel key down events, causing the page to scroll when the slider’s value is changed. Also, Opera shows some visual junk when the slider is dragged. Version 9.5 beta is needed to make the slider rail properly focusable.
  • Rail Focus does not work in Safari.

Next Time

In my next post, I will discuss how slider related ARIA properties are handled when creating a double slider.

Categories: Technical
Tags: , ,

Comments

Looks fantastic!

Do you have a licensing model for this? I.e. are we free to reuse?

Michael

Hans Hillen says:

Hi Michael,

The slider component is provided under Creative Commons license and is free to reuse. As mentioned in the article, the component is not completed yet. If you want to try it out before it becomes available, you can download the TPG Slider source code. This includes the example page as well as basic instructions of use.

mike foskett says:

Hi,

Thanks for a great article.
I’m about to implement sliders in a widget for Tesco and you’ve cut my learning curve dramatically.

Enough of the well deserved praise.
I hate to inform you that the examples in the article are not working. Though the demo page is fine.

thanks for the heads up, will tell hans.

Hans Hillen says:

Thanks for letting us know. Unfortunately, I just can’t get scripts to work inside WordPress posts anymore. I’ve taken the easy solution and removed all in-post working examples. Instead, the examples can be viewed in the Slider Demo Page