Latest Post: Why <s>, <del>, and <ins> Don't Speak: Accessible Alternatives for Text-Level Semantics

Why <s>, <del>, and <ins> Don't Speak: Accessible Alternatives for Text-Level Semantics

Learn why HTML elements like <s>, <del>, and <ins> aren't reliably announced by screen readers, and how to enhance their accessibility using CSS pseudo-elements and visually hidden content.

3 min read
The tags <s>, <del>, and <ins> in a background.

Thanks to Nico Bruenjes and this amazing article from Fokus.dev, I learn about this technique to make <s>, <del>, and <ins> accessible to screen readers. It’s a great way to ensure that all users can understand the meaning behind these elements.

Let’s take a deep look at the issue.

The Problem: Silent Semantics

HTML gives us a few handy elements to show changes in content:

  • <del>: Indicates deleted text.
  • <ins>: Indicates inserted text.
  • <s>: Indicates text that is no longer accurate or relevant.

They’re visually styled (usually strikethrough or underline), but most screen readers don’t announce them at all.

🧪 In testing:
  • NVDA (2024.4.2) says “deletion” for <del>

  • VoiceOver (macOS/iOS) and Narrator do not announce <s>,<del>, or <ins> meaningfully

  • <s> is never announced as “struck through” by any major screen reader

A possible fix: Use Pseudo-Elements and Visually Hidden Text

Here’s a technique to make these elements accessible without changing their appearance.

What we’re doing:

  • Add screen-reader-only content using ::before and ::after
  • Keep it visually hidden with CSS clipping
  • Translate if needed with :lang() for localization

CSS Snippet

:where(s, del, ins)::before,
:where(s, del, ins)::after {
  clip-path: inset(100%);
  clip: rect(1px, 1px, 1px, 1px);
  height: 1px;
  width: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  content: '';
}

:where(s)::before {
  content: 'stricken text start ';
}
:where(s)::after {
  content: ' stricken text end';
}

:where(del)::before {
  content: 'deletion start ';
}
:where(del)::after {
  content: ' deletion end';
}

:where(ins)::before {
  content: 'insertion start ';
}
:where(ins)::after {
  content: ' insertion end';
}

Localization Tip

Don’t forget to provide translations for different languages:

:lang(de) :where(s)::before {
  content: 'Durchgestrichener Text Beginn ';
}
:lang(de) :where(s)::after {
  content: ' Durchgestrichener Text Ende';
}

:lang(es) :where(s)::before {
  content: 'Texto tachado inicio ';
}
:lang(es) :where(s)::after {
  content: ' Texto tachado fin';
}

We can try this out with any screen reader now to see how it works:

<p>
  This feature was <del>not included</del> <ins>added later</ins> in the
  release.
</p>
<p>The old name <s>FooApp</s> is now called BarSuite.</p>

This feature was not included added later in the release.

The old name FooApp is now called BarSuite.

With the CSS above, users will now hear:

  • “deletion start not included deletion end”

  • “insertion start added later insertion end”

  • “stricken text start FooApp stricken text end”

WCAG Criteria This Helps With

This technique supports multiple WCAG 2.2 Success Criteria:

  • 1.1.1 Non-text Content: Ensures that all content is accessible, including text that is visually styled but not announced.
  • 1.3.1 Info and Relationships: Ensures that the meaning of the text is conveyed to assistive technologies.
  • 3.1.2 Language of Parts: Ensures pseudo-element content can be understood when localized.
  • 4.1.2 Name, Role, Value: Custom semantics are conveyed properly for interactive/semantic elements

Conclusion

Semantic HTML is great, but only when it’s recognized by assistive technologies. For elements like <s>, <del>, and <ins>, you need a little extra love to make them truly accessible.

Using visually hidden pseudo-elements ensures that all users—not just sighted ones—understand when something has been added, removed, or deprecated.

Keep it inclusive. Keep it semantic. Keep it accessible.

Questions about Semantic Text

ARIA doesn't have a role for 'stricken', 'inserted', or 'deleted' text. It also doesn't override the lack of screen reader support for these tags. Using ARIA alone won't solve the problem.


Share article