Page MenuHomePhabricator

MediaWiki's assistive headers are broken in modern browsers
Closed, ResolvedPublic

Description

In vector we output assistive headers into h5's to separate the parts of the UI for users using screen readers to understand.

However we use display: none; on these headers.
Modern screen readers use standard css-capable web browsers. This means that use of display: none; hides content from the very users who are supposed to be seeing them.

WAVE's text overview provides a good view of how this affects the output since they intentionally hide content that is display: none;ed to reflect the reality of screen readers:
http://wave.webaim.org/report?view=textonly&url=http://en.wikipedia.org/wiki/Ian_Fleming

As you can see our personal links, namespaces, and actions all just end up as a big mass of unlabeled lists that appear conceptually as part of the page text after categories.


Version: unspecified
Severity: normal

Details

Reference
bz41297

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 22 2014, 1:08 AM
bzimport set Reference to bz41297.
bzimport added a subscriber: Unknown Object (MLST).

That url is not really useful... "The file you uploaded is too big
Files uploaded to WAVE cannot be larger than 450 kilobytes."

Maybe we should use visibility: hidden instead?

(In reply to comment #1)

That url is not really useful... "The file you uploaded is too big
Files uploaded to WAVE cannot be larger than 450 kilobytes."

Looks like it's inconsistently working and not working.

Here's a smaller disambiguation page that'll also have less superfluous content in the way.

http://wave.webaim.org/report?view=textonly&url=http://en.wikipedia.org/wiki/Ian_Fleming_%28disambiguation%29

Maybe we should use visibility: hidden instead?

visibility: hidden; is supposed to have the same effect on screen readers as display: none; does.

There are a few notable techniques for hiding things visually while leaving them in the page for screen readers.

{ position: absolute; left: -9000px; } /* Or some variant using -9999px, top: of the same value, and/or !important */

And:
{ overflow: hidden; height: 0; }

WordPress seems to like this technique:
{ position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px); }

The h5 were changed to h3, but still use display: none; However, the above wave link now shows the proper result.

This is NOT fixed. Those patchsets solve completely different problems.

The #p-search, #p-personal, #p-views, and #p-namespaces headers are still hidden using display: none;

Oh huh, sorry. I've always thought they used ones of the accessible techniques, but that's apparently only used for #mw-navigation h2.

This bug is not about making headers visible, it's about using a screen-reader friendly method of hiding headers, because things like display: none; also hide them from screen readers that are supposed to be reading them out.

For an update on the techniques:

{ overflow: hidden; height: 0; }

This technique breaks in VoiceOver and should be avoided.

{ position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px); }

This one is the most reliable of them all, it works universally without side-effects.

@DanielFriesen , this seems to work only with browsers with a full support of CSS3,

{ visibility: none; z-index: -1; }

would be better

@Rezonansowy Do you have some tests/articles for backing your most recent code example?

The code of the newly merged Less helper mixin screen-reader-text() from https://gerrit.wikimedia.org/r/261611

.mixin-screen-reader-text() {	
      display: block;
      position: absolute !important;
      clip: rect( 1px, 1px, 1px, 1px ); /* not supported in IE 6&7 */
      width: 1px;
      height: 1px;
      margin: -1px;
      border: 0;
      padding: 0;
      overflow: hidden;
}

@Volker_E Here's the correct example:

#mw-navigation h2 {
    visibility: hidden;
}

I tested it with #mw-navigation h2, using a Firefox Inspector. Seems to work.

You can test it with any Wikipedia article.

@Rezonansowy that way the element still takes up the space that it would do if it were not hidden (unlike display:none;). quite often that is undesirable.

@Rezonansowy You can read at snook.ca about the technical backgrounds that lead to the properties currently in the mixin, which are also widely accepted as best practice for hiding content still accessible for screen readers.

@TheDJ At some point we should consider adding clip-path property like in clip-path: polygon( 0 0, 0 0, 0 0, 0 0 ) as laid out in updated offscreen techniques article.

This is NOT fixed. Those patchsets solve completely different problems.

The #p-search, #p-personal, #p-views, and #p-namespaces headers are still hidden using display: none;

I am not able to find any instance of #p-search, #p-personal, #p-views or #p-namespaces with display:none;. I understand that this issue is old and that the problem could have shifted to another place. @DanielFriesen could you please confirm that the problem persists, and if it does, help me understand it?

They are h3 elements now, and (with a few exceptions) they are still being hidden with display: none, using selectors like #whatever h3.

Thanks @matmarex !

#p-search has an <h3> with a <label> of Search, this isn't hidden but is clip: rect'd, so its accessible.

The #p-personal h3 is hidden, but the div's aria-labelledby attribute is set to its id so its accessible. Same for #p-views, #p-namespaces.


The ARIA 1.1 spec says that, " the interface is such that it is not possible to have a visible label on the screen, authors SHOULD use aria-label and SHOULD NOT use aria-labelledby." Would it makes sense to remove the <h3>s and only use aria-label? Are they being used elsewhere?

Volker_E claimed this task.

What @Prtksxna shared above. They are fined and aligned with ARIA standard.