Accessibility and complex HTML forms: How to use headings between form controls? - html

A client needs to create quite a complex form. We use <fieldset>/<legend> to group certain elements together. But it's not enough - even if we nest them.
Think about the following:
<form>
<fieldset>
<legend>Your personal details</legend>
<label>First name: <input name="first_name"></label>
<label>Last name: <input name="last_name"></label>
<fieldset>
<legend>Gender</legend>
<label>Male: <input type="radio" name="gender" value="male"></label>
<label>Female: <input type="radio" name="gender" value="female"></label>
<label>Other: <input type="radio" name="gender" value="other"></label>
</fieldset>
</fieldset>
</form>
Imagine this is only a small part of a bigger form. For example, we could have a "postal address" and a "billing address". Would we need to "indent" the whole thing once more using <fieldset>/<legend>s?
<form>
<fieldset>
<legend>Postal address</legend>
<fieldset>
<legend>Your personal details</legend>
...
<fieldset>
<legend>Gender</legend>
...
</fieldset>
</fieldset>
</fieldset>
<fieldset>
<legend>Billing address</legend>
...
</fieldset>
</form>
Or should we rather use headings?
<form>
<h2>Postal address</h2>
<fieldset>
<legend>Your personal details</legend>
...
<fieldset>
<legend>Gender</legend>
...
</fieldset>
</fieldset>
<h2>Billing address</h2>
...
</form>
While it's probably valid to nest <fieldset>/<legend>s, I would not over-do it. Party because JAWS will announce the <legend> for each contained input element (in contrast to NVDA that will only announce it once, when reaching the first contained input element).
On the other hand, headings will not be announced at all by desktop screen readers when jumping between form elements using Tab/Shift-Tab. So its information will easily be missed.
What do you think about that, dear screen reader experts? Should we use aria-describedby to attach the headings to the subsequent <fieldset>? What if there's more than one <fieldset> below that heading?
I feel there's no perfect solution here. Any suggestions, please?

It's perfectly valid to nest fieldset+legend, but as you ahve said, some screen readers will repeat it for each of the elements under that legend.
It makes a lot of totally useless redundency.
There is certainly no perfect solution, and no normative solution on this either, but I would go for an hybrid structure.
Use legend only for the deepest level, where elements are really close together such as male/female, yes/no, etc. (i.e. groups of radio buttons), and headings for all the rest and intermediate levels. For example:
<h2>Personal information</h2>
<fieldset>
<legend>Gender</legend>
...
</fieldset>
<fieldset>
<legend>Marital status</legend>
...
</legend>
</fieldset>
<h2>Billing address</h2>
...
<h2>Delivery address</h2>
...
Headings have a great bonus advantage, there are shortcuts keys to jump directly to them. It's especially useful when you want to modify only one or two particular fields in the whole form. You can't do this with legend.
IF you are afraid that the screen reader user miss "Personal information", "Billing address" and "Delivery address", you may use aria-labelledby refering two IDs:
<h2 id="billingAddressHeading">Billing address</h2>
<p><label id="streetLabel" for=street">Street: </label>
<input type="text" aria-labelledby="streetLabel billingAddressHeading"/>
</p>
If you use two IDs like that only on the first field of the group, you make sure that the screen reader won't uselessly read the group label for each of the fields.
Be careful to not forget to reference the label itself in aria-labelledby, because it replaces completely the <label>.
Note that, technically, you are also allowed to use fieldsets without legen.
<h2 id="billingAddressHeading">Billing address</h2>
<p><label id="streetLabel" for=street">Street: </label>
<input type="text" aria-labelledby="streetLabel billingAddressHeading"/>
</p>
As a final note, if you find the form getting too complex, it's maybe the time to think about splitting it into several smaller pages.

Related

Accessibility: the proper html code to pronounce the <form> description by screen readers

