Category Archives: Categorized

Use of aria-describedby with form elements that have descriptor text

If form fields have formatting help or descriptor information for the input, such as “Passwords must be 8 characters long”, one cannot assume that screen readers are reading that input by default.

<label for="choosePassword">Choose Password:</label>
<input id="choosePassword">
<span class="help">Passwords must be 8 characters long</span>

When users tab through the form, and focus to this field is reached, assistive technology such will say “tab Choose Password colon edit” (JAWS, in this case, with verbosity settings set to advanced). This user is completely missing out on needed information to fill out the form field.

For a screen reader to read the help text, one can address this gap in one of two ways. One way is to incorporate the extra text as part of the label:

<label for="choosePassword">
    Choose Password:
    <span class="help">Passwords must be 8 characters long</span>
</label>
<input id="choosePassword">

For some web designers this is perfectly fine. They will nest the descriptor text within the label, and leave it there, or perhaps use CSS to position that element elsewhere. Screen readers will read the descriptor text just as it normally would read the label.

The second way is to use the aria-describedby attribute:

<label for="choosePassword">Choose Password:</label>
<input id="choosePassword" aria-describedby="choosePasswordHelp">
<span class="help" id="choosePasswordHelp">Passwords must be 8 characters long</span>

The aria-describedby attribute value should match the id of the descriptor text. JAWS will read the above as “tab Choose Password colon edit Passwords must be 8 characters long”.

Using aria-describedby much less intrusive on your HTML than nesting potentially long descriptor text into the label, as it’s merely the introduction of an attribute on existing markup. The downside is that not all assistive technologies necessarily support aria attributes. In this case, the JAWS screen reader and VoiceOver do support aria-describedby, and that’s enough for me to adopt aria-describedby as part of my regular practice. (NVDA does not support it as of this writing according to my tests, and I don’t know about Window-Eyes and other technologies.).

Even more uses

aria-describedby need not be limited to one value, but instead it allows a space-delimited set of values (like the class attribute). This can come in handy in the instance that there are errors related to a field in question.

<p id="error_choosePassword" class="error">Error: Please enter a valid password.</p>
...
<label for="choosePassword">Choose Password:</label>
<input id="choosePassword" aria-describedby="error_choosePassword choosePasswordHelp">
<span class="help" id="choosePasswordHelp">Passwords must be 8 characters long</span>

Now when focus is put on the text field, JAWS will say “tab Choose Password colon edit Error colon Please enter a valid password. Passwords must be 8 characters long”.

Getting around the flicker of JavaScript modifying the DOM while the page is loading

When building things with progressive enhancement, I often want the page styled a certain way when JavaScript is on vs off. When you use $(document).ready() in order to modify your page, you may end up watching the page modify before your very eyes, and if you’re like me, wish you could find a way around it.

For instance, I might have portions of a form hidden by default unless the user clicks an option to expand it. My old method was to show it all by default, then using $(document).ready(), hide those options. The problem is that I would see a flicker as elements start appearing then disappearing on my screen.

Now I use this method:

<body class="nojs">
    <script>
      var bodyEl = document.getElementsByTagName('body');
      bodyEl[0].className = bodyEl[0].className.split('nojs').join(' jsEnabled ');
    </script>
    ...
</body>

So by default, my page has a nojs class. And a script runs immediately after to remove that class, and to add in a ‘jsEnabled’ class in its place. I can then do things in my stylesheet like this:

.conditionalContent { display:none; } // what I really want to happen
.nojs .conditionalContent { display:block; } // in case JS is disabled

This accomplishes the same thing as I was trying to do above (keep an element hidden by default if JavaScript is disabled, but show it by default if JavaScript is disabled) but without the flicker.

And then you also have an option to make use of .jsEnabled class in the stylesheet as well.

If you happen to have jQuery pulled into your site in your <head>, you can use this instead:

