Accessibility support for CSS generated content

The CSS before/after pseudo-selectors can be used to insert content into a page. In some situations this technique is a useful thing to do, but how do browsers and screen readers handle the generated content?

Quick recap: The before/after selectors insert content either before or after an element’s existing content. For example the CSS shown below will insert “bar” immediately after the “Foo” that is already present in the HTML:


#a:after { content: 'bar'; }

<a href="/" id="a">Foo</a>

The result of which can be seen in this test case. For more information on using these selectors, read Chris Coyer’s introduction to after/before on CSS Tricks.

Accessibility mechanics

CSS generated content isn’t included in the DOM. Ordinarily browsers take information from the DOM to create the accessibility tree, but in this case the generated content is still factored into the accessible name computation for the element.

Accessibility results

Using the test case mentioned before indicates that generated content is accessibility supported in most browsers, and recognised by screen readers accordingly. Internet Explorer is the only browser regularly used with a screen reader that does not expose the generated content as the accessible name for the element. Screen readers depending on MSAA/UIAutomation in IE are therefore unaware of the generated content.

Browser and screen reader support for CSS generated content
Chrome 41 (Android) Chrome 41 (Windows) Firefox 36 (Windows) Internet Explorer 11 (Windows) Safari 8 (OSX) Safari 8.1 (iOS)
Jaws 16 N/A Yes Yes No N/A N/A
NVDA 2015.1 N/A Yes Yes No N/A N/A
TalkBack Yes N/A N/A N/A N/A N/A
VoiceOver N/A N/A N/A N/A Yes Yes

With Internet Explorer accounting for about 15% of traffic (in March 2015), there is good reason to consider the viability of using CSS generated content.

There is another more important consideration however – the separation of content and structure from design. Introducing content through the design layer breaks the standards model, and so it should be done only when the generated content does not alter the meaning of the original content. In other words, use CSS generated content to change or supplement the design, but not to create or alter important content on the page.

15 comments on “Accessibility support for CSS generated content”

Skip to Post a comment
  1. Comment by James Edwards

    I agree completely.

    The term “generated content” is a misnomer — because it isn’t content at all, it’s presentation.

  2. Comment by James Edwards

    But IMHO, screenreaders shouldn’t be reading generated content, precisely because it isn’t content. To my mind, IE’s behaviour is the only correct one.

    So I usually recommend hiding generated content with aria-hidden elements, i.e:

    Foo

    #a > span::after { content: ‘bar’; }

  3. Comment by Léonie Watson

    @James

    You’re right about “generated content” being a misnomer. I was surprised to find that’s how it’s described in both the CSS2.1 and CSS3 specs.

    Wonder if it’s worth filing a bug against CSS4 selectors?
    http://dev.w3.org/csswg/css-pseudo-4/#generated-content

    1. Comment by James Edwards

      @Léone

      Suggest that the spec re-names, or at least, re-describes it? Makes perfect sense to me, yes.

  4. Comment by James Edwards

    sorry, meant that link as a code example: <a href=”/” id=”a”>Foo<span aria-hidden=”true”></span></a>

    1. Comment by Léonie Watson

      @James

      Good idea to use aria-hidden. Getting slightly side-tracked, but you might be interested in the following Firefox bug, whereby aria-hidden isn’t honoured when CSS before/after selectors are used inside a button element.

  5. Comment by Neil

    I am not so sure we can define content as something that appears in the DOM. maybe that’s what we wish, but out there…
    Also, there are cases it’s not that obvious if the generated content alters the content meaning or not. for instance, i use it for presenting asterisk before required form fields.

    1. Comment by James Edwards

      The example you have of a “*” for required fields, I would argue that that’s not content, it’s presentation.

      The “*” doesn’t change the meaning of the field, is simply highlights the meaning it already has. (Assuming that the require nature of the field is already indicated with required/aria-required; you wouldn’t use the “*” alone as the only thing which indicates a required field.)

      So in that sense, it’s no different than making the text red or bold — it’s information, but it’s not content.

  6. Comment by Patrick H. Lauke

    One of the problems with generated content is that authors will and do use it to generate actual content. As such, I see the screenreader/browser behavior that exposes them as yet another “self defence” mechanism, as there’s no way for the AT to know whether or not the author has used the CSS “correctly” or if they’re abusing it to inject actual content that should be in the DOM.

    1. Comment by James Edwards

      That makes sense. From the screenreader’s point of view, I guess they don’t really have much choice but to announce it, rather than risk losing important content.

  7. Comment by chaals

    +1 to Patrick.

    Yes. In principle it is meant to be design. In principle, focus and hover are different things. But in the real world, generated content is content. So it needs to be made available, and now most systems do.

    Relying on authors having carefully read a spec and understanding subtle differences in when they should use approach A or approach B is not underestimating the intelligence of good authors. But it is exposing real users to the mistakes of “ordinary” (in the sense of ‘not very good’) authors, unnecessarily.

  8. Comment by Neil Osman

    since separation of concerns got somewhat blurred with the content attr and the future alt attr, it could have been handy if we had a css variant of aria-hidden.
    which brings to mind the thought if WAI-ARIA ought to be further developed so it could be expressed through CSS. Why not?

Comment on this post

Will not be published
Optional