Suppose you have a form:
<form action="/action_page.php">
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="Submit">
</form>
How to make it accessible so that the accessibility screen reader pronounces the form name "this is my form about the customers:" when appears on the form?
If Bootstrap is available with its sr-only class, should it be
<form action="/action_page.php">
<legend class="sr-only">this is my form about the customers:</legend>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe"><br><br>
<input type="submit" value="Submit">
</form>
Should <fieldset> be added as well?
Thank you.
The most efficient for such a quite general description like "this is my form about the customers" is probably not <legend>, but simply an heading or paragraph just before the beginning of the form.
A very important feature of <legend> to keep in mind is that its text is repeated before the label of each field.
This is extremely powerful, and so has to be used very carefully.
This repeatition feature implies that legend's text has to be extremely concise and precise, meaning that it should only be used for field very closely related together.
It is typically used for radio button options, like this:
<fieldset>
<legend>Gender</legend>
<input id="m1" type="radio"/><label for="m1">Male</label>
<input id="m2" type="radio"/><label for="m2">Female</label>
<input id="m3" type="radio"/><label for="m3">Other</label>
</fieldset>
Here, as a screen reader, you will hear "Gender male", "Gender female" and "Gender other" as you navigate to the radio buttons. This is quick, efficient, and reminding "Gender" is quite useful.
If the text of the <legend> is long or not really local to a few fields, the fact that it is repeated before each field may quickly become more annoying than really useful.
For example, using it for a multiple choice question is a bad idea because of the length:
<!-- Bad example -->
<fieldset>
<legend>When the first web accessibility guidelines version 1 has been published ?</legend>
<input id="m1" type="radio"/><label for="m1">1995</label>
<input id="m2" type="radio"/><label for="m2">1998</label>
<input id="m3" type="radio"/><label for="m3">2001</label>
</fieldset>
Here you have quite a long question repeated before each answer, so as a screen reader user you can't really be quick and efficient, potentially slightly augmenting the handicap in time limited exams for example. The question would better be in a heading, which will be read only once when reading with arrow keys.
Note that it is completely skipped when navigating only with tab though, but it is'nt usually a big problem since most users don't only rely on tab alone.
<fieldset>
<h1>When the first web accessibility guidelines version 1 has been published ?</h1>
<input id="m1" type="radio"/><label for="m1">1995</label>
<input id="m2" type="radio"/><label for="m2">1998</label>
<input id="m3" type="radio"/><label for="m3">2001</label>
</fieldset>
Coming back to your case, your text "this is my form about the customers" isn't really short either, and especially it's extremely general. The fieldset can cover dozends of fields and will even probably stay for the whole form.
So having it repeated before each field is probably much more annoying than useful.
First, thank you for caring about accessibility, that is really appreciated!
I would suggest a simpler solution: add an aria-label to your form. Thus your form will be virtually wrapped in screen reader announcements, much like a fieldset. Like this:
<form action="/action_page.php" role="form" aria-label="this is my form about the customers:">
But please, make it shorter, like this:
<form action="/action_page.php" role="form" aria-label="Customer data">
We need to process quite a lot of info with our ears or fingers (if reading in Braille), so conciseness is also important.

Title for a form

I am working on an assignment and am a little lost. The question states:
Create a label element with the text Username. Within the label element, insert
an input box for the username field. Make the field required and add the title Supply
your username
Here is what I have. I am mainly confused on the title portion. Any help is greatly appreciated, and feel free to correct me on the other parts. Thank you
<form id="survey" name="survey"
action="www.sblogger/cgi-bin/subcomments"
method="post">
<fieldset id="commentFS"
<label>
Username
<input id="username">
required="required"
</label>
</fieldset>
</form>
You just need to add a title attribute on the input field. Also the label tag can stay on it's own, which leaves to:
<form id="survey"
name="survey"
action="www.sblogger/cgi-bin/subcomments"
method="post">
<fieldset id="commentFS">
<label>Username</label>
<input id="username"
title="Supply your username"
required>
</fieldset>
</form>
The assignment is not well-defined, since it does not say what kind of a title should be included. It may refer to an advisory title that may be presented to user in some situations (e.g., on mouseover), as assumed in #Jeffrey’s answer. It may also refer to text that appears inside the input box when it is empty, in which case you would use the placeholder attribute. It can also refer to visible text before the input box; this would be the most reasonable setup. Even then, there are several alternatives. It could be just text before the label and the input box, or it could be wrapped in a heading element, or even a legend for a fieldset. The following example is based on the wild assumption that such a legend is desired (which might be a wrong guess if you have actually been told to use the fieldset element, as you are using, although there is no reason to use it in a simple case like this).
<form id="survey" name="survey"
action="http://www.example.com/cgi-bin/subcomments"
method="post">
<fieldset id="commentFS">
<legend>Supply your username</legend>
<label>
Username
<input id="username" name="username"
required="required">
</label>
</fieldset>
<input type="submit" value="Submit">
</form>
Notes: The attribute required="required" (or just required unless you have been told to use XHTML syntax) must appear inside the <input ...> element, not after it. And the input element needs a name attribute, otherwise the data in it will not be sent at all to the server.

