{"version":"https:\/\/jsonfeed.org\/version\/1","title":{"value":"yatil.net feed"},"home_page_url":"https:\/\/yatil.net","feed_url":"https:\/\/yatil.net\/blog","items":[{"id":"https:\/\/yatil.net\/blog\/accessible-css-generated-content","url":"https:\/\/yatil.net\/blog\/accessible-css-generated-content","title":"Accessible CSS Generated Content","content_html":"

His1<\/a><\/sup> goal was to provide text effects by layering different styles of the same font on top of each other. Designers use this technique to extend a base font style with other flourishes of the same font. The final code he came up with is this HTML, using the notranslate<\/code> class to prevent translation of the heading2<\/a><\/sup>:<\/p>\n

<h1 class=\"type-family-jakob notranslate\" \n    data-heading=\"France-Norv\u00e8ge\">\n      France-Norv\u00e8ge\n<\/h1><\/code><\/pre>\n

The CSS looks like this:<\/p>\n

[class*=\"type-family\"] { position: relative; }\n\n[class*=\"type-family\"]:before, [class*=\"type-family\"]:after {\n  content: attr(data-heading);\n  position: absolute;\n  z-index: 1;\n  overflow: hidden;\n  left: 0;\n  top: 0;\n  font-size: inherit;\n  font-weight: normal;\n}<\/code><\/pre>\n

Until a couple of years ago, the browsers did not treat generated content as \u201creal\u201d content. They did not expose it to assistive technologies like screen readers. That created an issue, for example when web developers used CSS to specify the file format of a document:<\/p>\n

<a href=\"link\/to\/an\/interesting.pdf\">\n  Get the Report\n<\/a><\/code><\/pre>\n
a[href$=\"pdf\"]:after { content: \" (PDF)\"; }<\/code><\/pre>\n

For visual users, the link text \u201cGet the Report (PDF)\u201d would have been clear. But \u201c(PDF)\u201d was not conveyed to screen readers and other assistive technologies and thus not their users. Most developers don\u2019t intend that behavior, so browsers started to treat generated content as actual content<\/em>.<\/p>\n

Back to Andy\u2019s example. The \u201caccessible name\u201d (the label that assistive technology uses) of his heading rank 1 would include the :before<\/code> and the :after<\/code> version of the contentand the content of the <h1><\/code> itself. The browser \u201csees\u201d:<\/p>\n

<h1 class=\"type-family-jakob notranslate\">\n  France-Norv\u00e8ge France-Norv\u00e8ge France-Norv\u00e8ge\n<\/h1><\/code><\/pre>\n

There is an ARIA attribute that we can use to overwrite<\/em>3<\/a><\/sup> the content of the <h1><\/code>: aria-label<\/code>. So we could augment Andy\u2019s code like this to avoid tripling the heading:<\/p>\n

<h1 class=\"type-family-jakob notranslate\" \n    data-heading=\"France-Norv\u00e8ge\"\n    aria-label=\"France-Norv\u00e8ge\">\n      France-Norv\u00e8ge\n<\/h1><\/code><\/pre>\n

This would work, but having two attributes repeating the content of the heading feels wrong. As attr()<\/code> can use any attribute, not only data-<\/code> attributes4<\/a><\/sup>, we can use it with the aria-label<\/code> and remove data-heading<\/code>:<\/p>\n

<h1 class=\"type-family-jakob notranslate\" \n    aria-label=\"France-Norv\u00e8ge\">\n      France-Norv\u00e8ge\n<\/h1><\/code><\/pre>\n
[class*=\"type-family\"]:before, [class*=\"type-family\"]:after {\n  content: attr(aria-label);\n  \u2026\n}<\/code><\/pre>\n

This is where this story could end. And indeed this is where this story would have ended a couple of weeks ago. Yet, thanks to accessibility advocates, aria-label<\/code> is now actually one of the attributes that is<\/em> translated when using Google Translate through Google Chrome<\/a> \u2013 but not in other browsers. If that is enough to remove the notranslate<\/code> class from the heading depends on your circumstances. As the short clip of this example codepen<\/a> shows, the aria-label<\/code> attribute translates nicely:<\/p>\n