Problem/Motivation

Login form does not comply W3C :
"Attribute autocorrect not allowed on element input at this point."
"Attribute autocapitalize not allowed on element input at this point."
Both point introduced by :
#1955282: Disable Autocapitalize and Autocorrect on user login forms
"The aria-describedby attribute must point to an element in the same document." for both login and password.
This comes from the aria-describedby pointing to none existing element.

Proposed resolution

- Add the autocapitalize and autocorrect through javascript ?
- Either add a description or remove the aria-describedby

Remaining tasks

Problems and solutions are summed up in comment #13.
- For problem A :
-- choose between solution A1 or A2 (or define new one)
-- review patch #2 (if solution A2), or create new patch and review
- For problem B:
-- choose between solution B1 and B2
-- review patch #11 (if solution B1), or create new patch and review

To help with the review, see #13 for the markup with and without the patch.

User interface changes

None.

API changes

None.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Dom.’s picture

Dom.’s picture

Status: Active » Needs review
FileSize
911 bytes

This patch fixes the aria-describeby issue.
Regarding the autocorrect / autocapitalize option, I don't see anything but adding it though javascript which seems bad idea here considering they are required for mobile...

Dom.’s picture

Issue tags: +W3C validation, +w3c, +frontend, +Novice
LewisNyman’s picture

hmm, do we have to unset it if we can just remove the code that sets it to begin with? This needs accessibility sign off

Dom.’s picture

I don't understand what means "accessiblity sign off". But the point I found is that this aria is added in form.inc :

if (!empty($element['#description'])) {
    $description_id = $element['#attributes']['id'] . '--description';
    $description_attributes['id'] = $description_id;
    $variables['description']['attributes'] = new Attribute($description_attributes);
    $variables['description']['content'] = $element['#description'];

    // Add the description's id to the fieldset aria attributes.
    $variables['attributes']['aria-describedby'] = $description_id;
}

But this is made before UserLoginBlock.php unsets the #description in the rendering process, that is why aria-describedby is there at that time.

LewisNyman’s picture

We need some one on the accessibility team to review this patch and give it a thumbs up. I've tagged it so someone should see it.

Dom.’s picture

