Skip to content
This repository has been archived by the owner on Jun 30, 2018. It is now read-only.

Add technique for identifying CSS generated content-images #297

Closed
alastc opened this issue May 18, 2017 · 72 comments
Closed

Add technique for identifying CSS generated content-images #297

alastc opened this issue May 18, 2017 · 72 comments

Comments

@alastc
Copy link
Contributor

alastc commented May 18, 2017

As discussed in #296, one of the aspects of the Adapting text SC #78 was the ability to change font-family by the user.

That aspect has been removed from Adapting text because it is (or should be) a failure of 1.3.1, i.e. not identifying an element as an image that has the sole purpose of displaying an image.

This would apply to things like font-icons, image backgrounds and before/after pseudo content, e.g.
<span class="icon" aria-hidden="true"></span><span class="off-screen">Bookmark</span>

Although it has an accessible name, the icon would disappear if a user over-rides font-family and/or background images.

If an element (like the span above) is identified as an image, then the user stylesheet/script/extension could use this sort of CSS to avoid replacing the icons:

*:not([role="img"]) {
font-family: Comic Sans MS, Georgia,'Times New Roman',serif;
}

This technique would not preclude any particular implementation, so even very simple versions can achieve it quiet easily, e.g:
<span class="icon" role="img" aria-label="Bookmark"></span>

The key thing is that an element intended to provide an image is given that role.

The next step is a test page with good & bad variations on this, I've assigned it to myself for now and created this issue to remind me to do it.

@lauracarlson noted there is already a failure under F87 - Failure of Success Criterion 1.3.1 due to inserting non-decorative content by using :before and :after pseudo-elements and the 'content' property in CSS, we could also generate a similar failure for this, but I think a technique first is the way to go.

@alastc alastc self-assigned this May 18, 2017
@patrickhlauke
Copy link
Member

for clarity, note that icon font usage is not really "background content images", as the content is not an image in the background, but rather a CSS generated foreground character. suggest changing the title here (and avoiding this inaccuracy in future discussions)

@patrickhlauke
Copy link
Member

and actual background images (using CSS background: ... or similar) wouldn't cause any problems for LV users anyway with regards to font substitution, as they don't use any font/text that would be substituted

@patrickhlauke
Copy link
Member

patrickhlauke commented May 18, 2017

split out the issue of LV users explicitly suppressing images (also applies to non-LV users of course) into a separate issue/technique, i'd say, as it feels like currently you're trying to tackle different things under one big umbrella technique/advice (and this aspect is likely more along lines of "how to provide alternative content for CSS background images", which of course also touches on how to do it for AT users etc and relates to 1.1.1, 4.1.2, 1.3.3)

@alastc alastc changed the title Add technique for identifying background content images May 18, 2017
@alastc
Copy link
Contributor Author

alastc commented May 18, 2017

I've tried "identifying CSS generated content-images" instead, but note that if #296 takes effect then font-icons are being added to non-text content.

Actual background Images (e.g. sprites) are also an issue, if you override foreground colours you have to also override background colours, and therefore images. It is also an issue for High Contrast Mode. See the requirements table for more.

The principle is if it looks like a duck, I mean image, smells like an image, it is identified as an image.

Before we split things out, let me do a test page with as many variations as I can think of, and then you can point out some more, and then we can see what fits together.

@patrickhlauke
Copy link
Member

I've tried "identifying CSS generated content-images" instead, but note that if #296 takes effect then font-icons are being added to non-text content.

sure, they're non-text content. but they're still not "background content images"

@alastc
Copy link
Contributor Author

alastc commented May 18, 2017

So I didn't include "background" :-)

@lauracarlson
Copy link
Contributor

lauracarlson commented May 18, 2017

Hi Alastair and all,

As mentioned, a start of a technique is in the Wiki:
Providing a Semantically Identified Icon Font with role=img.

Please test it. I tested in Safari and it seems to work okay there.

Also please, edit at will, add more examples etc.

Thanks,
Laura

@lauracarlson lauracarlson self-assigned this May 21, 2017
@lauracarlson
Copy link
Contributor

I added a second example to the Semantically Identifying Icon Font with role=img technique.

Comments and ideas for improvement are appreciated. @alastc please, edit as you see fit.

Thanks,
Laura

@patrickhlauke
Copy link
Member

patrickhlauke commented May 21, 2017 via email

@patrickhlauke
Copy link
Member

a more robust and sensible way of doing

