Is legend in header valid ? <h1><legend> Caption </legend></h1> - html

I would like to know if I could insert a legend inside a header. This way the legend can have also its hierarchy related to the whole document.
I have more text below which is relevant but needs to be highlighted for the readers. In this case personal information would be legend and h2 at the same time. h1 would be another element in the site which I chose not to display.
<fieldset>
<h2>
<legend>Personal information</legend>
</h2>
<h3>
Credentials
</h3>
<label for="username">
Username
</label>
<input id="username" type="text">
<label for="surname">
Surname
</label>
<input id="surname" type="text">
<h3>
Contact details
</h3>
<label for="street">
Street
</label>
<input id="street" type="text">
<label for="house-number">
House number
</label>
<input id="house-number" type="number">
</fieldset>

As stated in https://developer.mozilla.org/it/docs/Web/HTML/Element/legend
Permitted parent elements: A <fieldset> whose first child is this <legend> element
In your example the <legend> element is not the first child of its ancestor <fieldset>, so it is not valid HTML5 markup.
Furthermore note that also reverting the order of the elements like so
<legend><h2>Personal information</h2></legend>
the markup would not be still valid, since <legend> allows phrasing content only

Element legend is not allowed as child of element h1.
Only as a child of a fieldset.
Quote from W3C validator -
Contexts in which element legend may be used:
As the first child of a fieldset element.

Related

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

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.

What is the appropriate semantic markup for form label help sub-text

