Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessibility improvements #3210

Closed
stevevance opened this issue Feb 6, 2015 · 25 comments
Closed

Accessibility improvements #3210

stevevance opened this issue Feb 6, 2015 · 25 comments
Labels
accepted accessibility Anything related to ensuring no barriers exist that prevent interactions or information access feature help wanted needs discussion

Comments

@stevevance
Copy link

I was testing my website with a person who is completely blind and uses the VoiceOver (VO) function on an iPad. I was observing her as she browsed the entire webpage (through a tapping function in VO that mimics tabbing between elements*) and came across the Leaflet map. I don't remember if she came across the map by tabbing through the page or by randomly tapping on it. What comes next is the unexpected behavior.

Problems while using VoiceOver

VO spoke the filename of the images in the map's base layer, speaking, "6078 dot p n g, link", "6079 dot p n g, link", and so forth. When the user tabbed and landed on the zoom controls VO read "plus sign, link" and "hyphen, link". I can't remember if it spoke the default title attributes on these buttons

The ESRI search button had no attribute to read, but VO said that it was a search input that could be opened. This is its own issue.

When she landed on the layer control (where layers are switched on and off) the outcome was as I expected, and useful. VO spoke the name of the layer, indicated it was a checkbox or radio button and said whether it was selected. By double tapping she could control the layer's visibility.

I feel at this point that it must be explained that this user likes maps. She can use maps that are designed for the blind. She highlighted the "Blindsquare" app as extremely usable, as it speaks the names of businesses she's walking past or that are nearby in a different direction.

I think that Leaflet can be designed to be usable by the blind because it's still possible to describe what features are being overlaid on the map. Through continuing to tab through the page VO came across the one marker on my map that has a popup that's popped up when the map loads. The information in the popup window could be read, and any links within it to other pages could be clicked/tapped.

What she or VO couldn't do was tab to the next few hundred markers on the map that were inside MarkerCluster (the plugin) clusters.

Expectations

My ideas apply only to using VO on an iPad. I think that when tabbing through elements on the screen that VO should come across the

tag and read its title attribute which should tell the user that this is a map, what the map shows, and that it's been designed for their screen-reading environment.

The next tab should land on the zoom controls, layer controls, and any other controls, so the user can understand what functions are available to control the map. These should all have title attributes.

The next tab should land on any marker that has a popup and the contents of the popup should be read. The next tabs should land and activate other markers depending on how the map designer activates them (does a click on the marker open a popup or does it open a link to another page?).

The difference in marker icons should be made apparent to the screen reader, through the title and alt options that Leaflet exposes. For example, I have markers that indicate the kind of building permit it represents, and I use a wrench to indicate "renovation" permits. I have gone and set these attributes for the website, and any other missing attributes, but I'm not sure if they will be noticed by VO.

Conclusion

The biggest obstacle I observed was that each individual base map tile image was selectable and the user had no idea what these were or what they would do if she clicked on them (that they were links was unexpected).

I think these map tiles should be invisible to even the screen reader. Anyone with an iPad can turn on VoiceOver by asking Siri (or in the Settings app) and experience some of these problems.

Notes

This user primarily uses JAWS software on a Windows computer to navigate the web and all other software. That experience is very different than using VO because of the hardware keyboard and the key commands that JAWS offers (for example, press "H" to jump between heading tags on a website).

It's nothing short of amazing to watch how VoiceOver works. To move across the page, to tab forward, you swipe from left to right and VO reads the element. For example, text that is tagged in HTML with <h1> to <h6> will be read by VO as "[tagged text], heading level 1". To select something, like a link, you would double tap.

@nateirwin
Copy link

Don't want to take over your issue here, @stevevance, but I saw your tweet about this earlier, and wanted to jump in and talk about Leaflet accessibility in general. This could (should?) be its own issue, but I thought I'd start here because the context you provide is a great lead-in.

I work on digital mapping for the National Park Service, and all of our products must meet Section 508 and WCAG. We recently went through a third-party accessibility audit to test our web maps, and, because our mapping library (NPMap.js) is built on top of Leaflet, a number of the audit's findings and recommendations apply directly to Leaflet itself. I've been meaning to open an issue about this for quite some time, but other things got in the way. Thanks for the nudge!

