Why is my code failing Google Accessibility review? - html

Basically, I've got an input & an associated label, both with the same ID. However, Google Accessibility Review is failing it, with the following response:
Form elements do not have associated labels
To me, because the id is the same and the label is pointing towards the input, then I can't see what's failing here?
Am I missing something blindingly obvious!?
<div class="field additional">
<label class="label" for="street_2">
<span>Address</span>
</label>
<div class="control">
<input type="text" name="street[]" value="" title="Street Address 2" id="street_2" class="input-text " autocomplete="off" aria-required="true">
</div>
</div>

Many things may explain this :
you may have another label linking to the same element conflicting for the same form element,
elements with the same id may appear elsewhere in the same HTML document,
this message may concern another form element,
the label itself might not be visible
The fact that your input name is an array (name="street[]") let me think that we have not all the elements to conclude on one of those choices.

Related

How do I disable or prevent input text suggestions for form fields in Edge?

How do I prevent a form from suggesting auto-complete values, from previous entries or from saved information in Edge?
In the above image, the email input field is marked as autocomplete="false", but still in the right pane you can see the suggestion is populating.
When I add autocomplete=disabled to one field it seems it work, but when I add the attribute to all the inputs, it again starts displaying suggestions for every field.
What is the solution for this?
Add the aria-autocomplete="list" attribute to the input.
<input type="text" id="FirstName" name="attr1" aria-autocomplete="list">
Do not use any other value for the attribute.
According to your description, I reproduced the problem. I think your issue is caused by the "Save and fill personal info" setting being enabled in Edge.
If you navigate to edge://settings/personalinfo and disable this feature, you can see this behavior no longer exists.
Or you can also click the "Manage personal info" option in the picture you provided, and then disable it.
I did some simple tests and found that if you need to solve the problem from the code, you need to modify the name attribute of the form's related field.
Like this(do not use attribute values like name or email... and maybe there are others I am not aware of):
<label for="attr1">attr1:</label>
<input type="text" id="FirstName" name="attr1">
<label for="attr2">attr2 :</label>
<input type="text" id="LastName" name="attr2">
<label for="attr3">attr3 :</label>
<input type="email" id="Email" name="attr3" autocomplete="off">
<input type="submit">
I don't recommend this, because good naming helps you understand and maintain the code. Using proper attributes like name and email also helps your code be more accessible for screen readers or other assistive technology.

Is there a Standardized method of Form Accessibility and Semantics?

