Mike Cravey

Accessible Inline Form Labels

Update: Added the check to make sure the input is empty before showing the overlayed label the first time.

I recently read Trevor Davis‘ post on inline form labels. First off, I have the utmost respect for TD. I read his blog regularly and have learned a lot from his posts. While I respect the work he has done for his plugin, I approach things differently. I am a UX Architect for a government site so I have significant concerns about accessibility, semantics and progressive enhancement.

My approach differs from him in 2 main facets:

  1. He is pulling his inline form label value from the title attribute. I am using the actual label. I feel this is more semantic.
  2. He is adding and removing a value to the form field. This can cause validation and styling issues. I am going to overlay the label on to the form field therefore not mucking with the value of the field.

That is not to say my technique is not without issue. It relies on good support of the CSS box model.

Markup

	
		<form id="contact">
			<ul>
				<li>
					<label for="name">Name</label>
					<input type="text" id="name" name="name" value="" />
				</li>
				<li>
					<label for="email">Email</label>
					<input type="text" id="email" name="email" value="" />
				</li>
				<li>
					<label for="verbiage">Message…</label>
					<textarea id="verbiage" name="verbiage" rows="5" cols="25"></textarea>
				</li>
			</ul>
		</form>
	

Simple markup, just your basic form. I’m an unordered list guy for forms, but certainly your favorite method of marking up forms should be fine. Except for tables, cause that’s just wrong.

Stylings

	
		form li {
			line-height: 1.5;
			margin-bottom: 1.5em;
			position: relative;
		}

		form label.overlayed {
			position: absolute;
			top: .15em;
			left: .5em;
			white-space: nowrap;
			color: #999;
		}
	

Again, simple stuff, note the position: relative on the li. That’s sets a bounding box for everything inside of it. Then we are free to use position:absolute for the label (when overlayed). That effectively removes it from layout allowing the inputs to slide left (or up, depending on your form layout).

Notice the use of the overlayed class. I could just style the labels this way by default, but the whole technique here needs javascript. As a general rule of thumb, I use the same technology to add something as I use to manipulate it. Since I will need JavaScript to manipulate the label visibility, I will use JavaScript to put it in position to begin with. I could have styled the label in a default manner (left of the input, above the input, etc) but chose not to for simplicity’s sake.

Scripting

	
	var oTxtFields = $('input,textarea');
	$.each(oTxtFields, function(){
		var label = $('label[for=' + $(this).attr('id') + ']');
		label.addClass('overlayed');
		if (!$(this).val() == '') {
			label.hide();
		}
		$(this)
			.focus(function(e){
				$('label[for=' + $(e.target).attr('id') + ']').hide();
			})
			.blur(function(e){
				if ($(e.target).val() == '') {
					$('label[for=' + $(e.target).attr('id') + ']').show();
				}
			})
		;
	});
	

This code is relatively simple as well but let me point out a few things. Obviously this is assuming jQuery is loaded. Setting a native object for the form elements saves a lot of processing time. Doing the jQuery lookup every time you reference the object is very expensive. Do it once and store it to an object.

Moving on, for each form element set a label variable based on the associated label tag then add the class overlayed to the label. This will position the label inside the form field. Since JavaScript is needed for this technique, we want to initialize the whole thing with JavaScript. You don’t want to end up in a situation where the user has stylesheets capabilities but not Javascript leaving them with an overlayed label and no way to hide it.

Finally we add some event listeners for each form field. The first is a focus which does a lookup on the label associated with the field that has focus and hides it using jQuery’s hide method.

The second event listener added is for blur. If, on blur, the form field value attribute is empty we show the associated label using jQuery’s show method.

That’s about it. I hope you found this technique useful. If nothing else, maybe you found this to be an alternative to Trevor’s inline form label technique. If I get enough interest I will look into creating a jQuery plugin for this. Feel free to wholesale reuse this technique. I hardly coined it, I just blogged it.

5 Responses to “Accessible Inline Form Labels”

  1. Trevor Davis says:

    Mike-
    Thanks for the nice remarks.

    I am curious to know what your accessibility concerns were with using the title attribute. As I said in the comments on my article, I would use a regular label element as well, but just push it off the screen for users with CSS enabled.

  2. Trevor Davis says:

    Also, just as a note, you may want to check the value of the input before overlaying the label. When fields (like the fields in this comment form) are already populated with data, they overlap the labels.

  3. craveytrain says:

    Actually, the title thought process wasn’t so much an accessibility concern as a semantic one. Felt like I was duplicating content. Why have a label and title with the same content (that obviously being the assumption)?

    Good point on the checking for a value before overlaying the label. I had assumed all input values would be blank when one hits the page, but that’s not a fair assumption. Time for my first (of probably many) update.

  4. LuK says:

    Hi,

    nice blog & thanks for that article…I’m here because I found out recently that the list is more semantic for forms (I used divs before and had my labels and inuputs in them), I already used a script (the attardi one http://attardi.org/labels/) to put the labels inside the form fields but the html markup which is used for that script is not very semantic (not even labels are used…) so I want to improve my forms and found your article…

    now my question: How about leaving the label in the input field until the user begins to type text in it? The “problem” (it’s really a detail…I know) is that a user could forget what he/she should write in the field (yes, there are such people =D) and when the script hides the label on focus that could be the case…what do you think about that and how could it be implemented in your script?

    forgive the poor language!

    regards,

    LuK

  5. craveytrain says:

    I’m glad someone found this article useful.

    As for your question, I just saw something the other day that could make total sense to add to this, sliding labels. I may update this script with this functionality and submit it as a proper plugin sometime soon.

Leave a Reply