I've taken many of the audit's recommendations and turned them into actionable items. You can see the open issue on the NPMap.js side here: https://github.com/nationalparkservice/npmap.js/issues/168.

We (the NPMap team) would love to start implementing a few of these fixes in Leaflet, if there is support for this work. Specifically, we'd like to work on these fixes:

  1. Use buttons, not links, for controls
  2. Use alt text rather than title attributes on controls
  3. Set tabIndex of HTML element with the leaflet-container class to 0
  4. Use anchor elements rather than divs for markers and point the href attribute to the id of the popup's div (I feel like this one may be pretty difficult)
  5. Set focus to a header element in popup when popup is shown, setting the tabindex to -1 before the element is focused

The list above is a subset of the fixes we are looking to implement in NPMap.js, but these are the items I think it makes sense to implement in Leaflet. I believe the third item would help with the VoiceOver issue.

There is a larger issue that I really don't have a solution for: All vectors, not just markers, need to be tabbable. The way things are currently, only markers are tabbable. This means that VoiceOver and other accessibility technologies won't work for other vectors. At this point, I don't know enough about accessibility and SVG, VML, and Canvas to make an educated recommendation, but I'm willing to put some time into researching.

@geospatialem
Copy link

@stevevance + @nateirwin -

Check out this StackOverflow issue as well, it may be helpful to you as it was for my application:
http://stackoverflow.com/questions/26745454/how-to-make-leaflet-tile-layers-accessible

@nateirwin
Copy link

@geospatialem: That looks good. May want to add that to the list...

@mourner
Copy link
Member

mourner commented Feb 6, 2015

Thanks every for extremely valuable feedback! It's in my best interests to improve Leaflet on the accessibility front so related PRs are always welcome. I'll follow-up with more detailed response but just wanted to quickly comment specific changes by @nateirwin:

Use buttons, not links, for controls

Agreed!

Use alt text rather than title attributes on controls

The HTML specs say that alt attribute is only applicable to images and inputs. Did you meant to say something other than "controls"?

Set tabIndex of HTML element with the leaflet-container class to 0

Already the default behavior.

Use anchor elements rather than divs for markers and point the href attribute to the id of the popup's div (I feel like this one may be pretty difficult)

Yeah, can be a bit difficult. Are there alternatives? Maybe making the whole popup content container focusable too and switching the focus on marker click — would that work?

Set focus to a header element in popup when popup is shown, setting the tabindex to -1 before the element is focused

Can you describe how this works in practice?

@nateirwin
Copy link

Thanks, @mourner. To address your comments:

The HTML specs say that alt attribute is only applicable to images and inputs. Did you meant to say something other than "controls"?

