The CSS "content" property accepts alternative text (#tilPost)

Developers often use before and after pseudo-elements (generated content) for the styling of elements in websites. With a few lines of extra CSS, it is possible to include icons, images, or even add text without adjusting the HTML.

Developers often use before and after pseudo-elements (generated content) for the styling of elements in websites. With a few lines of extra CSS, it is possible to include icons, images, or even add text without adjusting the HTML.

Unfortunately, you have to consider using content in pseudo-elements very carefully because it can affect accessibility. Just because your generated content is not defined in the HTML, it doesn’t mean that it is not picked up by assistive technology like screen readers.

Let’s have a look at an example:

.new-item::before {
  content: "★";
}

The above CSS code prepends the symbol (black star) to the inner content of elements with the class new-item. And this might be all great from a visual perspective, but for screen readers, it has unexpected side effects.

<a class="new-item" href="#">go to new things</a>

This link is now presented with a star before the inner text go to new things. On the other hand, screen readers will now read out "Black star go to new things", too. This experience is not great!

Today I learned that the content property supports a way to define alternative text for generated content.

.new-item::before {
  /* "black star" and element content is read out */
  content: "★";
  
  /* "Highlighted item" and element content is read out */
  content: "★" / "Highlighted item";
  
  /* Generated content is ignored and only element content is read out */
  content: "★" / "";
}

That’s pretty cool because we can now provide alternative texts right in CSS! Unfortunately, at the time of writing, the overall browser support is not given yet. Firefox and Safari are missing.

Today, you should still use generated content, and this way of handling its alternative text very carefully. Going with a separate element in combination with aria-hidden=true is probably still a better approach these days.

Edits part 1 – define alternative text in HTML or custom properties



Section titled Edits part 1 – define alternative text in HTML or custom properties

Andrea Giammarchi pointed out that having alternative text in CSS is not a scalable or maintainable solution, and I agree.*

The spec defines that it is possible to define the alternative using an element attribute. Unfortunately, the spec does not define if custom properties should be allowed – I don’t see a reason why they shouldn’t, though.

.new-item::before {
  /* "black star" and element content is read out */
  content: "★";
  
  /* Attribute content and element content is read out */
  content: "★" / attr(data-star-alt);
  
  /* Custom property and element content is read out */
  content: "★" / var(--star-alt);
}

⚠️ Unfortunately, using attr didn’t seem to work in Chrome with Voiceover.

Edits part 2 – improve browser support using feature detection



Section titled Edits part 2 – improve browser support using feature detection

Zoltan Hawryluk pointed out that you could feature detect the browser support of content: '' / '' with @supports and then use the Safari-only alt property. Unfortunately, the only thing I could find about alt is this article by Bruce Lawson).

@supports (content: "x" / "y") {
  .new-item::before {
    content: "★" / "Highlighted Text:";
  }
}

@supports not (content: "x" / "y") {
  .new-item::before {
    content: "★";
    alt: "Highlighted Text:";
  }
}

Using these two features it boils down to only Firefox not supporting alternative text for generated content.

Additional resources

My friend Manuel published a very nice follow up post, that you might want to check out, too – Here’s what I didn’t know about “content”.

And also Adrian Roseli went deeper into the browser support topic of Alternative Text for Generated Content.



Reply to Stefan


Print Share Comment Cite Upload Translate
APA
Stefan Judis | Sciencx (2024-03-28T14:54:48+00:00) » The CSS "content" property accepts alternative text (#tilPost). Retrieved from https://www.scien.cx/2020/04/28/the-css-content-property-accepts-alternative-text-tilpost/.
MLA
" » The CSS "content" property accepts alternative text (#tilPost)." Stefan Judis | Sciencx - Tuesday April 28, 2020, https://www.scien.cx/2020/04/28/the-css-content-property-accepts-alternative-text-tilpost/
HARVARD
Stefan Judis | Sciencx Tuesday April 28, 2020 » The CSS "content" property accepts alternative text (#tilPost)., viewed 2024-03-28T14:54:48+00:00,<https://www.scien.cx/2020/04/28/the-css-content-property-accepts-alternative-text-tilpost/>
VANCOUVER
Stefan Judis | Sciencx - » The CSS "content" property accepts alternative text (#tilPost). [Internet]. [Accessed 2024-03-28T14:54:48+00:00]. Available from: https://www.scien.cx/2020/04/28/the-css-content-property-accepts-alternative-text-tilpost/
CHICAGO
" » The CSS "content" property accepts alternative text (#tilPost)." Stefan Judis | Sciencx - Accessed 2024-03-28T14:54:48+00:00. https://www.scien.cx/2020/04/28/the-css-content-property-accepts-alternative-text-tilpost/
IEEE
" » The CSS "content" property accepts alternative text (#tilPost)." Stefan Judis | Sciencx [Online]. Available: https://www.scien.cx/2020/04/28/the-css-content-property-accepts-alternative-text-tilpost/. [Accessed: 2024-03-28T14:54:48+00:00]
rf:citation
» The CSS "content" property accepts alternative text (#tilPost) | Stefan Judis | Sciencx | https://www.scien.cx/2020/04/28/the-css-content-property-accepts-alternative-text-tilpost/ | 2024-03-28T14:54:48+00:00
https://github.com/addpipe/simple-recorderjs-demo