<a href="email.html">
 <!-- Icon added visually. Text alternative (which overrides any character that might be used as icon font code point) and role="img" added. -->
 <span class="fa fa-envelope" aria-label="Favorite" role="img"></span>
</a>

would be, in my view, to add the aria-label on the link itself and simply completely hide the icon font, a la

<!-- add aria-label on the link itself -->
<a href="email.html" aria-label="Favorite" >
  <!-- Icon itself completely hidden from AT, so needs no role nor alternative -->
  <span class="fa fa-envelope" aria-hidden="true"></span>
</a>
@alastc
Copy link
Contributor Author

alastc commented May 21, 2017

That's fine for screenreader style AT, but how would a more basic extension know that there is an icon it shouldn't override?

What we're trying to achieve (without disrupting other AT) is to identify icons that are implemented by CSS background or font-icon. Without something (like role=img) how does that work? Hidden text / meta-data isn't useful here.

@patrickhlauke
Copy link
Member

[aria-hidden=true]:empty

@alastc
Copy link
Contributor Author

alastc commented May 21, 2017

Hmm, not sure what proportion of implementations that would work for, it feels like there should be a positive thing an author can add to say "this is an image".

@patrickhlauke
Copy link
Member

conversely, adding an explicit role to something that's hidden from the accessibility tree feels...slightly off (but as a suggested practice, rather than something normative, i guess it could fly)

@jake-abma
Copy link
Contributor

This would apply to things like font-icons, image backgrounds and before/after pseudo content, e.g.
Bookmark

In this case it doesn’t have an accessible name. There is text content present but no programmatic relationship.

Another one, probably mentioned already, but how to convey the hidden accessible name (via aria-label or aria-labelledby) to LV users?

@patrickhlauke
Copy link
Member

Another one, probably mentioned already, but how to convey the hidden accessible name (via aria-label or aria-labelledby) to LV users?

to use spec language, that's orthogonal to the problem discussed here i'd say. the image itself is purely decorative, and the accessible name is on the actual control. how aria-label etc on arbitrary elements (not just CSS images, but any other element where it may be used, like form controls, links, etc) can be visually exposed is a separate, broader discussion that should be had.

@alastc
Copy link
Contributor Author

alastc commented May 22, 2017

The problem case is when it is not decorative, but meaningful. Either as an indicator (e.g. a star), or interactive.

If you have low vision and expand things to >200%, the last thing you want to do is replace the icons with their accessible name. Here's a quick example from the BBC zoomed in:

BBC homepage at 400% showing icons

Then replacing top icons with the hidden text:

BBC homepage at 400% showing text instead of icons

I didn't try and replace the weather icons, but you get the idea. Replacing the icons with their hidden text breaks the layout, I had to undo a lot of CSS in order to show the text. Without personalisation that doesn't work.

What I'm aiming for a set of methods that work such as:

  • Use a foreground img/SVG (which with HTTP2 is not a performance hit so people are moving that way anyway).
  • Include text (or rather, if text is included then don't worry about it).
  • If you can't do either of the above, then you can use a background image or font icon, but semantically mark your icon as an image. (Kind of like you can recreate a data table with ARIA. Not ideal, but there if you need it.)

I'm working on a test page (starting from Laura's) to try and make a matrix of what works / doesn't work in both screen readers and when over-riding fonts/backgrounds.

I find it interesting that replacing fonts and backgrounds only breaks some of the icons, I've come across a lot of big sites that use different methods for icons (e.g. BBC, Adobe) where some are foreground, some are background. We just need a little push for foreground or semantic fallback.

@lauracarlson
Copy link
Contributor

Hi @patrickhlauke and @alastc ,

Removed the aria-hidden="true" attributes, as they'd result in the entire element being hidden, meaning that the aria-label would not be seen by any AT either.

Thank you, Patrick!

