Label inside input fields

Hi everyone,

I have the following code for a form that I’m doing:

<div id="newsletter">
<form action="" method="post">  <fieldset>
    <legend>Subscribe to our newsletter</legend>
    <ol>
    <li>
    <label for="name">Full Name:</label>
    <input id="firstname" name="firstname" class="text" type="text" />
    </li>

    <li>
    <label for="email">Email:</label>
    <input id="email" name="email" class="text" type="text" />
    </li>
    </ol>
</fieldset>

<fieldset class="submit">
<input class="submit" type="submit"
value="Subscribe" />
</fieldset>
</form>

I’m using label tags etc. for accessibility but as I’m trying to locate the form in a relatively small space on the web page, I was going to position the labels off the page, ie.

label {
position: absolute;
left: -9999px;
}

or something like that. I then wanted to float the two input text fields so they’re side by side but since I’ve positioned the labels offscreen I wanted to put the labels inside the input fields, eg. Type your full name, Type your email. I just don’t know how to get them in the inputs though.

Can anyone help me out here? Also is doing this ok from an accessibility perspective?

Appreciate any advice.

HI,

If you want text inside your input then you use the vallue attribute.


<input id="firstname" name="firstname" class="text" type="text" value="[B]Enter Name...[/B]" />


Jquery has some routines for clearing the input text when the element has focus that you might look into to stop people having to rub it out before they type.

Placing the labels off screen is better than display:none and is more accessible.

<label for=“name”>Full Name:</label>
<input id=“firstname” name=“firstname” class=“text” type=“text” />

The “for” attribute of the label should (must) match the id of the input, so the above code has the label not linked to the input.

If you’re going for multiple inputs for one label, one way I’ve done is this way:

<label for=“birthdate”>Date of birth (dd/mm/yyyy): </label>
<input type=“text” id=“birthdate” name=“bday” title=“Enter two-digit day” maxlength=“2”>
<input type=“text” name=“bmonth” title=“Enter two digit month” maxlength=“2”>
<input type=“text” name=“byear” title=“Enter four digit year” maxlength=“4”>

http://juicystudio.com/article/invisible-form-prompts.php

old link but the technique still seems to work

Maxlength is there to reinforce the instructions, which is helpful.

Another way I’ve done it:


(inside the form's main fieldset...)
<div>
  <normal label>Label: </label>
  <normal input...>
</div>
<fieldset class="access">
  <legend>Date of birth</legend>
  <p>Date of birth: </p>
  <label [b]for="day"[/b]>Day: </label>
  <input type="text" [b]id="day"[/b] name="bday" maxlength="2">
  <label [b]for="month"[/b]>Month: </label>
  <input type="text" [b]id="month"[/b] name="bday"  maxlength="2">
  <label [b]for="year"[/b]>Year: </label>
  <input type="text" [b]id="year"[/b] name="bday" maxlength="4">
</fieldset>

next div with label-input pair...

fieldset.access has the same CSS code as the divs, so it does the same job

fieldset.access legend is moved off-screen, but heard by screen readers who have a Forms Mode.

fieldset.access p is styled like most labels, and is for the sighted users, and as a non-form control it is not read out by any screen readers who have a Forms Mode.

fieldset.access labels are either display: none or pulled offscreen.
Display: none on the Big 2 Windows screen readers (JAWS and Window-EYes) seem to be read out despite their display: none status, for some special reason. Pulling the labels offscreen is a nicer idea, but
Safari and Chrome have some display bug where the abso-po’d labels cause the inline-block inputs to start new lines. For this reason I’ve sometimes display: none’d the labels.

Another way I’ve done it:

<label for=“postcode”>Postcode: </label>
<input type=“text” id=“postcode” name=“postcode1” title=“first 4 digits of postal code” maxlength=“4”>
<label for=“postcode2” class=“access”>Postcode letters: </label>
<input type=“text” id=“postcode2” name=“postcode2” maxlength=“2”>

label.access {
position: absolute;
left: -999em;
}

Again, this makes it look like this in most browsers:
Postcode: 3362 AB

But in Safari and Chrome it’s
Postcode: 3362
AB

So for this reason I’ve been forced again to use display: none instead, relying on the Big 2 still reading them out.

The problem with this though is that there are other readers: NVDA for Windows is free, Orca for Gnome desktops on Linux/OpenSolaris is free and does not have a virtual buffer (I can’t figure out yet if there’s a Forms Mode as I still have trouble working it), VoiceOver comes on all OSX Macs.

Javascript can clear input values. eg.

<input type='text' id='s_str' name='s_str' value='Enter Search String here' />
<script type="text/javascript">
	//<![CDATA[
	var inp = document.getElementById('s_str');

	inp.onfocus = function()
	{
		if (inp.value == 'Enter Search String here')
		{
			inp.value = '';
		}
	};
	//]]>
</script>

Of course that depends on javascript being enabled to do the clearing. For accessibility it would be better to have javascript both insert the value and clear it. eg. onload inp.value = ‘Enter Search String here’;

I then wanted to float the two input text fields so they’re side by side but since I’ve positioned the labels offscreen I wanted to put the labels inside the input fields, eg. Type your full name, Type your email. I just don’t know how to get them in the inputs though.

I was re-reading this… I’m not sure I’d want to rely on value text (or javascript to give me value text) to represent off-screen labels in any non-trivial form.

If your form is really that small (name, email, submit) then you may be able to get away with it, but do some usability testing if you do (grab your friends and coworkers, anyone who hasn’t seen the site, and ask them to fill the form in). If you manually put the text in the values as Paul suggested, it means those of us without JS will be backspacing or highglighting-and-deleting the text first (which is annoying but still perfectly useable).

If you use Mittaneague’s suggestion (which normally I support), those without JS will need to read the labels, and sighted users with CSS on may well have JS off, meaning they’d get no labels whatsoever.

I’ve seen a unique JS which did the adding of the value text in the inputs, and by default (no js) the label was visible, and when JS was running the labels were then moved offscreen (JS added a class which had the styles for offscreen). This is a possibility, becuase then JS makes a cleaner-looking form with input value text doing the work of the labels, while those without JS get plain labels (we expect pages to look uglier when we surf without JS… but we also expect the page to “work” too).

Thanks for all the detailed replies guys,

I’d really just like a javascript clearing method that clears the value text. I don’t really think it’s necessary to have it insert it also. I mean the site has a whole lot of other javascript so I guess if someone doesn’t have it turned on, then they’re going to miss out on the rest of the site functionality anyway.

But I just have a related question re the structure of the form. As displayed in my first post, the form has the two fieldsets and all the li elements. Since I’m floating the two li elements which contain the input text fields, I found that not only did I need to float the li’s but I also had to float the fieldset that contained them. Then I also had to float the second fieldset that contained the input submit button (ie. so I could float this to the right). Then to get it all working I had to add another float_wrapper that contained everything inside div#newsletter and float this also.

So for such a simple form, are all the fieldsets and other elements really necessary. Surely there’s an easier way to layout such a tiny form?

div#newsletter {
	position: absolute;
	left: 0;
	top: 5px;
	font-size: 10px;
	color: #fff;
	width: 500px;
}