With so many articles on the "proper," "semantic," and "accessible" use of forms and architecture, I'm rethinking how I approach forms. There are literally so many variations of what is "right" that I'm not 100% on what is really accurate anymore.
In an MDN article (here), it mentions:
With this example, a screen reader will pronounce "Fruit juice size small" for the first widget, "Fruit juice size medium" for the second, and "Fruit juice size large" for the third.
<form>
<fieldset>
<legend>Fruit juice size</legend>
<p>
<input type="radio" name="size" id="size_1" value="small" />
<label for="size_1">Small</label>
</p>
<p>
<input type="radio" name="size" id="size_2" value="medium" />
<label for="size_2">Medium</label>
</p>
<p>
<input type="radio" name="size" id="size_3" value="large" />
<label for="size_3">Large</label>
</p>
</fieldset>
</form>
Now, I can see the benefit of this for something like the example above, however, say I made a multi-step shopping cart, I wouldn't want assistive technology to speak "Checkout: cc-number," "Checkout: cc-date" using "checkout" prior to every label. Especially in cases where steps are labelled. This would be repetitive and sometimes confusing I would assume... But I've always grouped sections of a form within a <fieldset>. Now I'm rethinking using fieldset and legend at all, but does it now go against semantics? What's the trade-off? Is there a balance?
Additionally, and I'll use the same MDN article so I'm not sending you all over the web,
Note that even without considering assistive technologies, having a
formal label set for a given widget lets users to click on the label
to activate the corresponding widget in all browsers. This is
especially useful for radio buttons and checkboxes.
Some assistive technologies can have trouble handling multiple labels
for a single widget. Because of this, you should nest a widget inside
its corresponding element to build an accessible form.
<form>
<p>
<input type="checkbox" id="taste_1" name="taste_cherry" value="1">
<label for="taste_1">I like cherry</label>
</p>
<p>
<label for="taste_2">
<input type="checkbox" id="taste_2" name="taste_banana" value="1">
I like banana
</label>
</p>
</form>
Now, in this instance, the labeling for both these items are reasonably common, I have used both methods, but is there a balance between accessibility and semantics here? I tend to put the label not wrapping the input for consistency in code and I know their is strong debate on this subject (mainly the ability to drop the for and not need the id and/or having labels in different areas of the markup). So, I'm not trying to rehash the debate here, I tend to use the for and id regardless if I wrap elements in a label or not. But if there is an accessibility concern for one then why isn't the latter the golden standard?
Yet another point, WAI-Aria rules now contribute, so how much do these rules really impact the accessibility and semantics of a form?
<p>Required fields are followed by <strong><abbr title="required">*</abbr></strong>.</p>
<form>
<fieldset>
<legend>Fruit juice size*</legend>
<p>
<label for="size_1">
<input type="radio" name="size" id="size_1" value="small" aria-labelledby="size_1_label" />
<span id="size_1_label" required aria-required="true">Small</span>
</label>
</p>
<p>
<label for="size_2">
<input type="radio" name="size" id="size_2" value="medium" aria-labelledby="size_2_label" />
<span id="size_2_label">Medium</span>
</label>
</p>
<p>
<label for="size_3">
<input type="radio" name="size" id="size_3" value="large" aria-labelledby="size_3_label" />
<span id="size_3_label">Large</span>
</label>
</p>
</fieldset>
</form>
I'm really just curious whether or not there is a standardized method of approach when dealing with Semantic and Accessible markup. So far it seems people just do whatever they feel is right and then vocalize their thoughts all over the internet.
I've read through W3C's drafts and recommendations but even they use varying examples. Does anyone have evidence of what approach really improves accessibility and semantics in relation to forms? Are their any particular websites that have the time an resources to test this and draw an accurate conclusion that I'd be able to review?
The answer to your question really is "it depends".
All of the accessible markup you list above is valid. So if you are simply looking for accessible markup, you can use any of the examples. The rest of the decisions really come down to
error handling, and
additional instructions
Error Handling
When errors appear in your form, they need to be programmatically associated with the form fields that they reference. There are two ways to do this while maintaining the label itself:
Add the error to the label
You can add the error text to the label itself. Having a wrapped label gives you more flexibility over the order that this error text occurs in the DOM. you can place the error before the label, after the label, after the input or before the input. For this reason, you might choose to use the wrapping technique instead of the non-wrapping technique:
<label>My Input
<input type="text" aria-invalid="true" id="myinput" name="myinput"/>
<span class="error">The input field must be a valid username</span>
</label>
Associate the error using ARIA
The second technique is to associate the error using ARIA. This is very flexible because it allows multiple elements to form the label of the input and can also be used for additional instructions.
<label id="mylabel">My Input</label>
<input type="text" aria-invalid="true" aria-labelledby="mylabel myerror"/>
<span id="myerror" class="error">The input field must be a valid username</span>
Now if your input is a checkbox or radio button, you will want to maintain the for and id association so that the user can click (or touch) the label in order to activate the checkbox/radio.
Additional Instructions
As mentioned above, using ARIA labelling techniques, you can associate multiple elements with a single input field. This is useful for providing additional instructions and hints. aria-labelledby is used for the accessible name (label) whereas aria-describedby can be used for a hint and can also reference multiple elements by using multiple ids.
<label id="mylabel">My Input</label>
<input type="text" aria-invalid="true" aria-labelledby="mylabel myerror" aria-describedby="unameinstructions"/>
<span id="myerror" class="error">The input field must be a valid username</span>
<span id="unameinstructions">A valid user name must contain at least one alpha, one numeric character and must be at least 8 characters</span>
Here is a presentation I created on accessible dynamic forms http://www.slideshare.net/dylanbarrell/accessible-dynamic-forms-27169766 it references some example code that can be found here https://github.com/dylanb/a11yvalid and the running example of good best practices (except perhaps the CSS styling choices) can be found here http://dylanb.github.io/bower_components/a11yfy/examples/form-validation.html

