It's becoming increasingly common for web pages to include input fields, especially search fields, that prompt the user with placeholder text inside the input field, rather than a separate visible label. The main argument I've heard for doing so is to conserve scarce screen real estate.
I've seen this implemented in a variety of ways, some more accessible and usable than others. This blog post is my attempt to test a few of these methods, and identify a best practice for how to do this in a way that works for everyone.
You can access all the example pages together on my Form Test home page, or access each example page individually by following links in context below.
Example 1
The simplest method for pre-populating an input field is to simply add content to it's value attribute, like so:
<input type="text" name="search" id="search" value="Search" />
However, there are problems with this approach.
First, the default value does not disappear when the user clicks on the field. Therefore the user could accidentally append their own text to the default text, and submit that mess as their search query. If they're aware of the default text they might delete it before typing their own text, but this is burdensome for the user.
The above problem could be addressed by using Javascript to clear the default value when the field receives focus (I've done this in subsequent examples). However, if we use Javascript at all, it isn't going to work for users without Javascript enabled. Therefore we should pre-populate fields only for Javascript users, rather than burden non-Javascript users with a half-broken solution.
Another potential problem with this example is that there is no <label> element. In fact, the pre-populated value is often used by developers as a substitute for a label. Is this ok? Let's consider it for a moment. The applicable success criterion in the W3's Web Content Accessibility Guidelines 2.0 is SC 2.4.6, a which says "Headings and labels describe topic or purpose. (Level AA)". In the WCAG 2.0 Glossary, the definition of term "label" says (in part) "The term label is not limited to the label element in HTML." Therefore, some might argue that providing a label within the value of the input text satisfies this criterion. But does it work?
Current versions of JAWS, Window-Eyes, NVDA, and VoiceOver all read the value, just as they would read a label, when the field receives focus. So far so good.
However, if the user deletes the prompt or replaces it with other text, and then navigates elsewhere on the page and returns later, the prompt is no longer available. Given this, my position is that pre-populated input values should not be used as a substitute for HTML <label> elements. If there's no space available in the design for a visible label, and the purpose of the field is obvious based on its position and context, the label could be positioned off-screen so it's only visible to screen reader users.
Also, if the field is pre-populated using Javascript (as recommended above), then users without Javascript would receive no prompt whatsoever unless a label is present.
Example 2
This example differs from Example 1 in several ways:
In the HTML markup, a label has been added (and explicitly associated with the input field), and there is no value by default (it's added later using Javascript).
<label for="search">Search:</label>
<input type="text" name="search" id="search" />
Using Javascript, we wait until the window has fully loaded, then call a function that initializes the form by:
- populating the input field with a default value
- adding an event listener that clears the default value when the user clicks on the field.
This example is ok for most users. If mouse users click on the field (or even on its label) that has the desired effect of clearing the field. Also, when keyboard users tab to the field in any browser, the value is automatically selected and will disappear as soon as they begin to type.
However, this example does not work for screen reader users, at least not in Windows. Here's what happens for them:
- JAWS users can navigate to the first (next) form field using the shortcut key "f". JAWS announces the field, its label, and its default value. Users can then give the field focus and enter forms mode by clicking with the mouse button or pressing Enter. However, doing so does not trigger the click event. Therefore the Javascript that clears the field is not activated.
- NVDA users can also navigate to the first (next) form field using "f". When they do so, they jump directly into the form field, ready to enter text. Again, the label and value are announced. And again, the click event is not triggered. Therefore the default text does not disappear.
- For Window-Eyes users, the "f" key jumps to the first (next) form, then users must hit "c" to navigate to the first control within that form, and Enter to give that control focus. Again, this does not trigger the click event and the default text does not disappear.
The solution is to use the focus event rather than the click event.
Example 3
This example uses the focus event to trigger the clearing of the default value, and adds a blur event to restore the default value if users leave the field without entering new text.
The HTML for this example is the same as in Example 2, but the Javascript is different. Here's the entire relevant Javascript block:
function init() {
var defaultSearch = 'powered by Google';
//add default value to search
document.getElementById('search').value=defaultSearch;
//when either search field gets focus, remove the pre-populated text (if it exists)
if (document.addEventListener) { //browser supports addEventListener
document.getElementById('search').addEventListener('focus',function (e) {
if (document.getElementById('search').value==defaultSearch)
document.getElementById('search').value="";
},true);
}
else if (document.attachEvent) { //browser is IE
document.getElementById('search').attachEvent('onfocus',function (e) {
if (document.getElementById('search').value==defaultSearch)
document.getElementById('search').value="";
});
}
//when either search field loses focus (e.g., user tabs away)
//if field has no value, restore default value
if (document.addEventListener) { //browser supports addEventListener
document.getElementById('search').addEventListener('blur',function (e) {
if (document.getElementById('search').value=="")
document.getElementById('search').value=defaultSearch;
},true);
}
else if (document.attachEvent) { //browser is IE
document.getElementById('search').attachEvent('onblur',function (e) {
if (document.getElementById('search').value=="")
document.getElementById('search').value=defaultSearch;
});
}
}
window.onload=init;
This example seems to provide maximum accessibility and usability for all users. However, as always I'm open to feedback and suggestions.



No comments:
Post a Comment