Skip to content

Instantly share code, notes, and snippets.

@alice
Last active July 9, 2019 15:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alice/756caca028b2dae610e4ed5184c2f93e to your computer and use it in GitHub Desktop.
Save alice/756caca028b2dae610e4ed5184c2f93e to your computer and use it in GitHub Desktop.

Alternative Text for CSS Generated Content

Problem

CSS generated content may consist of text, images, or a combination of the two.

However, if the generated content is within a pseudo-element, there is no way to provide any kind of text alternative for the content.

Examples

https://css-tricks.com/examples/PseudoSprite/ uses the following CSS snippet to generate a sprited image inset into a <p> element:

.star:before {
    content: "";
    width: 22px;
    height: 22px;
    background: url(images/sprite.png) -24px 0 no-repeat;
}

If this image was important for accessibility, an author may wish to provide a text alternative for the image.

Conversely, https://web.dev/fast/use-imagemin-to-compress-images uses a ligature font (in the "Codelabs" sidebar) to display a themed bullet glyph:

.codelab-cta::before {
    font: normal normal normal 24px/1 "Material Icons";
    font-feature-settings: "liga";
    content: "code";
}

This causes a screen reader user to hear "code" before each codelab title, with no mechanism for a developer to suppress this.

Goals

  1. Allow developers to specify text alternatives for CSS generated content which may be interesting for assistive technology users who may not be able to perceive the content visually.
  2. Allow developers to provide a "no-op" text alternative for CSS generated content which should not be exposed to the accessibility tree.

Proposed solution

Alternative Text for Accessibility is a part of the CSS Generated Content Module Level 3 specification, although it is not yet implemented in any browser.

This feature allows a text alternative to be attached to a content value, by appending a trailing slash to the value followed by the text alternative:

.new::before {
 content: url(./img/star.png) / "New!";
  /* or a localized attribute from the DOM: attr("data-alt") */
}

To apply this to the example from above:

.star::before {
    content: "" / "Star";
    width: 22px;
    height: 22px;
    background: url(images/sprite.png) -24px 0 no-repeat;
}

If the pseudo-element is purely decorative and its function is covered elsewhere, setting alt to the empty string can avoid reading out the decorative element. In this case, the visual indicator is redundant as the collapsed state is expressed elsewhere using ARIA.

.expandable::before {
 content: "\25BA" / "";
/* a.k.a. ► */
 /* aria-expanded="false" already in DOM,
   so this pseudo-element is decorative */
}

Applying this to the earlier example:

.codelab-cta::before {
    font: normal normal normal 24px/1 "Material Icons";
    font-feature-settings: "liga";
    content: "code" / "";
}

Open questions

James Craig raised the issue of backwards compatibility:

Doesn't this break backwards compatibility of the content property? Now web developers would have to duplicate their assignment with and without the slash.

content: "\2730"; /* for legacy UAs */
content: "\2730" / "New!"; /* for newer UAs that recognize the slash syntax */

Considered alternatives

alt property available in pseudo-element styles

This was the previous proposed solution, and is still shipping in Safari as the prefixed property -webkit-alt.

This was objected to as it does not cascade with the content property it applies to.

However, it is certainly easier for developers to understand.

comma instead of slash

Commas are typically used in CSS to separate lists of equivalent items in a collection; slash has been used elsewhere in CSS (typically in shorthands) to denote other relationships between items.

alt() function syntax

This was also proposed by James Craig

Alternately, you could define an alt() syntax to make it more readable:

content: url(example.png), alt("text alternative");

Argument to image() function

Instead of using url() in content, use the proposed image() function, and add an argument to that function to provide alt text.

This would allow specifying one text alternative per image in generated content, and may co-exist with the syntax proposed above.

However, it also would not solve the case where someone would like to provide an alternative string for string content, or for a sequence of generated content.

References & acknowledgements

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment