Screen readers and CSS

As I have noted in a couple of blog posts recently, there are some cases when CSS has quite unexpected results in screen readers (or the way web browsers create the accessibility information they hand over to screen readers). If you haven’t read them, the posts are Screen readers, list items and list-style:none and Using display:table has semantic effects in some screen readers.

Here are a few examples:

Using display:table on non-table elements to get the visual layout characteristics of an HTML table without actually using one may cause screen readers to act as if there was a real table

on non-table elements to get the visual layout characteristics of an HTML table without actually using one may cause screen readers to act as if there was a real table Using display:block or float on table-related elements may cause screen readers to treat the table as a layout table and ignore its semantics or report an incorrect data structure

or float on table-related elements may cause screen readers to treat the table as a layout table and ignore its semantics or report an incorrect data structure Using list-style:none to visually remove bullets or numbers from list items may cause screen readers to ignore them too, basically treating list items as paragraphs of text

Some argue that this is in fact correct behaviour and that screen readers should do their best to convey only what is visible on the screen. I disagree with this since it has the effect of mixing content and semantics (HTML) with presentation (CSS). A central idea of CSS is that it makes it possible to use correct semantics in the HTML layer while still being able to change the visual appearance of your document. I think there are very few developers who expect that using CSS to change the way an HTML element is displayed will also change its semantics for screen reader users.

But if this is the way browser and screen reader vendors think it should be, here are some other situations where CSS should change the semantics of the underlying HTML:

<irony>

h1, h2, h3, h4, h5, h6 { font:inherit; margin:0; } should turn all headings into plain text

should turn all headings into plain text .h1 { display:block; margin:0.67em 0; font-weight:bold; font-size:2em; } should turn arbitrary elements into real h1 headings

should turn arbitrary elements into real h1 headings a:link, a:visited { color:inherit; text-decoration:none; } should turn all links into plain text

should turn all links into plain text .link { display:inline; margin:0; color:#00e; text-decoration:underline; } should turn arbitrary elements into links (without hrefs though)

should turn arbitrary elements into links (without hrefs though) fieldset { display:inline; margin:0; padding:0; border:0; } should prevent screen readers from announcing legend text before form controls

should prevent screen readers from announcing legend text before form controls input[type="text"] { display:inline; padding:0; border:0; font:inherit; } should turn text inputs into non-interactive plain text

should turn text inputs into non-interactive plain text .offscreen { position:absolute; left:-9999px; } should have the same effect as display:none , as should .invisible { position:absolute; opacity:0; }

</irony>

Yes, I’m being ironic, or at least trying to be. It would be a bit absurd if all of this was implemented. But I think it’s very confusing that lists and tables are treated the way they currently are in some combinations of browsers and screen readers.