Angular/bootstrap show specific form validation message

I'd like to have a required email input on a form, and I'd like to augment the input's label to show validity with specific messages. I tried the markup below (simplified, and a few variants). The actual can be found at this fiddle illustrating the problem.
<label for="email">Email
<small class="help-inline" ng-show="form.email.$invalid-required"> (required)</small>
<small class="help-inline" ng-show="form.email.$invalid-email"> (email)</small>
</label>
<div class="input-group">
<input type="email" placeholder="Email" name="email"
ng-model="model.email" required>
I'd like the 'required' message to appear when the input is empty, and when it's non-empty, I'd like the 'email' message to appear conditionally if angular email validation passes.
As you'll see in the fiddle, both messages appear and disappear together, even though, as I use the chrome inspector, the $invalid classes on the input seem to change appropriately. This casts suspicion on the ng-show expression for the errors, but no matter what I try there I get the same behavior.
I've seen a couple answers (like this one) that use a lot of code, but that answer seems a little roundabout. I'm new to web, and already appalled by how bulky the html/code can get (each time I learn about a new streamlining idea, mine seems to double in size)
Thanks in advance.
Change the expression for required to
<label for="email">Email <small class="help-inline" ng-show="!form.email.$viewValue">
and it would work.
The problem with Angular is that it does not allow invalid data in the model. So unless you provide a valid email value the linked model property remains empty and both the required and email validation fail.

Invalid form control (type=url) is not focusable when hidden in Chrome