Some form elements in a form may require text to explain the function of said element. I'm thinking of encapsulating this text in a paragraph element, as follows,
label p {
margin-top: -1px;
font-size: smaller;
}
<div class="form-group">
<label for="form-input-1">Label Text
<p>Label explainer/help text</p>
</label>
<input id="form-input-1" />
</div>
My question is: is the <p> element the most semantic element for this use? In my opinion, the label sub-text is a type of sub-title and one could argue that it may call for a <h*> element. But, these are often used for outlines, and I don't believe this would be super semantic here. Would a <span>, make sense here, as these may be used to mark off parts of inline flow elements?
Please, share your thoughts!
<label> elements can only contain phrasing content, which means they can't contain headings or paragraph elements, which are flow content.
Additionally, the MDN Docs note that headings should not be used within labels because that "interferes with many kinds of assistive technologies".
If additional form field instructions are needed beyond what would reasonably fit within a label, you should use a separate element, outside of the label—and tie it to the input using the aria-describedby attribute, as outlined on the W3C's Web Accessibility Tutorial on Form Instructions.
Here's an example of that approach:
form {
display: grid;
grid-gap: 0.5rem;
padding: 0.5rem;
}
<form>
<label for="input">Label Text</label>
<span id="instructions">Additional instructions lorem ipsum</span>
<input id="input" aria-describedby="instructions" type="text">
</form>
In complex forms there are mulitple sections, headings, hints, helper texts an so on used as explanation. So there are multiple ways to add descriptions and helper texts to a form:
<span> is the simplest form. Add it to the label-element.
<fieldset> with <legend> wraps fields together and adds a descripition.
<section> can give additional structure and information to a form.
<p> can be used to add addtional information i.e. to the whole form or a form-section
<div> is used by Google in Maerial Design for a text field helper line
Often done but NOT to be used for farer explanation should be texts in placeholders.
In your example I believe a span within the labelshould be a good solution which will match the semantic.
ADDITOINAL INFORMATION
Complex HTML code example from MDN:
<form method="post">
<h1>Payment form</h1>
<p>Required fields are followed by <strong><abbr title="required">*</abbr></strong>.</p>
<section>
<h2>Contact information</h2>
<fieldset>
<legend>Title</legend>
<ul>
<li>
<label for="title_1">
<input type="radio" id="title_1" name="title" value="A">
Ace
</label>
</li>
<li>
<label for="title_2">
<input type="radio" id="title_2" name="title" value="K" >
King
</label>
</li>
<li>
<label for="title_3">
<input type="radio" id="title_3" name="title" value="Q">
Queen
</label>
</li>
</ul>
</fieldset>
<p>
<label for="name">
<span>Name: </span>
<strong><abbr title="required">*</abbr></strong>
</label>
<input type="text" id="name" name="username">
</p>
<p>
<label for="mail">
<span>E-mail: </span>
<strong><abbr title="required">*</abbr></strong>
</label>
<input type="email" id="mail" name="usermail">
</p>
<p>
<label for="pwd">
<span>Password: </span>
<strong><abbr title="required">*</abbr></strong>
</label>
<input type="password" id="pwd" name="password">
</p>
</section>
<section>
<h2>Payment information</h2>
<p>
<label for="card">
<span>Card type:</span>
</label>
<select id="card" name="usercard">
<option value="visa">Visa</option>
<option value="mc">Mastercard</option>
<option value="amex">American Express</option>
</select>
</p>
<p>
<label for="number">
<span>Card number:</span>
<strong><abbr title="required">*</abbr></strong>
</label>
<input type="tel" id="number" name="cardnumber">
</p>
<p>
<label for="date">
<span>Expiration date:</span>
<strong><abbr title="required">*</abbr></strong>
<em>formatted as mm/dd/yyyy</em>
</label>
<input type="date" id="date" name="expiration">
</p>
</section>
<section>
<p> <button type="submit">Validate the payment</button> </p>
</section>
</form>
Link to see MDN form live:
https://mdn.github.io/learning-area/html/forms/html-form-structure/payment-form.html
Link to wider MDN explanations:
https://developer.mozilla.org/en-US/docs/Learn/Forms/How_to_structure_a_web_form#common_html_structures_used_with_forms*
Link to example Google Material Design:
https://material.io/develop/web/components/input-controls/text-field/helper-text
There doesn't seem to be any definitive answer or resource so you can only get opinions. Here's mine:
I'd start by thinking about how to markup the whole form. I think the semantic form style described in MDN article is a pretty good place to start. Especially the part that a form is logically a list of form controls so you should have <ul> and <li> elements wrapping the controls in semantic order. However, I think it has one problematic part where it uses logically markup like
<label><input>text</label>
for radio buttons, but
<label>text<input></label>
for text inputs. I'd highly prefer that the markup order doesn't change depending on the input type (checkbox/radio button vs text/email/password). To do that in practice, you probably want to always use markup like
<li class="checkbox">
<label for=id1>text</label>
<input id=id1>
</li>
which you can then style by using e.g. li.checkbox { display: flex; ... } and reorder the label and input visually as needed. Obviously the class is needed only for styling but it is not needed for semantics. If browsers ever implement :has() then there would be no need for a class at all.
As for the help text for the input, in theory, you would want to use
<li class="checkbox">
<label for=id1>text</label>
<input id=id1>
<label for=id1 class=help>help content here</label>
</li>
because by spec it should be possible to attach multiple labels to a single input. However, as far as I know, this doesn't work in practice with the software that's commonly used by blind people needing accessibility aids.
As such, the next question is how do you think this help text should be used by all the following groups?
Users with vision without JavaScript support. (Note that this group includes most search engines.)
Blind persons without JavaScript support.
Users with vision with JavaScript support. (Note that this group includes some search engines.)
As far as I know, there's no good answer to cater for all the 3 groups perfectly. Note that for practical support for a yet another group "Blind persons with JavaScript support" you can use any markup you want and use ARIA attributes to make it accessible. Overall, the best I can think of is as follows:
<li class="checkbox">
<label for=id1>text</label>
<input id=id1 aria-describedby=id2>
<aside id=id2>help content here</aside>
</li>
That should be good enough to attach the help content to the input for accessibility tools, the help content is semantically additional content so <aside> should be okay for both blind and visual users and you can use CSS only to make the <aside> visible only when the input is focused. Also note that <aside> allows any content for help, incuding videos in iframes, not just text. Of course, if you need user to click within the <aside> element you cannot use input:focus to toggle the element visible but you need to use some kind of JavaScript support. Exact details depend on which group you want to cater for most and if you want to have the help text available to all groups.
This markup also contains all the information you need to wrangle it as needed by JavaScript. For some non-JavaScript styling options you might want to wrap the label and input in some wrapper element so that you can position those as a group separate from <aside> element. In that case markup like
<li class="checkbox">
<div>
<label for=id1>text</label>
<input id=id1 aria-describedby=id2>
</div>
<aside id=id2>help content here</aside>
</li>
could be a good option. You can target that classless <div> element by selector form li.checkbox>div if needed. One could then use e.g. display:grid or subgrid for the li.checkbox and e.g. display:flex for the li.checkbox>div to position everything nicely. However, if you do that, you cannot nicely toggle the visibility of the help text simply by using style like input:not(:focus) + aside { display: none; }. I think you can survive without the wrapper <div> element if you use display:grid for li.checkbox because that allows positioning stuff in 2D unlike flex.
And if you need to support users with vision but without support for CSS, then I don't have a good solution. Using the above mentioned semantic list markup results in bullet points in addition to form inputs which could look pretty messy for non-CSS users.

do I need WAI-ARIA attribute aria-labelledby on nested input element?

Is the attribute aria-labelledby needed on an <input> element that is nested inside a <label> element that serves as a label for <input>? Like below:
<label>This is an input field:
<input type="text" />
</label>
or do I need something like:
<label id="mylabel">This is an input field:
<input type="text" aria-labelledby="mylabel" />
</label>
I know that the for attribute is not needed on <label> if the target of for is nested, does the same principle apply to the ARIA attributes?
When <input> tag is present inside the <label> tag, you don't need to use aria-labelledby attribute.
But, if you are writing like this :
<div> Enter some text here:
<input type="text"/>
</div>
Then, you need to use aria-labelledby on <input> tag like this:
<div id="txt"> Enter some text here:
<input type="text" aria-labelledby="txt">
</div>

Why use <legend> in HTML?

What's the point in using <legend>>?
It looks to be the same as a <p> tag, although it cannot be nested inside a div?
Is there a reason to use it?
A legend describes the content of a fieldset.
<fieldset>
<legend>What pets do you like?</legend>
<label> <input type="checkbox" name="pet" value="cats"> Cats </label><br>
<label> <input type="checkbox" name="pet" value="dogs"> Dogs </label><br>
<label> <input type="checkbox" name="pet" value="etc"> Etc </label>
</fieldset>
It has the semantic association with the form controls in that fieldset.
This allows, for example, screen readers to announce the question with each of the possible answers to provide context to what the answers are for.

Does the position of legend tag within fieldset matter?

I have a fieldset as below:
<fieldset>
<legend>Colour</legend>
<label><input type="radio" name="colour" value="blue"> Blue </label>
<label><input type="radio" name="colour" value="red"> Red </label>
</fieldset>
Here if I keep the legend tag below all the label tags, the HTML renders the fieldset exactly same as before.
<fieldset>
<label><input type="radio" name="colour" value="blue"> Blue </label>
<label><input type="radio" name="colour" value="red"> Red </label>
<legend>Colour</legend>
</fieldset>
Even this renders the same.
So question here is, whether it is programmatically correct and as per standards to write legend tag at any place within fieldset.
So question here is, whether it is programmatically correct and as per standards to write legend tag at any place within fieldset.
No, it is not. The legend element (if present) must be the first child of a fieldset element.
This is what the HTML5 spec. says:
4.10.15 The fieldset element
[...]
Content model:
Optionally a legend element, followed by flow content.
The HTML4.01 spec. defines the fieldset element as follows:
<!ELEMENT FIELDSET - - (#PCDATA,LEGEND,(%flow;)*) -- form control group -->
where the comma-separated list defines the order in which the child elements must appear, i.e. LEGEND has to appear before other flow (block or inline) elements.