What's the best way to wrap Label and Input elements

I'm working on a HTML5 form and I want to float some input elements and their labels. Its this the best way to do it?
<form>
<fieldset class="float_left">
<label for="login">Login ID #</label>
<input type="text" name="login" id="login">
</fieldset>
<fieldset class="float_right">
<label for="password">Password</label>
<input type="password" name="password" id="password">
</fieldset>
<span class="forgot_login float_left">Forgot your login information?</span>
<input type="submit" value="LOG IN" class="form_button float_right">
</form>
I seen people wrap them in divs, lists, etc. I want to follow the best practice. Should I also wrap every label and input elements with a fieldset even if I don't plan on styling it? Ex:
<form>
<fieldset>
<label for="name">Full Name:</label>
<input type="text" name="name" id="name" placeholder="First Name" class="float_left">
</fieldset>
<fieldset>
<label for="email">Email:</label>
<input type="email" name="email" id="email" placeholder="Ex: johndoe#gmail.com" class="full_input">
</fieldset>
<fieldset>
<textarea rows="3" name="message" id="message" placeholder="1000 Character or less" class="full_input"></textarea>
</fieldset>
<input type="submit" value="SEND" class="form_button float_right">
</form>
Thanks.
The primary, original purpose of a fieldset is to convey a contextual association between multiple input fields to non-visual agents. It is expected that a screen reader is going to read the legend text, then the first field, then the legend, then the next field... As in: "Address: Street 1... Address: Street 2... Address: City..."
For sighted people, a fieldset does visually imply a container-type relationship of the same kind: those fields are related by context, but only when there are multiple fields.
So it never makes semantic sense to have a single label/field (a label is not a field, in that it does not accept input) in a fieldset. It's just annoying to people using screen readers (because it behaves like a redundant label). To sighted people it destroys the implication of relationship if you use it for single fields and also multiple fields, and takes up a lot more space.
In short, use it sparingly, semantically, and correctly - not as a styling device.
For a 'neutral' container, use a div or a span, because they carry no semantic information. List structures, paragraphs, all other elements have semantics and you need to be careful about how you use them.
People will tell you crazy things about the semantics of HTML elements. Don't take anyone at their word, including me. Go read the spec and know it for yourself.
Using fieldset for a combination of a label and a control is illogical, though formally valid: a fieldset is supposed to be a set of fields.
Other than that, the question is largely a matter of opinion and debate. HTML5 more or less favors p for such a pair, but that causes an empty line by default, so div is a more reasonable choice. There are also good reasons to use a table element, with one row for each label/control pair.
Unless you plan to use a fieldset legend then I wouldn't bother using fieldsets. Bootstrap forms is a nice way to get started too http://getbootstrap.com/css/#forms there is no best way though.
You often see people using a wrapper div because it helps with creating a neater row i.e. apply padding to a wrapper instead of to all elements within it or floating all elements within a parent and applying a clear-fix element at the bottom to wrap correctly.. or just float the parent as well.

Right and correct markup in html forms