Alastair, I updated the live examples to match the HTML in the Wiki (no aria-hidden="true). If you want to add them to your test page, they are at:

Thanks,
Laura

@steverep steverep assigned steverep and unassigned alastc, lauracarlson and steverep May 22, 2017
@steverep
Copy link
Member

Hi @alastc and @lauracarlson.... Sorry I accidentally unassigned both of you in trying to assign myself as well, and now I can't seem to reassign you both. The widget is not very screen reader friendly.

@alastc
Copy link
Contributor Author

alastc commented May 23, 2017

I've fleshed out that test page.

@steverep I meant something like example B3 or B4 on that page, where they are both within a link.

I still need to test in NVDA and/or Jaws, but I was surprised VoiceOver didn't read any of the font-icon 'characters' out, I thought it would. Maybe I'm remembering NVDA, and VO doesn't read CSS generated content?

Examples A6, B6 and C6 are with aria-label="" instead of aria-hidden, seems to work ok, although VO reads out "Link, image, [name]" so it is a little busy, but it works there.

I also need to add a set of examples for background images instead, but that shouldn't be as difficult as the font-icon scenario.

From a dev point of view, my favourite is probably this one for links with text (c6):

<a href="#">
   <span role="img" class="fa fa-star" aria-label=""></span>Favourite
</a>
@steverep
Copy link
Member

just so that folks can get a clearer first-hand picture of the problems you're describing, what browser/AT combinations (and any specific settings) is this causing the problems you mention?

So far I've tried:

  • NVDA + Firefox, IE, or Chrome
  • ZoomText + Firefox or IE (no Chrome support)
  • VoiceOver + Safari (iOS only - no access to a Mac)
  • Orca + Firefox

I need to go back and document cases better (too much for a thread post like this anyway), and also add JAWS to the mix.

@alastc, can we move your test page somewhere we can both edit and collaborate? I'm guessing a wiki won't work because we can't easily link to the Font Awesome CDN, but I could set it up on my domain if you'd like.

As for your examples, it would help to put the desired behavior in each case:

  • A should be identified as an "image" and then the name "favorite" (keyboard or mouse)
  • B should be identified as a "link image" and the name "favorite" (keyboard or mouse)
  • C should be identified as "link: favorite" via keyboard (ignore the icon as decorative), and the same, nothing, or just "image" on mouse over (guidance here is lacking, but announcing the URL is possible and obviously undesirable)

C6 is okay with NVDA, but none of your A or B are okay. Try just:

<span class="fa fa-star" role="img" aria-label="favorite"></span>

for A, and then just wrap the anchor around it for B.

@jake-abma
Copy link
Contributor

I would just be happy to go trough all Alastairs options but it's still not clear for me what goes wrong in UA/AT as I've also tested my options and also added the image variant below the font-icon variant. Checked with Jaws/IE - FF/NVDA - VoiceOver/Mac and all works fine with mouse/keyboard...?!

As with images not being exposed to accessibility API when alt is left empty we use the aria-hidden variation for role=“img”. According to the spec this is valid.

“An element is considered hidden if it, or any of its ancestors are not rendered or have their aria-hidden attribute value set to true.”

My examples as suggested before and which seem to work when I test it are at:

http://codepen.io/Jake-Abma/pen/BRGeop

Really trying to ‘get’ what’s wrong with it before searching for other possible solutions.

@jake-abma
Copy link
Contributor

jake-abma commented May 24, 2017

and aria-hidden="true" does NOT work in practice for accessible names on mouse over or for some focus indicators whenever it is used on visible content.

Do you mean you 'see' the icon but it's 'not' read by a screen reader? If that is the case than we do agree, but this is supposed to be that way. Just like we 'hide' the image (<img...>) for icons when alt is left empty.

@patrickhlauke
Copy link
Member

taking a real-world example (and forgive the fact that there are probably lots of other tiny issues in the code, since I only touched it years ago): https://www.paciellogroup.com makes use of traditional FontAwesome glyphs (in the main part of the page, as well as in the footer for all the social media links) that are hidden using aria-hidden="true". Tested this with iOS/VoiceOver, NVDA/Chrome/Firefox/IE, JAWS/Chrome/Firefox/IE.

The circular question mark glyph next to "Why Accessibility?" doesn't seem to be causing any trouble.

The social media links do seem to confuse iOS/VO a bit in terms of where the focus outline is (is this the problem you mentioned?).

2017-05-24-09 16 58

This is clearly a shortcoming/bug in VoiceOver ... nothing inherently wrong with the use of aria-hidden. If I recoded those links to use aria-label on the link rather than the classic .sr-only type CSS, VO behaves correctly with regards to the outline.

Using NVDA with "Enable mouse tracking" (which I normally have disabled) i see that in some combinations NVDA announces just the destination of those links, and not the content that is hidden with sr-only (in Chrome, NVDA remains completely silent when moving the mouse over those links). Once again, this points to a bug in NVDA.

So while I can see that there are current bugs in AT, this to me points to bugs in AT rather than anything fundamentally broken with aria-hidden itself. For a "right here, right now" advice I'd caution that certain combinations/uses are not fully supported by AT in certain combinations, but AT (and browsers) have bugs. It is not in my mind something fundamentally incorrect with careful use of aria-hidden, but rather something that needs to be reported to AT for them to fix.

@allanj-uaag
Copy link
Contributor

@alastc was looking at the test page. with an eye towards low vision folks. Except for the C group with on screen text, if the icon fails to load the low vision user gets a square and no on screen text. A @title would be very useful. or some method where text becomes visible if the icon fails to load.
something like... (from https://www.filamentgroup.com/lab/bulletproof_icon_fonts.html)
HTML


Twitter

CSS
.icon-fallback-text .icon {
display: none;
}
.supports-fontface.supports-generatedcontent.icomoon .icon-fallback-text .icon {
display: inline-block;
}
.supports-fontface.supports-generatedcontent.icomoon .icon-fallback-text .text {
/* a generic way to visually hide content while remaining accessible to screen readers (h5bp.com) */
clip: rect(0 0 0 0);
overflow: hidden;
position: absolute;
height: 1px;
width: 1px;
}

@alastc
Copy link
Contributor Author

alastc commented May 24, 2017

Hi @allanj-uaag, I'm not sure what you're using to switch fonts, but when I added the *:not([role="img"]) to the text-adaptation script, that worked fine (except for two which it didn't, expectedly).

The first recommended ones from the filament group article is equivalent to C3 in the test page, but that example is wrapped in a link. The second with fall backs is more complex, but to do with how the fall backs work.

The main difference in what we are suggesting here is that it adds role=img, so a user-side script doesn't kill the font or backround, it is compatible with their techniques.

@allanj-uaag
Copy link
Contributor

@alastc I didn't switch fonts, I turned them off (changed @font-face to @font-facex) to simulate what happens if the font fails. My concern is that except for a few instances, screen readers will get the accessible name of the icon. without a title (which doesn't work from the keyboard) or some other fallback low vision users are at a loss if the font-icon fails - the get a square. Except for the C group where text is on the screen. Tho designers don't always like text on the screen.

@alastc
Copy link
Contributor Author

alastc commented May 24, 2017

@allanj-uaag that misses the point of this technique though, the point was to provide a technique so that user-side scripts can differentiate icons from general font (text) usage. I.e. when you use a script/extension to change font it will not affect the font-icons.

@steverep I was intending to show things that don't work as well as those that do, but good point:

  • I've added an example a2.1, which is a simple method of "Favourite, image".
  • I thought B6 was ok, but is the fact it's an image important in that scenario? So long as the function is announced, that's what matters. In which case b5 is ok.
  • I've added B7 as the suggested format.

From looking at the various options, it seems that having an element as an image equivalent seems best, then treat it as such with alt text.

Oh, and I used the filament group's 'star' example so it isn't reliant on an external font now, so we can put it anywhere now.

@mraccess77
Copy link

@steverep wrote Instead of repeating myself, please see my original comment above. In short, aria-label="" is NOT skipped over by most UAs and instead behaves just like alt="", and aria-hidden="true" does NOT work in practice for accessible names on mouse over or for some focus indicators whenever it is used on visible content. Let's please focus on what works in practice (i.e. has good accessibility support), and not what we presume should work.

I've read the thread but don't agree. I don't think we should be going against the specification in two areas just because assistive technology work a certain way. If we need to change the spec that is different -- but as a standards organization we need to have criteria that matches the standards and doesn't reflect the current state of assistive technology hacks. aria-hidden is not supposed to be to exposed in the accessibility tree and an empty aria-label is supposed to be skipped over in the name calculation. Using aria-label="" is an based on the alt="" outdated hack to communicate decorative content and I don't think we should continue or promote such an ambiguous solution.

@alastc
Copy link
Contributor Author

alastc commented May 26, 2017

Using aria-label="" is an based on the alt="" outdated hack to communicate decorative content and I don't think we should continue or promote such an ambiguous solution.

Even if it's a better solution? I'm not sure we're talking about the same thing?!

If you have a link containing a foreground image of a star, and text of "Favourite", would you want it to say "Link, image, favourite, favourite", or just "Link, favourite"? It seems to be a clear case of duplicative alt-text.

We've been testing scenarios where CSS injected images (via font-icons or background images) are used on their own, with text and/or in a link. It does appear that having an element (e.g. <span>) and treating it like a foreground image (using aria-label) is the best bet. Using aria-hidden can work in some cases, but it is really confusing and sometimes counter-productive.

Anyway, this is a bit off-track, as the role=img bit seemed to work ok, there are several working examples for each scenario.

@lauracarlson
Copy link
Contributor

Hi @alastc and @steverep ,

Alastair wrote:

the role=img bit seemed to work ok, there are several working examples for each scenario.

I have worked a bit more on our technique page for Providing a Semantically Identified Icon Font with role=img.

The description currently reads:

The objective of this technique is to show how to provide a semantically identified icon font that does not disappear if a user overrides font-family via user stylesheet.

Some low vision users rely on user stylesheets to override fonts to perceive content. However, they need to be able to perceive icon fonts that are meaningful, for instance indicators (e.g. a star signifying a favorite) and interactive ones (e.g. an email link).

The key is for the author to semantically markup icon fonts with role="img". Then the user's font replacement selector can hook into that semantic and exclude role="img". This results in those icon fonts being shown.

So far we have one example for each scenario (indicator, link with visible text, link without visible text). They are:

  • Example 1: Star Icon Font used as an indicator (not interactive)
  • Example 2: Email Icon Font in a link without visible text
  • Example 3: Email Icon Font in a link with visible text

Alastair and Steve, please add more examples and edit/improve the page as you see fit.

Thank you!
Laura

@jake-abma
Copy link
Contributor

Hi All,

As I've mentioned before and also provided some examples the solution as provided till now only cover certain implementations of font-icons. There are millions of multiple coloured font-icons out there where these solutions will not work. The multi coloured icons consist of more than 1 font-icon stacked on top of each other. Often these are used in a mix together with the simple one-off font-icons.

Think of favourite icons where there are 5 next to each other, four full yellow, the last half yellow / half grey. The last one is a stacked one which would not be shown with the examples provided. The techniques shown will change the meaning of the star rating. (four instead of four-and-a-half).

I've been implementing this for the last couple of years and using only the simple variant will cause half of the icons to show up and the other half not. Users will not know using their own style sheet. This should not be what we want to promote, so if we already want to give a solution we must be clear to provide a full approach solution / technique.

Regards!

@jnurthen
Copy link
Member

@jake-abma It would be hacky but you could put role="img" on those child images (which are hidden using aria-hidden). This would then prevent them from being removed with the font substitution.

@jake-abma
Copy link
Contributor

jake-abma commented May 31, 2017

Please note font-icons are also used a lot without the <span class="icon" aria-hidden="true"></span> construction but as part of other elements. Think of an arrow before a link or check icon before a list item by using the :before / :after on the link / list items. Both are added via CSS without span/icon markup. Need to cover those too... ?!

@jnurthen
Copy link
Member

@jake-abma I started by saying it would be hacky ;)
Semantics /should/ be ok as the sub images are hidden with aria-hidden so the tree shouldn't be altered. besides role="img" makes all children presentational anyway in the accessibility tree. So long as none of the children can take focus it shouldn't actually be a huge issue. Icon fonts are - after all - a bit of a hack anyway so I wouldn't be totally averse to recommending a hack on top of them to make them work correctly.

@alastc
Copy link
Contributor Author

alastc commented Oct 12, 2017

LVTF comment: Laura created several techniques for this in the wiki, awaiting instructions on how to get these approved and incorporated into the main WCAG repo.

@joshueoconnor
Copy link
Contributor

@alastc can this be closed? Btw Good work @lauracarlson

@alastc
Copy link
Contributor Author

alastc commented Dec 17, 2017

I think so, so long as Laura (or someone) has a task to create the technique.

@jake-abma
Copy link
Contributor

@alastc, @lauracarlson, @joshueoconnor, I’ll be happy to support / help create if needed

@lauracarlson
Copy link
Contributor

lauracarlson commented Dec 18, 2017

Hello everyone,

Jake wrote:

I'll be happy to support / help create if needed

Thanks @jake-abma .

I created the technique: Providing a Semantically Identified Icon Font with role=img. It is in the wiki. We have been awaiting instructions on how to get it approved and incorporated into the main WCAG repo.

Josh and Andrew, do we need a survey to get this new technique approved?

Jake, after it is approved, if you could take the text and incorporate it into the WCAG repo that would be great.

After the technique is approved and in our official WCAG techniques, I suspect that this issue can be closed. Is that correct Josh?

Thanks everyone!

@awkawk
Copy link
Member

awkawk commented Jan 8, 2018

Closing as we have a suggested technique that we can evaluate.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.