I'm encountering a problem in Chrome where form submission results in the following error:
An invalid form control with name='ctl00$cphMain$ctl01$groupControl$website' is not focusable.
This is an <input type="url" ...> rendered in Chrome inside a <div> that has display:none set (until the neighbouring checkbox is checked). There is no required attribute, nor is there a maxlength attribute set, so I'm unsure as to why the submission fails. Here is the relevant section of markup (the control in question is inside the 2nd <fieldset>):
<label class="checkbox">
<input id="ctl00_cphMain_ctl01_groupControl_ctl13" type="checkbox" name="ctl00$cphMain$ctl01$groupControl$ctl13" onclick="$(this).parent().siblings('div.expandableContainer').slideToggle();"/>
Include contact...
</label>
<div class="expandableContainer form-expanded js-initial-hide " style="display: none;">
<fieldset>
<label>
Name:
<span class="req">*</span>
</label>
<input name="ctl00$cphMain$ctl01$groupControl$name" type="text" maxlength="100" id="ctl00_cphMain_ctl01_groupControl_name"/>
</fieldset>
<fieldset>
<label>
Website:
<span class="req">*</span>
</label>
<input name="ctl00$cphMain$ctl01$groupControl$website" type="url" id="ctl00_cphMain_ctl01_groupControl_website" value="http://" onblur="if (this.value == 'http://') this.style.color = '#666';" onfocus="this.style.color = '#000';" style="color:#666;"/>
</fieldset>
<fieldset>
<label>
Email:
<span class="req">*</span>
</label>
<input name="ctl00$cphMain$ctl01$groupControl$email" type="email" maxlength="100" id="ctl00_cphMain_ctl01_groupControl_email"/>
</fieldset>
</div>
According to W3.org (http://www.w3.org/TR/html401/interact/forms.html#successful-controls), this is supposedly a 'successful' control. Even adding a MaxLength of 2000 (the DB field width) doesn't work. No errors are received for the surrounding controls.
Is there any idea why this form submission is failing? Checking the box (to cause the surrounding <div> to be displayed (with display:block) allows the form to be submitted without any problems.
Many thanks.
Well I discovered the problem: The invisible URL fields (<input type="url" ... />) had a non-empty value set (basically part of a legacy JavaScript solution to implement placeholder text). For some reason, this value in an invisible field trips up Chrome (possibly from their built-in validation, that other people discussing similar issues have alluded to). Perhaps Chrome misses the lack of visibility specified in the ancestor <div>.
How I fixed this:
Removed the onblur, onfocus and style attributes as they are redundant;
Changed the value attribute to the new HTML5 placeholder attribute, keeping the same attribute value.
The only drawback is that site visitors must manually enter the "http://" in the field rather than append to it; our project team will discuss strategies to improve the UX of this.

Two input fields inside one label

Consider the following:
<label>Range from
<input name='min_value'/> to
<input name='max_value' />
</label>
Is this semantically correct since the W3C recommendations state that a label is associated with exactly one form control?
Clicking into the second input shifts focus immediately to the first input? Can this be prevented?
How would one markup a min/max input combination to show that two inputs belong together?
No, it's not correct (since, as you note, a label is associated with exactly one form input).
To label a group of inputs that belong together, use a <fieldset> and a <legend>:
<fieldset>
<legend>Range</legend>
<label for="min">Min</label>
<input id="min" name="min" />
<label for="max">Max</label>
<input id="max" name="max" />
</fieldset>
References:
<input />HTML 5 spec.
<fieldset>HTML 5 spec.
<label>HTML 5 spec.
<legend>HTML 5 spec.
As the accepted answer states, that's not correct, however I think there are better ways to do it.
Accessible alternatives:
Option 1 (using the aria-label attribute):
Range:
<input ... aria-label='Range start' />
<input ... aria-label='Range end' />
Option 2 (using hidden label tags):
<label for='start'>Range start</label>
<input type='text' id='start' />
<label for='end' class='hidden'>Range end</label>
<input type='text' id='end' />
Where the .hidden class is only readable by screen readers.
Option 3 (using aria-labelledby attributes):
<label id='lblRange'>Range</label>
<input type='text' id='start' aria-labelledby='lblRange' />
<input type='text' id='end' aria-labelledby='lblRange' />
Advantages of option #1: Each input has a good description that other suggestions (such adding a "to" label) do not. Options #2 and #3 might not be the best for this specific case, but worth mentioning for similar cases.
Source: http://webaim.org/techniques/forms/advanced
I see many answers saying it is wrong to put 2 inputs inside a label.
This is actually a wrong statement in html5. The standard explicitly allow it:
http://www.w3.org/TR/html5/forms.html#the-label-element
If the for attribute is not specified, but the label element has a labelable element descendant, then the first such descendant in tree order is the label element’s labeled control.
If a label element has interactive content other than its labeled control, the activation behavior of the label element for events targeted at those interactive content descendants and any descendants of those must be to do nothing.
However, Safari does not respect the html5 standard here (tested on iOS 11.3). So, someone that wants to be compatible with Safari must use workarounds here or wait until Apple fixes its browser.
According to this - label can contain only one input as it should be associated with only one control. Putting input inside the label means elimination of for attribute (automatic linking).
So you should either put single input into label or specify for attribute which points to input id and don't put input into label.
How about this:
<label> Range from <input name='min_value'> </label>
<label> to <input name='max_value'> </label>
1 LABEL = 1 INPUT !!!
If you put 2 INPUTS inside a LABEL, it will NOT work in Safari (and iPad and iPhone)... because when you click inside LABEL it automatically focuses the first INPUT... so the second input is impossible to type to.
I see many answers saying it is wrong to put 2 inputs inside a label. This is actually a wrong statement in html5. The standard explicitly allow it: http://www.w3.org/TR/html5/forms.html#the-label-element
<label id='dobRange'>DOB between</label>
<input type='text' id='start' aria-labelledby='dobRange' />
<input type='text' id='end' aria-labelledby='dobRange' />
in haml:
= f.label :dob_range
= f.search_field :dob_gteq, 'aria-label': 'dob_range'
= f.search_field :dob_lteq, 'aria-label': 'dob_range'
i don't think you should be putting the input field inside the label control.
<label for="myfield">test</label><input type="text" id="myfield" name="myfield />
the label is just that, a label for something.