Once upon a time in HTML
I was looking W3Fools and find this paragraph, related to the errors in W3Schools:
<form>
First name: <input type="text" name="firstname" /><br />
Last name: <input type="text" name="lastname" />
</form>
This code is wrong. Non-block-level elements (such as <input>) are
not valid directly inside <form> tags until HTML5.
Well, since I always format that way I said to myself "WAIT, I was wrong all this time". And go to validate it to check if it's true. Efectively, this code don't pass the validation.
Then, searching for the correct markup, I found several examples from more reliable sources, but none of the following examples passes the validator.
The bad, the good and the ugly
1. W3Schools
<form>
First name: <input type="text" name="firstname"><br>
Last name: <input type="text" name="lastname">
</form>
2. Mozilla Network Developer
In "Examples" section, I have found this:
A common use-case senario
<!-- A common form that includes input tags -->
<form action="getform.php" method="get">
First name: <input type="text" name="first_name" /><br />
Last name: <input type="text" name="last_name" /><br />
E-mail: <input type="email" name="user_email" /><br />
<input type="submit" value="Submit" />
</form>
3. W3C Wiki
<form action="http://www.google.com/search" method="get">
<label>Google: <input type="search" name="q"></label>
<input type="submit" value="Search...">
</form>
A Fistful of Codes
More details:
I'm trying to validate the code as HTML fragment, both in HTML 4.01 and XHTML 1.0.
The recurring error I have found is:
document type does not allow element "input" here; missing one of "p",
"h1", "h2", "h3", "h4", "h5", "h6", "div", "pre", "address",
"fieldset", "ins", "del" start-tag
The question
What is the correct and valid markup I should use to make a form?
Thanks in advance.
Edit:
A similar question was answered redirecting the OP to the form section of HTML4 specification. They provided this code:
<FORM action="http://somesite.com/prog/adduser" method="post">
<P>
<!--...stuff...-->
<INPUT type="submit" value="Send"> <INPUT type="reset">
</P>
</FORM>
First, it isn't the same code of their wiki. But nevermind, from I know, the wiki it isn't 100% accurate.... BUT:
They fix the validation error by enclose all tag in a <p>. But forms are not paragraphs, it isn't? This code pass validation, but I think that's not very semantic...
Expert answers you giving to me (thanks!), for the most part, are to enclose the inner tags in a <fieldset>, but if I only need one fieldset (for example, a form with only one field or self-related fields), is this correct? Might that not be superflous code (because the fieldset tags are supposed to enclose similar fields)?
A fieldset is a block level element that is commonly used in forms. Therefore you could use a fieldset or another block level element like a div.
<form action="http://www.google.com/search" method="get">
<fieldset><legend>My form</legend>
<label>Google: <input type="text" name="q"></label>
<input type="submit" value="Search...">
</fieldset>
</form>
or
<form action="http://www.google.com/search" method="get">
<div>
<label>Google: <input type="text" name="q"></label>
<input type="submit" value="Search...">
</div>
</form>
This probably rarely gets flagged as non valid markup because people tend to a lot of divs to help style forms nicely.
I tend to agree with a few of the others in that FieldSet is the best way to group form items together, especially as it really helps with things like screen readers.
I tend to use the following:
<form action="http://www.google.com/search" method="get">
<fieldset>
<legend style="display: none;"></legend>
<label for="q">Google:</label>
<input type="text" name="q">
<input type="submit" value="Search...">
</fieldset>
</form>
I normally don't include the legend, but if it is required for validation, it doesn't necessarily have to be visible ;)
This code is wrong. Non-block-level elements (such as <input>) are not valid directly inside <form> tags until HTML5.
That's not entirely true. They are valid in Transitional DTDs but not Strict DTDs.
What is the correct and valid markup I should use to make a form?
It depends on the form.
For the examples given, the W3C version is the best. Having a block container in a form doesn't matter (unless it adds useful semantics, or sensible grouping of separate groups of controls). <label> elements are excellent.
I tend to group fields and labels inside the <fieldset> tag, which also sounds very semantical to me.

What are the advantages of using the fieldset tag?

What are the advantages of using the <fieldset> tag?
I don't really get what it is used for.
Forms are often broken up into various sets of fields.
The fieldset tag allows you to logically group sets of fields in order that your forms be more descriptive.
You'll also note that you can use the fieldset to style your forms and display those logical associations between fields.
Just like forms you find in the "real" world.
The "advantages" of using a fieldset are that they allow you to mark up your data (in this case a form) in the most semantic way available. Consider that placing your fields in a fieldset is more descriptive than placing your fields in a div. The div tells you nothing about the relationship between the fields, a fieldset tells you there is a relationship.
It's a similar principle to many of the new HTML5 tagsets. <footer> for example tells you more about the meaning of the data inside it compared to an ambiguous <div>.
If you take a look at the HTML5 spec for Developers:
http://developers.whatwg.org/forms.html#the-fieldset-element
The fieldset element represents a set
of form controls optionally grouped
under a common name.
(there's a lot more information if you follow the link)
Combined with the legend element, it allows you to easily do this, which is difficult to recreate without using fieldset/legend:
It allows you to group a set of related fields and give them a legend.
<fieldset>
<legend>Gender</legend>
<input type="radio" name="gender" id="male" value="male">
<label for="male">Male</label>
<input type="radio" name="gender" id="female" value="female">
<label for="female">Female</label>
<fieldset>
<fieldset>
<legend>Address</legend>
<label for="line1">Line 1</label>
<input name="address1" id="line1">
<label for="line2">Line 2</label>
<input name="address2" id="line2">
<label for="town">Town</label>
<input name="town" id="town">
<label for="country">country/label>
<input name="country" id="country">
</fieldset>
You group stuff together with it. Which is useful if you need to access things in it for CSS or JavaScript, and don't want to go through the hassle of assigning ID's to everything.
Also, the legend looks pretty good.