<body class="nojs">
    <script>
      $('body').removeClass('nojs').addClass('jsEnabled');
    </script>
    ...
</body>

If anyone’s discovered other methods of getting around this type of issue (like using Modernizr, or something else), I’d love to hear about it.

CSS gradients and background images

Let’s say you have a web page with a solid pale blue background color with a background image positioned on top of it.

body { background: #a5c9e5 url(img.png) no-repeat 50% 300px; }

And this is the result:

See example 1 HTML.

Then you heard about CSS3 gradients and thought, “Wow! Now instead of a solid pale blue in the background, I can have a dark blue to pale blue fade!”

With this line of thinking, one may think that taking the ‘background-color’ value part of the shorthand above (‘#a5c9e5’), and replacing it with a ‘linear-gradient’ property would do the trick:

body { background: linear-gradient(top, #1e5799 0%,#a5c9e5 100%) url(img.png) no-repeat 50% 300px; }

But that’s not how it works. Despite the fact that you can define them using hexadecimal, rgb, or rgba, CSS background gradients are not like background colors, but instead are like background images.

So to get effect we described above on the same element, our browser would need to support multiple backgrounds, and we’d need to declare it like so.

body {
	background:
		linear-gradient(top, #1e5799 0%,#a5c9e5 100%),
		url(img.png) no-repeat 50% 300px;
}

(Note: For the sake of simplicity, this example CSS is simplified without all the additional declarations that use vendor prefixes.)

But when testing that out, we only see the gradient.

See example 2 HTML

Where’s the background image? It’s there, but under the gradient. The order in which the background images are specified matters. If we rearrange the properties so that the image is first and the gradient is second:

body {
	background:
		url(img.png) no-repeat 50% 300px,
		linear-gradient(top, #1e5799 0%,#a5c9e5 100%);
}

The image will show up as desired – on top of the gradient.

See example 3 HTML.

Think of CSS gradients not as a color, but as images. The guidelines for combining multiple background images apply to CSS gradients, too.

Resources

Source of train picture.

Nudging elements with position: relative

I find that most people are familiar with using position: relative; on a containing element so that its descendent can be absolutely positioned relative to that element. So to get this effect:

The positioning rules would look something like this:

.container {
	position: relative;
}
.container div {
	position: absolute;
	top: 20px;
	right: 20px;
}

Relative positioning is also helpful for positioning the targeted element relative to its expected position in normal flow.

Let’s say I have an image in my document:

<p>This is a paragraph</p>
<img src="img.png" alt="A man on a bycicle" />
<p>This is a paragraph</p>

By default, the markup above looks like this (see example 1 html):

But I’d like it to be pulled out a little for a magazine-like look. I’ll start by adding float:left; to the image so that my text can wrap around the image.

.container img { float: left; }

That will get me this (or see example 2 html):

But I want to pull the image off to the left so part of it is visually extending outside the article. I’ll specify 100 pixels to the left, but first I have to specify position:relative;.

.container img {
	float: left;
	position:relative;
	left:-100px;
}

Resulting in this (or see example 3 html):

Hmmm… but the text is continuing to wrap around the image as if it’s still in its original spot.

That’s relative positioning — the element can be visually offset from its position in the normal flow, but the browser reserves that element’s original space. In order to have our text flow around the image’s new position, we can use negative margins. Since I don’t want the text butting up against my image, I’ll just use 80 pixels instead of 100 pixels, which allows a 20 pixel gutter between the image and text.

.container img {
	float: left;
	position:relative;
	left:-100px;
	margin-right: -80px;
}

Resulting in our desired result (or see example 4 html):

Relative positioning is helpful for not just setting a context for the absolutely positioned elements within them, but can also allow more flexible positioning opportunities. Though this article only covered an example for pulling items left or right, the concept can also be applied to vertical offsets (top and bottom). In conjunction with negative margins, relative positioning can help some designs ‘break out of the box’ allowing elements to extend outside their normal containers.