div#newsletter legend {
font-weight: bold;
}

div#newsletter input.text {
width: 160px;
height: 20px;
}

div#newsletter label {
position: absolute;
left: -9999px;
}

div#newsletter div#float_wrapper {
width: 500px;
float: left;	
}

div#newsletter fieldset.main  {
width: 350px;
float: left;
}

div#newsletter fieldset li {
float: left;
height: 20px;
}

div#newsletter fieldset li#first {
margin-right: 10px;
}


div#newsletter fieldset.submit  {
width: 100px;
float: left;
padding-top: 15px;
}
v

But I just have a related question re the structure of the form. As displayed in my first post, the form has the two fieldsets and all the li elements. Since I’m floating the two li elements which contain the input text fields, I found that not only did I need to float the li’s but I also had to float the fieldset that contained them. Then I also had to float the second fieldset that contained the input submit button (ie. so I could float this to the right). Then to get it all working I had to add another float_wrapper that contained everything inside div#newsletter and float this also.

You seem to have run into one of the solutions for float enclosement, called “Float Absolutely Everything” : ) And you’re right, there’s other ways around this and yes it can be done with less code. I will post some example code but I may well miss the actual current layout you have so let us know if this isn’t looking right.

Gary’s article goes over the basic issue: in modern browsers, floats hang out of their containers… so, containers don’t enclose their floated children. As you’ve found, floating the container fixes this… but oh noes, you ended up in the vicious cycle of floating! One of the most popular ways of enclosing floats is to give the container overflow: hidden, which our very own Paul O’B came up with years ago. Just be careful, overflow:hidden has a Day Job: hiding overflow (of containers with set dimensions). Of course, IE6 needs Haslayout set. IE7 is ok as setting overflow triggers Haslayout in that browser anyway.

Tony Aslett’s “clearfix” is another solution, one I tend to use if overflow: hidden is hiding stuff on me : )

You can also lose the list. Unless you really do consider it a list of questions, you can use the semantically meaningless “div” to group label-input pairs for styling purposes (div means nothing more than “a division for some reason” so it’s nice) and fieldsets should group similar chunks/groups of questions.


<form action="somethin" method="post" id="newsletter">
  <fieldset>
  <legend>Subscribe to our newsletter</legend>
    <div>
      <label for="fullname">Full Name:</label>
        <input id="fullname" name="firstname" type="text" value="Full Name" />
    </div>
    <div>
      <label for="email">Email:</label>
        <input id="email" name="email" type="text" value="Email address" />
    </div>
    <div>
      <input type="submit" class="submit" value="Subscribe" />
  </fieldset>
</form>

That’s a basic version of your form, with the value text in there. No need to give the submit button its own fieldset; fieldset does mean to refer to a related group of questions. If it weren’t for IE bugs I’d have the submit by itself, but it’s safer and more semantic to wrap it in a block element, so I have it in a div here.

There’s another method used for writing forms, where the label itself is the block container. It’s perfectly legal but there were some issues with an old screen reader and an intermittant issue with some Macs. Read more about that if you’re interested.

Mittaneague gave you an example of some JS that would do the job. Another thing you can do instead of removing the text is highlighting it (using select()), so users can still read it but can remove it with a single backspace click.

We could give an example CSS if we knew how you’re trying to lay this form out. Only inputs showing, no labels (labels off-screen), anything else?

*edit also I see things referenced in your CSS that I don’t see in your HTML you originally posted, so to be clear, my form HTML above is based on the HTML you posted.

Thanks again for such a detailed response.

In the original html that I posted, there’s a legend with some text in it and then the rest of the form. So basically I’d need the legend text to be to the left, and then to the right of it would be the first input text field asking for the full name, then to the right of that would be the email text field - again asking for the email address inside the value. Then finally to the right again is the submit button. So it would all be in one line.

Re the javascript, I thought that the code given by Mittineague both inserted the value and cleared it, but on taking a second look I see that it just clears so this could be a solution.

It may be difficult to pull all the other labels up to the level of the legend (since every browser seems to do something weird and different with the legend) but you could float the divs to replace the floating of li’s to get everyone else in one line.

Ok - I’ll try that. Thanks again