The form label element is an incredibly useful little element – it lets you link the form field unquestionably with the descriptive label text that sits alongside or above it. This is a very useful feature for people using screen readers, but there are some problems with this element.
What happens if you have one piece of data that, for various reasons (validation, the way your data is collected/stored etc), needs to be collected using several form elements?
The classic example is date of birth – ideally, you’ll ask for the date of birth once but you may have three inputs, one each for day, month and year, that you also need to provide hints about the format required. The problem is that to be truly accessible you need to label each field. So you end up needing something to say “this is a date of birth”, “this is the day field”, “this is the month field” and “this is the day field”. Seems like overkill, doesn’t it? And it can uglify a form no end.
There are various ways that you can approach it (and I think I’ve seen them all). Some people omit the label and rely on the title attribute to help the user through; others put text in a label but make the text 1 pixel high and merging in to the background so that screen readers can still get that information. The most common method, though, is simply to set the label to not display at all using the CSS display:none property/value pairing (a technique which, for the time being, seems to work on most screen readers). But perhaps we can do more with this?
The technique I am suggesting as another alternative is as follows (here comes the pseudo-code):
- Start with a totally valid and accessible form
- Ensure that each form input has a
labelthat is linked to its related form control - Apply a
classto anylabelthat you don’t want to be visible (for examplesuperfluous)
Then, through the magic of unobtrusive JavaScript/the DOM, manipulate the page as follows once the page has loaded:
- Find all the
labelelements that are marked as superfluous and hide them - Find out what
inputelement each of theselabelelements is related to - Then apply a hint about formatting required for input (gleaned from the original, now-hidden label text) – add it to the form input as default text
- Finally, add in a behaviour that clears or selects the default text (as you choose)
So, here’s the theory put into practice – a date of birth, grouped using a fieldset, and with the behaviours added in using DOM, and here’s the JavaScript that does the heavy lifting.
But why not just use display:none? As demonstrated at Juicy Studio, display:none seems to work quite well for hiding label elements. So why use a sledge hammer to crack a nut? In all honesty, this is something of an experiment, but consider the following:
- Using the DOM, you can add extra levels of help, potentially across a whole form – or even range of forms – without necessarily increasing your markup (it goes beyond simply hiding labels)
- Screen readers today may identify a
labelthat is set not to display, but they may not in the future – this might provide a way around - By expanding this technique above, it might be possible to visually change the parent container that groups these items – in this case, a
fieldsetandlegend, which are notoriously difficult to style consistently across different browsers – while still retaining the underlying semantic/logical structure
Well, it’s an idea to think about at least. How is it for you? How else might you use DOM scripting to improve the accessiblity or usability of your forms?


Comments
Comments are ordered by helpfulness, as indicated by you. Help us pick out the gems and discourage asshattery by voting on notable comments.
Got something to add? You can leave a comment below.
03/12/2005
@gillbates: I’ve aluded to doing that in the last paragraph – a combination of CSS and DOM scripting to get it looking like a normal label, but retaining the semantic relationship that you get with fieldset/legend and contents. The DOM part could come it to hide the fieldset and legend (because they are such a bitch to style in CSS) and use the text found in the legend to create a new (easy-to-style) text element elsewhere. Am I making sense here? It’s early in the morning and I’ve yet to have a cup of coffee!
Vote Helpful or Unhelpful
03/12/2005
Just a quick question, why not use fieldset instead of label (maybe even styled as the rest of the form’s labels) in the case of a D.O.B. or other “multi-input inputs”?
Vote Helpful or Unhelpful
03/12/2005
Very nice article
Vote Helpful or Unhelpful
03/12/2005
I gotcha Ian, I re-read everything paying real attention and it became clear that you had already addressed this. I guess I must’ve missed my coffee when I read it =)
Vote Helpful or Unhelpful
03/12/2005
Cool. I’ve been making webforms for years. I had no idea how much of a noob I was. ;-)
Is the “for” attribute a defined attribute or is it something you just made up to work with your script ?
And what does the thisId = labels[i].htmlFor; do?
isn’t getAttribute supported by IE ?
Vote Helpful or Unhelpful
03/12/2005
Welcome to the dark side, Ian. You’ll like it here.
Vote Helpful or Unhelpful
03/12/2005
Russell: yes and no.
forandclassare two attributes IE does not play well with. To change theforattribute in IE, you needhtmlForand forclassyou needclassName. Most other browsers supportget/setAttributeonforandclass.Now if you want to see something really screwy, check out how you need to work with IE on form elements you want to set a
nameon.Vote Helpful or Unhelpful
05/12/2005
Labels are also extremely useful for radio buttons and checkboxes: You can click on the text enclosed by the label and check the item.
Labels, when assigned a width and floated, also make for an easy way to align form inputs. To see some of this in action check out this monstrous signup page I put together
Vote Helpful or Unhelpful
05/12/2005
Instead of getting the text by using
labels(i).childNodes(0).nodeValueand parsing the string, why not use the title attribute of the label element, which “offers advisory information about the element for which it is set.” (WC3 Recommendation).It seems the perfect fit, not only semantically correct, but
format = labels(i).title;is certainly a less brittle implementation than
var format = labels(i).childNodes(0).nodeValue;var startpoint = format.indexOf("(format ")+ 8;var endpoint = format.indexOf(")");format=format.substr(startpoint,(endpoint-startpoint));Does this make sense?
—Scott, who does know that those are supposed to be square brackets, but Textile isn’t playing nicely with source code…Vote Helpful or Unhelpful
06/12/2005
Great solution and very nice article :)
Vote Helpful or Unhelpful
08/12/2005
“But why not just use display:none?”
Because display:none makes some screen readers ignore the content and not read it. This is a very nice way of doing it!
By the way, you might want to fix the tab order on this form, as tabbing from “http://” to the Message takes me to the logo at the top of the screen!
Vote Helpful or Unhelpful
10/12/2005
The off left technique is a better solution than
display:nonewhich, as Simon points out, most screen readers honor by not announcing it. See discussion at : http://css-discuss.incutio.com/?page=ScreenreaderVisibilityNo js required, hiding labels can be solved with a little css.
label {
position:absolute;
left: -9999px;
}
That said, IMHO it is better for accessibility to leave the labels visible so you have a bigger target to hit with your mouse – clicking the label focusses the field which is good for people with motor disabilities.
Vote Helpful or Unhelpful
Impress us