OK, sure ! Sorry for I did not understood your comment ! (my english isn't that good!)

LewisNyman’s picture

No problem! Thanks for the work

Cliff’s picture

Dom., I'm one of the organizers of the Accessibility Group and can at least give you an initial review.

I haven't been actively participating for a while, and I'm not a scripter, so I would need to see the HTML produced with and without this patch.

aria-describedby is one way to add a label to a form field or other element. Labeling a form field seems to be the point of using it here.

It sounds like the issue is that the id that this aria-describedby points to is either not being created, not being set, or being cleared after it is set. Whatever is going on, the correct fix is more likely to be to ensure that id element is created, given a value, and kept intact in the code produced for this login form. Removing the aria-describedby because its target is not found is probably not what we want to do.

What we probably need to do is:

  1. Replace aria-describedby, which is meant to point to a description (usually a sentence or two) of the feature, with aria-labelledby, which is meant to point to a simple label.
  2. Confirm that somewhere on the page containing the form is an element with an id attribute that matches the contents of this aria-labelledby.

For example, this code, borrowed from an example for another aria property, aria-posinset, in the specification for ARIA 1.0, is the pattern we are expecting to see:

   <h2 id="label_fruit"> Available Fruit </h2>
<ul role="listbox" aria-labelledby="label_fruit">
[etc.]

The element with the matching id might be immediately adjacent to the element being labeled, but it could also be anywhere else in the code. We just need for the connection to be explicitly stated with an id attribute on one element that matches the aria-labelledby attribute on another.

By the way, you're right to focus on the aria-describedby, because having autocapitalize, autocorrect, or both active in a login field is completely inconsistent with WCAG 2.0. With respect to forms, WCAG calls for this approach:

  • As much as possible, help the user avoid making a mistake. For example, when all possible answers are known, don't make the user type them in. Give them a selection box instead.
  • When it isn't possible to help the user avoid mistakes, help them recognize and correct any mistakes they do make. Helping a user to correct a mistake might mean reminding them that an email address must have an "@" followed by a domain name.
  • But don't change their entries—let them decide whether they need to be changed. In other words, if they type "suger," instead of changing it to a correctly spelled word automatically, highlight it and give them choices that might be right. Did they mean "sugar"? "super"? "surge"?
  • And don't be so helpful that you make it easier for spambots and miscreants to get into secure environments.

I hope you can see my point:

  • Alerting users to potential errors in form fields is good.
  • But by changing entries instead of notifying the user that there is (or might be) an error and letting the user decide how to address it, activating autocorrect and autocapitalize in any form fields actually violates WCAG.
  • And WCAG 2.0 explicitly does not require or encourage error checking in login fields, because to do so would undermine the security of the website or application. For similar reasons, error checking shouldn't be done on input fields for account numbers or other sensitive information. You should not say, "The security code for that Visa card isn't 333 any more. Try 666 instead."

And thanks for your work to make Drupal even more accessible!

Cliff’s picture

Issue tags: +Accessibility

Updating to tag as an Accessibility issue.

JesseSturgis’s picture

FileSize
1.04 KB

This patch removes autocapitalize and autocorrect from the name and pass fields and satisfies W3C requirements. Running the existing code through validator showed that those two attributes were not allowed.

Cliff’s picture

Thanks, JesseStugis! It looks like we almost have this solved.

Dom., as to the aria in this login form, is it needed?

As I said, the purpose of aria-labelledby is to associate a label with a field when it would otherwise be hard to do. In the example I cited above, I'm not sure if the other possible approach would work. That would be:

<h2><label for="fruit"> Available Fruit </label></h2>
<ul role="listbox" id="fruit">
[etc.]

But labeling the fields on a login form isn't complex at all, so I'm not sure why we would even need aria here. Usually label is enough by itself.

So is this another of our issues involving aria orphans? Should we just remove the aria-describedby?

Dom.’s picture

Issue summary: View changes
FileSize
4.43 KB
10.62 KB

Hi !
Thanks @Cliff for all details and explanation and @JesseSturgis for the patch.
I'm not that happy with patch at #11 for reasons :

  • It does not also include patch #2, which would make work longer for alexpott to comit it in two spearate patches.
  • It does remove completely the autocapitalize and autocorrect.

We have two different things involved in this issue :

  • A/ The aria-describedby issue, which is pointing to an unset description in login block.
  • B/ The autocapitalize="off" and autocorrect="off" which are unvalid for W3C.

Regarding problem A :
- Login form is ok : it has a description for both the username and password. The markup is therefore okay and valid.

- Login block is not: the description is removed for some reasons (probably get more compact).

Regarding this, I see two possible solutions :

  1. Have the description back to login block too, but then it will take a design to keep it nice and compact.
  2. Remove the aria-describedby for login block only (as per my patch #2) since there is no description in that case.

Regarding problem B:
- @Cliff #9, you describe how the device should not input password (for security reasons) and should not change user input for no reasons (username are probably not words from dictionnary so a mobile should not autocorrect it). For this accessibility purpose, autocapitalize and autocorrect have been explicitely remove by adding autocorrect="off" and autocapitalize="off" (see #1955282).
We have two solutions :

  1. Revert issue #1955282 : meaning allow capitalization and autocorrection on some devices which seems to break accessiblity advices described by @Cliff #9.
  2. Find a way to add this explicit "off" setting by still being W3C valid. This may be done in JS for instance or another way to be defined.

Remaining tasks (updated in issue description too):
- For problem A :
-- choose between solution A1 or A2 (or define new one)
-- review patch #2 (if solution A2), or create new patch and review
- For problem B:
-- choose between solution B1 and B2
-- review patch #11 (if solution B1), or create new patch and review

mgifford’s picture

Thanks for starting this issue Dom., the login form is one of the most important forms in Drupal, so important that we get this right.

The UX folks are pushing against adding any more description elements if possible. There would need to be a strong case for including it but we probably shouldn't have the aria-describedby.

Just looking around for some references here.

Dom.’s picture

According to your documentation none of these attributs (autocapitalize, spellcheck, etc...) are valid. Should we thus consider keeping those and having the login form not valid, or remove those and have a little less usability on mobiles ?
In other words, can someone discuss on #13 so we can actually come up with a decision eventually ?

LewisNyman’s picture

I would rather keep the usability fixes for mobile rather than validate. It sounds like the only other actionable fix would be to remove the "described-by" attribute if there isn't a describing element? I think the description text we have on the login page inputs are kind of redundant.

Dom.’s picture

According to @LewisNewman and @mgifford, solutions choosen are :
A1: remove aria-describedby since their is no description to describe the element (patch attached for review)

B3: do not touch autocorrect="off" and autocapitalize="off", to keep usability (this is not accessiblity issue here but usability) in favor of W3C compliance.

NOTE: let's handle the problem A here and keep follow up on problem B here : #2487808: autocorrect="off" and autocapitalize="off" in login form are deprecated and may be not enough.

Status: Needs review » Needs work

The last submitted patch, 17: remove-aria-describeby-login-block-2467863-17.patch, failed testing.

Dom.’s picture

Status: Needs work » Needs review

I don't understand the test failing here...

benjifisher’s picture

I think we should update the issue summary based on the comment in #17. If the testbot approves, then I think the Novice tag should be removed once the summary has been updated.

benjifisher’s picture

Add one more Novice task, once the testbot approves: show the HTML markup before and after the patch, in order to make the accessibility review easier and more public.

heatherwoz’s picture

Working on this at mentored sprint at DrupalCon LA.

User login block before:

      <form class="user-login-form" action="/drupal/node?destination=/drupal/node" method="post" id="user-login-form" accept-charset="UTF-8">
  <div class="form-item js-form-type-textfield form-type-textfield form-item-name">
      <label for="edit-name" class="form-required">Username</label>
        <input autocorrect="off" autocapitalize="off" spellcheck="false" aria-describedby="edit-name--description" type="text" id="edit-name" name="name" value="" size="15" maxlength="60" class="form-text required" required="required" aria-required="true" />

      </div>
<div class="form-item js-form-type-password form-type-password form-item-pass">
      <label for="edit-pass" class="form-required">Password</label>
        <input aria-describedby="edit-pass--description" type="password" id="edit-pass" name="pass" size="15" maxlength="128" class="form-text required" required="required" aria-required="true" />

      </div>
<input type="hidden" name="form_build_id" value="form-TucjkBKVr9xy84ZcRPhYShokHx6LlE8_U3WSqQz33pY" />
<input type="hidden" name="form_id" value="user_login_form" />
<div class="form-actions form-wrapper" id="edit-actions"><input type="submit" id="edit-submit" name="op" value="Log in" class="button form-submit" />
</div>

</form>

User login block after patch applied:

<form class="user-login-form" action="/drupal/node?destination=/drupal/node" method="post" id="user-login-form" accept-charset="UTF-8">
  <div class="form-item js-form-type-textfield form-type-textfield form-item-name">
      <label for="edit-name" class="form-required">Username</label>
        <input autocorrect="off" autocapitalize="off" spellcheck="false" type="text" id="edit-name" name="name" value="" size="15" maxlength="60" class="form-text required" required="required" aria-required="true" />

      </div>
<div class="form-item js-form-type-password form-type-password form-item-pass">
      <label for="edit-pass" class="form-required">Password</label>
        <input type="password" id="edit-pass" name="pass" size="15" maxlength="128" class="form-text required" required="required" aria-required="true" />

      </div>
<input type="hidden" name="form_build_id" value="form-GEWllfmCRyA7LOW9i_uCHbKRetG5Fe6cK9gP37rHdtk" />
<input type="hidden" name="form_id" value="user_login_form" />
<div class="form-actions form-wrapper" id="edit-actions"><input type="submit" id="edit-submit" name="op" value="Log in" class="button form-submit" />
</div>

</form>      

Aria-described by attribute is removed.

benjifisher’s picture

Issue summary: View changes
Issue tags: -Novice

Thanks, @heatherwoz!

crasx’s picture

This patch does work but I am concerned we are fixing a symptom and not the actual issue. If I understand this correctly the issue occurs when code unsets #description without unsetting aria-describedby after the form is created.

Could we add something to the render layer to remove the aria-describedby if there is no description attribute or does this need to be done on a form by form basis?

mgifford’s picture

@crasx that does seem like it would be a better fix.

The login form is pretty unique. Are there other examples where we might want to unset the aria-describedby attribute like this patch does in $form['name'] & $form['pass']?

Would be better not to introduce a hacky solution to get around this though.

mgifford’s picture

Title: Login form is not W3C compliant » Login form's aria-describeby points to an element that doesn't exist
Priority: Normal » Major
Issue tags: +Needs reroll

I think at think that we need to address this issue with the login form in 8.0 and move @crasx's concerns that we remove the aria-describedby in FAPI if there is no description attribute to 8.1. Maybe we can address them both in 8.1, but I don't know it well enough, and having this error on all login pages is a pretty big issue.

Bumping this up to major.

Dom.’s picture

Regarding @mgrifford #28 :

I think at think that we need to address this issue with the login form in 8.0 and move @crasx's concerns that we remove the aria-describedby in FAPI if there is no description attribute to 8.1.

If I remember well by the time, my patch #17 actually does this:
- Because description is being removed in the login form block, the patch also removes the aria-describeby pointing to this none existant description.
- The patch #17 does not correct FAPI in any way, it is only login-block specific.

It was RTBC by @heatherwoz in #23. Does it need a new reroll and review ?

mgifford’s picture

I wasn't clear. @crasx suggested that fixing it just in the login block was a problem and that we should look for a broader fix to FAPI.

I don't see a reference to RTBC in the comment by @heatherwoz in #23.

I am willing to mark this RTBC though to fix the login block. I will create a new issue to fix fapi in 8.1. EDIT: Created - #2547063: Remove the aria-describedby introduced in FAPI if there is no description

mgifford’s picture

Status: Needs review » Reviewed & tested by the community
webchick’s picture

Status: Reviewed & tested by the community » Fixed

On the one hand, I agree with crasx that I'd much prefer to fix this holistically for any element missing #description, rather than force all developers who want to unset descriptions without introducing accessibility issues to know this One Weird Trick™.

However, I think the case for fixing this here is that the login block, unlike other forms where this might be happening, is much more prominent for end users. Also, the approach being taken here, where a block is the same as a full-page form but manually unsets descriptions, isn't like a widespread pattern we see lots of places. The only other potential place I can think of is Search, but the full page version doesn't have a description/described-by attribute, so we're OK there.

Typically we'd block this on tests; however, I don't know that it's worth a test for this one particular one-off issue—we're very unlikely to re-introduce this problem for the login block again. I think it's definitely worth a test if we fix this in the holistic way, though. So +1 on the follow-up issue to discuss this.

Committed and pushed to 8.0.x, with the small addition of a comment to explain why this was done:

    // When unsetting field descriptions, also unset aria-describedby attributes
    // to avoid introducing an accessibility bug.
    // @todo Do this automatically in https://www.drupal.org/node/2547063.

  • webchick committed d830e59 on 8.0.x
    Issue #2467863 by Dom., JesseSturgis, mgifford, LewisNyman, Cliff,...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.