Can I prevent :after pseudo-element from being read by screen readers?
Asked Answered
B

6

37

Please consider the following HTML markup:

<label class="required" for="email-address">
  Email Address
  <span class="audible">Required</span>
</label>
<input type="text" id="email-address" placeholder="[email protected]">

Along with that I have the following CSS:

.required:after {
  color: red
  content: "*";
  /* ... */
}

When I focus the field a screen reader will read out: Email Address required "star". I'd like to use CSS only to display a visual *, but I don't want that read by screen readers. Is this possible?

Or is this scenario common enough that screen readers and users would ignore the star or adjust the settings. I.e., is this not a real problem?

Bim answered 29/10, 2014 at 15:19 Comment(1)
Here's the answer that works https://mcmap.net/q/426878/-how-to-hide-css-generated-content-from-screen-readers-without-html-markupSuperannuated
S
14

Try this, it targets screen readers with a media query and hides the star

@media reader, speech, aural {
    .required:after {
        display: none;
        visibility: hidden;
    }
}

Update:

As the support for my initial solution doesn't seem to be that good I have thought of a alternative. It occurred to me that the only way to ensure that its not read by a screen reader (w/o extra markup) would be to have no asterisk at all! However you could add a image with css to look like a asterisk like so:

.required:after {
    content:'';
    display: inline-block;
    width: .5em;
    height: .5em;
    background-image: url(http://upload.wikimedia.org/wikipedia/commons/b/b5/Asterisk.svg);
    background-size: .5em .5em;    
    vertical-align: top;
    margin-left: .15em;
    margin-top: .1em;
}

http://jsfiddle.net/3a1dvdag/

Salzhauer answered 29/10, 2014 at 15:28 Comment(5)
You could just use content:none if you were going down this approach.Catachresis
This is just what i was looking for. Any information on support for this?Bim
Aural is in the spec so it should be the most implemented. w3.org/TR/1999/REC-html401-19991224/…Catachresis
I tested this on voice over, nvda and jaws (latest). Only jaws seemed to do it. But that might be good enough for me.Bim
@Bim I have just updated the answer with a better way that should have greater support, that said i haven't been able to test it as i don't have any screen readers available to meSalzhauer
W
7

Gonna throw this out here as there's no final answer highlighted and it's a much discussed topic.

The above solution given by @Sam will be in the near future the best option to go for. No browsers thus far that have the @media aural, speech media query so, if you provide it, it will only work in the near future.

Is there any other way to hide pseudo elements from screen readers?

Yes, with limits. You can use the "private use Unicode character set". Because the characters are private use, screen readers cannot pronounce them and therefore ignore the character.

If that's not an option try to stick to <span> or <i> elements with aria-hidden="true" on them. It's not as clean as pseudo elements, but at least you have full control of the content.

<button type="button">
    <span class="i i-arrow-down" aria-hidden="true">Label
</button>
Whitaker answered 2/8, 2016 at 6:21 Comment(3)
Im going to say after looking into this adding the element instead of using the pseudo is probably a good way to go.Bim
@Bim Another option is to always provide an aria-label on the <button> tag. Then the contents (both the <i> el as the actual label) are ignored and the aria-label is read out loud. I tested it with VoiceOver and it works there, will test it on JAWS and other screenreaders. I'll get back on this.Whitaker
@Bim Meanwhile I tested it on Jaws as well and works perfect.Whitaker
C
6

There's this syntax where one can set the alt text for pseudo elements using slash as delimiter. We can leave it blank to indicate the element should be ignored (the same way it is usually done with img tags), like this:

.required:after {
    color: red
    content: "*" / "";
    ......
}

This source indicates there was an 'okay' browser support on 2020. I've tested in Chrome with VoiceOver on MacOS and it works now (as opposed to what the table indicates), so hopefully support may already be very good by now.

https://a11ysupport.io/tests/tech__css__css_generated_content_alt

Checkroom answered 3/8, 2022 at 2:58 Comment(1)
Unfortunately, this does not currently work with Firefox and Safari.Liggins
W
4

Right now I think there only exists either workarounds like using a combination of HTML elements and aria-hidden, or limited support from browsers that implement the CSS3 speech module. Note that this module is still at Candidate Recommandation level, but should provide a more accurate control on what should be read aloud or not.

If browser support was perfect, a good answer would be:

Use CSS3 speech module.

But yeah, this is the Web, and browser support isn't perfect, so I'd recommend using some combination of span with aria-hidden="true" even 4 years after this question was asked.

But one should know that although the aria-hidden property indeed prevents the element content from being read, it also hides its presence to the user. The difference is subtle, but the speak property will not hide the element presence by mentioning it when saying how many children belong to an element.

For instance, let's consider this code:

<html lang="en">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <title>What a beautiful day!</title>
  <style type="text/css">
  body {
    counter-reset: headers;
  }

  h2::before {
    counter-increment: headers;
    content: counter(headers, upper-roman);
    speak: none;
  }
  </style>
</head>
<body>
  <h2>Early morning</h2>
  <h2>Lunch</h2>
  <h2>Before dinner</h2>
</body>
</html>

And this is what Voice Over reads for the Lunch element, on a supporting web browser (Firefox 59 here):

Voice Over on Firefox 59 result for CSS speak: none property

It counts the speak: none; element in (pseudo-elements count for one), but doesn't read it alound.

Using aria-hidden leads the element not to be counted at all.

I haven't tried other screen readers, and your mileage may vary.

Whall answered 31/5, 2018 at 15:44 Comment(0)
C
1

If you use a separate span for your icon you could apply an aria hidden tag to prevent screenreaders from reading it. I'm not sure what the support is for this though.

<label class="required" for="email-address">Email Address 
<span class="icon" aria-hidden="true"></span>
<span class="audible">Required</span>  </label>
<input type="text" id="email-address" placeholder="[email protected]">

More info in the W3C spec

Catachresis answered 29/10, 2014 at 15:30 Comment(1)
Yeah i might have to go this way. But i was wondering if there was a way without adding the extra markup - so css only.Bim
P
-1

make a css classs with atribute speak:never

Penley answered 20/7, 2023 at 8:27 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Horseplay

© 2022 - 2024 — McMap. All rights reserved.