CSS generated content and screen readers
As all widely used web browsers (unless you still consider IE7 as being widely used) now support the :before and :after pseudo-elements along with the content property, using those pseduo-elements has become more and more common.
There are many clever CSS tricks they can be used for, like implementing a particular design without having to insert extra markup into your HTML. There is one catch though, and many developers seem unaware of this: several screen readers will speak content that is created this way. VoiceOver does (in both OS X and iOS). NVDA does when used with Firefox, though not with IE. I made a CSS generated content demo page so you can try it yourself.
Depending on what is inserted, this may not be a problem. It may even be a good thing. But I have seen developers use CSS pseudo-elements to insert nonsensical content that they wouldn’t put in the HTML because it isn’t semantic, thinking that “well, this is CSS, and CSS is for presentation, so it should be all good”. And I can’t blame anyone for thinking that, because some of the things that happen with Screen readers and CSS are pretty unintuitive.
CSS generated content can cause problems for screen reader users in two ways:
- If the generated content is nonsensical, such as inserting random characters just for the sake of decoration, users whose screen readers support generated content will hear things like “right-pointing double arrow”. Rather annoying, but not likely a showstopper.
- If generated content is used to insert essential content, users whose screen readers do not support it will miss out completely (as will sighted users whose web browsers do not support CSS generated content). This is bad.
So just a brief heads-up that CSS generated content is not invisible to all screen readers. Neither is it announced by all screen readers. In other words, use with care and consider what happens both when it is supported and when it isn’t.
- Previous post: iOS orientation change and automatic text resizing
- Next post: Safer event handling with jQuery namespaced events