Is it possible to add "aria-hidden" for css content property?

1.9k Views Asked by At

I have a decorative element in the header that separates links "|". It is added as a CSS content element:

::after {
    content: "|";
    .....
}

In HTML it is presented inside of the span along with the header link:

<span>
    <a ...>
        Link
    </a>
</span>

In some screen readers, "|" separator is being displayed and I want to make it invisible for the screen readers by adding "aria-hidden". Is there any way to add it to the CSS file? Or is there any other way to make a CSS content property invisible for screen readers?

I saw an example of adding ARIA property in square brackets like so:

::after[aria-hidden] {
    content: "|";
    .....
}

However, it would remove the visibility of the whole element completely, not only for screen readers.

3

There are 3 best solutions below

2
QuentinC On

No, it's impossible. This is one of the drawback of CSS generated content, and why it's quite discouraged from accessibility point of view. You can't add HTML attributes to an element using CSS. If you want to control ARIA attributes like aria-hidden, you have to add the content in the HTML code.

Just for your information, most screen readers render CSS generated contents as normal, but some don't at all with some browsers. So, CSS content isn't recommended either for conveying important information.

Note that your proposition, ::after[aria-hidden] don't add the attribute to the generated element, but tries to match a generated element having the attribute. As it isn't possible to add any attribute to CSS generated elements, it won't ever match anything. It doesn't make any sense, and is in fact invalid according to CSS specification.

0
slugolicious On

As noted, you can't add ARIA attributes via CSS. However, the way I usually do this is have a separate <span> element that uses the CSS content attribute and specify aria-hidden on the <span>.

<style>
  .foo::after {content: "|"}
</style>

<a href="...">some link</a>
<span class="foo" aria-hidden="true"></span>
<a href="...">another link</a>
3
Andy On

It is not possible. There are two great answer already, I’d like to explore some other options, though.

A solution would be to not use content. `

a {
  display: inline-block;
}
a::after {
  content: "";
  display: inline-block;
  height: 1em;
  margin-left: .3em;
  border-right: .12em solid black;
}
<a href="#">Link</a>
<a href="#">Link</a>
<a href="#">Link</a>

CSS selectors

In CSS you can only select an element for styling, you cannot add attributes. Some elements allow to define generated content, for example the ::before and ::after pseudo-elements.

You can select elements based on attributes, for example [aria-hidden].

Note that

Pseudo-elements are featureless, and so can’t be matched by any other selector.

so you cannot select a pseudo-element based on its attributes. It has none!

The selector from the example ::after[aria-hidden] is invalid and will be discarded.

You could match an element that has aria-hidden and add a pseudo-element to it. Beware though, that aria-hidden is not a regular boolean attribute, it expects a string true|false.

[aria-hidden="true"]::after {
  content: …

Defining accessible names for generated content

As discussed in the related question How to hide CSS generated content from screen readers without HTML markup?, the CSS standard allows to define alternative text (an accessible name) for generated content.

If the pseudo-element is purely decorative and its function is covered elsewhere, setting alt to the empty string can avoid reading out the decorative element.

content: "|" / "";

Unfortunately, alternative text for content is not well supported.

Speech module

There is the standard CSS Speech Module which intends to allow control of how contents are announced by screen readers.

/* not supported anywhere – yet? */
::after {
  speak: never;
}

This is purely theoretical, though, and would probably only apply to screen readers, not to assistive technology in general. Braille displays would still output the content of the pseudo-element.