Sorry, I should have been clearer. We use images in most of our controls (as do some of Leaflet's controls and many Leaflet plugins), and the guidance we received said we should use foreground images (not background images) with the alt attribute specified on them. The report said the following about title attributes:

Title attributes are not reliably read out by all assistive technologies. Some screen readers don’t read title attributes by default, so those users will not be able to distinguish the map controls from one another. Title attributes can also be problematic for low vision users—they're not readable with screen magnification, and they may obscure other interface elements.

Because of this guidance, we are switching all of our controls to foreground images with alt attributes specified, and we stopped using title attributes on most elements.

Already the default behavior.

Ah, ok. I thought the tabindex was set to 1.

Yeah, can be a bit difficult. Are there alternatives? Maybe making the whole popup content container focusable too and switching the focus on marker click — would that work?

I believe the intention of using anchor elements with href attributes (href="#popup-div") is so that someone using a screen reader can "click" on the element and have the assistive technology read out the contents of the popup. The problem with this is it assumes that each marker has a popup div that is rendered when the layer is initialized. Correct me if I'm wrong, but I believe that popups are generally built on the fly when a marker is clicked or activated with a keyboard and then destroyed so there aren't a bunch of unnecessary DOM elements laying around.

Another possible solution to this is to add a hidden div to every marker div that contains information about what the marker is. Maybe the same information that displays in the popup, or maybe a more succinct version of that information. A screen reader could then easily access this information when jumping from marker to marker.

Both of these solutions assume that the information needed to build a popup is available on the client. I know that we often retrieve information for popups via AJAX calls, and these changes obviously will not address that use case.

All that said, I think what you outline is a good improvement over the current behavior. I'd say it is a good compromise; it improves accessibility while preserving the simplicity and flexibility of the current approach.

Can you describe how this works in practice?

In practice, you would do something like this when a marker is clicked or activated with a keyboard:

<h3>Oregon Caves National Monument</h3>
$(‘.leaflet-popup-content h3’).attr(‘tabindex’, -1).focus();

By setting the tabindex to -1, if the keyboard is used to tab away from the h3 element, it is not possible to tab back to it. By setting focus to that element, a screen reader would immediately read the title of the popup, providing important context for subsequent content.

To be honest, I'm not 100% clear on why the tabindex of the h3 needs to be changed to -1, but I can get some clarification on that.


One other thing that can be improved is the popup's close link. We can easily improve its accessibility by adding an aria-hidden="true" attribute to the "x" span. Then we could add a hidden span with close text after it:

<a class="leaflet-popup-close-button" href="#marker-id">

  <span aria-hidden="true">x</span>

  <span class="visuallyhidden">close popup</span>

</a>

.visuallyhidden {
  border: 0;
  clip: rect(0 0 0 0);

  height: 1px;
  width: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  position: absolute;
}

@mourner mourner changed the title Map cannot be browsed while iOS VoiceOver is turned on Accessibility improvements Feb 7, 2015
@jasonlally
Copy link

Glad to see this issue! Thanks for calling attention to this @stevevance and @nateirwin

The fix for the tile images posted on stack overflow above still seems to be problematic from a user perspective, but please correct me if I'm wrong. I'm by no means an expert here.

Is it useful for tile images to be made "visible" to screen readers? I feel like a blind or vision impaired user won't get much useful context from underlying base tiles, especially if there are a dozen or so tiles with alt="Map image tile."

Would the preferred behavior be to hide these altogether from screen readers or make it easy to skip these with a skip link? Or is that easy enough to tab past all the images already with existing screen reader technology?

@jasonlally
Copy link

Oh, sorry @stevevance I think that's exactly what you're proposing above. 👍

@stevevance
Copy link
Author

@jasonlally Hey Jason!

So, I read @mourner and @nateirwin's comments and I am still stuck: I really don't know what I need to change on my site. Some of my maps have a fair amount of self-written functions to interface with the map and all of them use plugins.

The biggest issue the blind user I worked with encountered was that every time she tapped the map on her iPad the iPad would read the filename of the image tile. That would be the first thing I would like to fix. Does anyone have a suggestion on how to tell the iPad that the element isn't "tappable"?

@jasonlally
Copy link

As far as making the iPad ignore the image tiles, would following the advice here help?
http://www.w3.org/WAI/tutorials/images/decorative/

Something like:

<img src="tile.png" role="presentation" alt="">

One could argue that map tiles are more than decorative and do provide information, but really the context is provided by the layer information, in this primary use case. It appears that assistive technologies will ignore images with alt="" and newer tech will honor the role="presentation" aria tag.

Anyone else have thoughts on this? It seems like a simple change to leaflet here would be to have tiles output this as the default?

@amnesia7
Copy link

@nateirwin not sure how easy it is to change the leaflet controls to use buttons rather than links but what if the current links used role="button"?

@stevevance
Copy link
Author

@jasonlally It seems that Leaflet by default doesn't include an alt tag on the images. Is a missing alt tag the same as alt=""?

@MuellerMatthew
Copy link
Contributor

There is a larger issue that I really don't have a solution for: All vectors, not just markers, need to be tabbable. The way things are currently, only markers are tabbable. This means that VoiceOver and other accessibility technologies won't work for other vectors. At this point, I don't know enough about accessibility and SVG, VML, and Canvas to make an educated recommendation, but I'm willing to put some time into researching.

One work-around I have been experimenting with is wrapping each SVG path tag with a blank <a> tag which is tab accessible. Then I added a bit of css code to style the paths when they have focus:
a:focus>path.leaflet-clickable {stroke-width:5px;}
to my css so that when I tab to the link that surrounds each path, the path changes so I can visually tell which one I am tabbed.
and now I am working on trying to capture the click event from the which surrounds the path and treat it as a click event on the actual object.

@atstp
Copy link
Contributor

atstp commented Jul 14, 2015

@nateirwin & @stevevance If you're looking for a patch on the leaflet controls (while the bigger issues are getting attention), L.EasyButton is updated to use buttons with img tags inside.

Here are zoom controls that, based on what's above, should be screen reader friendly.

Hope it helps in the meantime!

@patrickarlt
Copy link
Member

After reading through this issue (in response to an internal Esri discussion around accessibility) I think a few things could be done:

  • Use role=presentation and alt="" on map tiles so screen readers don't read their URLs.
  • User role=button and aria-label="Zoom In/Out" on the zoom buttons. aria-label might be read by more screen readers then title.

Is a missing alt tag the same as alt=""?
@stevevance in #3210 (comment)

Definitely not. In my own testing most screen readers will read the images URL if an alt attribute is missing. You can see https://www.w3.org/TR/WCAG20-TECHS/H67 for more info and https://github.com/Esri/esri-leaflet/blob/10fced2121c5cbc506c8b6e7ee95cc891076eabe/src/Layers/TiledMapLayer.js#L81-L85 for how this is implemented in Esri Leaflet.

Maybe making the whole popup content container focusable too and switching the focus on marker click
@mourner in #3210 (comment)

i actually really like this idea. If a user focuses a popup we should send focus to the popup container. I might look into putting this in Esri Leaflet first and seeing if I can push anything that might be useful upstream to Leaflet. This would also need to make SVGs accessible but I think there is something here.

@stevevance
Copy link
Author

stevevance commented Nov 11, 2016

Use role=presentation and alt="" on map tiles so screen readers don't read their URLs.

Yes. Please make this a reality.

patrickarlt added a commit to patrickarlt/Leaflet that referenced this issue Nov 12, 2016
patrickarlt added a commit to patrickarlt/Leaflet that referenced this issue Nov 12, 2016
mourner pushed a commit that referenced this issue Nov 12, 2016
DiogoMCampos pushed a commit to DiogoMCampos/Leaflet that referenced this issue Dec 18, 2016
DiogoMCampos pushed a commit to DiogoMCampos/Leaflet that referenced this issue Dec 18, 2016
@remilev
Copy link

remilev commented Nov 12, 2017

Hi, in my own testing of NVDA screen reader, I see that popups are not easy to open. In "navigation" mode of NVDA, when a marker is focused by TAB key, screen reader will say the alt text of img tag if any. But hit ENTER or SPACE doesn't open the popup.

Adding only role="button" in the img tag of markers make it work.

_initIcon: function () { ... if (icon !== this._icon) { ... icon.setAttribute('role', 'button') }... } works great. Is there any reason not to do so ?

After that : maybe focus popup content automatically at popupOpen -> the voice can read it -> give focus back to the marker when popup is closed -> user can tab to next marker.

This would be very useful for case where popups contain complex informations, links or buttons and can't be sumarized only in the alt tag of icons.

EDITED
This 2015 demo is very enlightening : http://melmo.github.io/accessibility/berlin.js/code/dist/leaflet.html

  • They use role='presentation' for tiles (which is now in leaflet core)
  • They focus popup when opened and focus back to the marker when closed
  • They use role='application' on map div

The role='application' basically prevents assistive technology (JAWS / NVDA) to take hand over JS.
In my testing (chrome and firefox, leaflet in fullscreen) it prevents the screen reader to read ALL the alt tags of icons when page loads. And after that, user can TAB from one marker to another and open the markers whith ENTER key. Just like usual leaflet keyboard navigation without screen reader.

The role='application' may be dangerous as it turns off reen readers keyboard shortcuts a user could be used to, but it seems to fit perfectly with leaflet.
The article says it breaks things in firefox. It is ok for me though.

NOTE : adding role='button' on img tags is still a good idea :
When tabbing beetwen markers, user will hear : "this is my alt text - BUTTON" and not "this is my alt text - GRAPHIC". So he knows he can "click" it with enter key. great!

dstaflund added a commit to dstaflund/mws-restaurant-stage-1 that referenced this issue Mar 10, 2019
I don't like the idea of hiding content from end-users, but there
are a number of good reasons for hiding the map (and associated) skip-link from assistive technologies:

- Accessibility isn't part of Leaflet yet
  (See Leaflet/Leaflet#3210)

- Leaflet markers don't provide any information to assistive
  technologies that isn't already in the text-only section of the
  sight.  In particular, it doesn't include coordinates or other
  information into the accessibility tree.  In fact, it provides
  less out of the box.

- There's no easy way of customizing the overall title of the map
  and so you get the names of all markers spoken one after the other
  each time the map is refreshed (by giving the map focus or by
  zooming in or out, etc).

- You can't hide or customize the copyright links embedded in the
  map so you have to tab through 4 or 5 additional links to get out
  of the map control.

Of course, if I have time to work on the issue before handing it in for marking, I'll revisit this decision.  But for now, the map is out.
@Tmarty
Copy link

Tmarty commented Dec 23, 2019

They focus popup when opened and focus back to the marker when closed

This seems helpful to keyboard users. Would this be a good idea to add to leaflet itself?

An alternative is to insert the popup right after the marker in the HTML. This could remove the need for calling focus and would allow tabbing out of the popup to the next marker.

@ahukkanen
Copy link

#3210 (comment)

One other thing that can be improved is the popup's close link. We can easily improve its accessibility by adding an aria-hidden="true" attribute to the "x" span. Then we could add a hidden span with close text after it:

<a class="leaflet-popup-close-button" href="#marker-id">

 <span aria-hidden="true">x</span>

 <span class="visuallyhidden">close popup</span>

</a>

One accessibility evaluation I was involved in reported this particular issue.

I think the "visually hidden" text explanation for the close popup link should be also translatable to other languages.

@skorasaurus
Copy link
Contributor

They focus popup when opened and focus back to the marker when closed

This seems helpful to keyboard users. Would this be a good idea to add to leaflet itself?

An alternative is to insert the popup right after the marker in the HTML. This could remove the need for calling focus and would allow tabbing out of the popup to the next marker.

There is an existing issue for this already at #2199

@skorasaurus
Copy link
Contributor

skorasaurus commented May 26, 2020

#3210 (comment)

One other thing that can be improved is the popup's close link. We can easily improve its accessibility by adding an aria-hidden="true" attribute to the "x" span. Then we could add a hidden span with close text after it:

<a class="leaflet-popup-close-button" href="#marker-id">
> 
 <span aria-hidden="true">x</span>
> 
 <span class="visuallyhidden">close popup</span>
> 
</a>

One accessibility evaluation I was involved in reported this particular issue.

I think the "visually hidden" text explanation for the close popup link should be also translatable to other languages.

@ahukkanen - #7079 (specifically 45f04d3) improves the text for closing a pop-up.

Regarding translations: internationalization isn't built into leaflet core but it is available as a plugin - https://github.com/yohanboniface/Leaflet.i18n

@Malvoz
Copy link
Member

Malvoz commented Sep 15, 2020

@mourner, @IvanSanchez, and other core contributors, would you consider adding an "Accessibility" label for issues in this repo? If it is the case that you think it's not very helpful in terms of keeping track of issues, I still ask you to consider it, as I believe it encourages the community to think about accessibility.

@johnd0e johnd0e added the accessibility Anything related to ensuring no barriers exist that prevent interactions or information access label Sep 16, 2020
@johnd0e
Copy link
Collaborator

johnd0e commented Sep 16, 2020

@Malvoz
Done

@Malvoz
Copy link
Member

Malvoz commented Sep 16, 2020

Thanks @johnd0e, that's great. The following issues/PRs are related to improving accessibility, they should have the accessibility label:

1. #2199
2. #3472
3. #6742
4. #6821
5. #7192
6. #7193
7. #7211
8. #7346
9. #7499
10. #7274
11. #7498
12. #6248
13. #7538
14. #7539

Edit: updated.

@Malvoz
Copy link
Member

Malvoz commented Feb 23, 2021

TLDR:
This thread has gotten pretty long, and at this point some of the problems raised have been fixed. I suggest that we open new issues for the remaining problems that do not yet have one, so that we can close this one out as it is getting hard to track what's still to be done.


Having read all the comments, here's a summary of all problems that are yet to be addressed:

@stevevance's original post:

🔗 Issue 1:

What she or VO couldn't do was tab to the next few hundred markers on the map that were inside MarkerCluster (the plugin) clusters.

I don't have VoiceOver, but I can confirm that tabbing works on Android using TalkBack.

@stevevance can you (or someone else) confirm that this is still an issue with VO? In that case:

  • Open a new issue?

I think that when tabbing through elements on the screen that VO should come across the tag and read its title attribute which should tell the user that this is a map, what the map shows, and that it's been designed for their screen-reading environment.

This suggests a few things:

🔗 Issue 2.1:

should tell the user that this is a map

🔗 Issue 2.2:

what the map shows

Developers can already provide a summary of the map themselves using aria-label on the leaflet-container, <figcaption>, etc.

  • Open a new issue?

🔗 Issue 2.3:

that it's been designed for their screen-reading environment

I'm not sure this is something that should be embedded into maps directly. Another alternative could be for Leaflet to (at some point) have an accessibility statement on the website (similar to Esri's Commitment to Accessibility), which could be found through the attribution links.


🔗 Issue 3:

The next tab should land on the zoom controls, layer controls, and any other controls, so the user can understand what functions are available to control the map.
The next tab should land on any marker that has a popup and the contents of the popup should be read.

DOM order is important for keyboard-only and screen reader users, I agree that controls should come before map features in the DOM order.


🔗 Issue 4:

@nateirwin's #3210 (comment):

  1. Use buttons, not links, for controls

@mourner agreed.


🔗 Issue 5:

  1. Use anchor elements rather than divs for markers and point the href attribute to the id of the popup's div (I feel like this one may be pretty difficult)
  2. Set focus to a header element in popup when popup is shown, setting the tabindex to -1 before the element is focused

Both these points are essentially suggesting to solve the same thing: delegate focus to the popup container so that screen readers announce the content after it has been opened.


🔗 Issue 6:

There is a larger issue that I really don't have a solution for: All vectors, not just markers, need to be tabbable. The way things are currently, only markers are tabbable. This means that VoiceOver and other accessibility technologies won't work for other vectors.


@nateirwin #3210 (comment):

🔗 Issue 7.1:

One other thing that can be improved is the popup's close link. We can easily improve its accessibility by adding an aria-hidden="true" attribute to the "x" span.

🔗 Issue 7.2:

Then we could add a hidden span with close text after it:

<a class="leaflet-popup-close-button" href="#marker-id">

  <span aria-hidden="true">x</span>

  <span class="visuallyhidden">close popup</span>

</a>

We can (and should) use aria-label instead of a custom "visually hidden" class.


🔗 Issue 8:

@remilev #3210 (comment):

in my own testing of NVDA screen reader, I see that popups are not easy to open.

hit ENTER or SPACE doesn't open the popup.

Adding only role="button" in the img tag of markers make it work.

(the ENTER or SPACE part is covered by #7369.)


🔗 Issue 9:

maybe focus popup content automatically at popupOpen -> the voice can read it -> give focus back to the marker when popup is closed -> user can tab to next marker.

As stated earlier in this comment, sending focus to popups is tracked in #2199, but sending focus back to the marker after closing a popup has not been a consideration in that issue.


@Malvoz
Copy link
Member

Malvoz commented Nov 28, 2021

In #3210 (comment) I went through basically every problem discussed in this issue.

Only this and this remain, but I'm not sure they're actual problems.

And there's now a Leaflet accessibility guide.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted accessibility Anything related to ensuring no barriers exist that prevent interactions or information access feature help wanted needs discussion
Projects
None yet
Development

No branches or pull requests