---
title: "For content"
description: "Headings, link text, alternative text and plain language, checked while you write rather than at audit."
url: "https://opsinjs.pensievelabs.org/accessibility/for-content"
source: "https://opsinjs.pensievelabs.org/accessibility/for-content.md"
section: "Accessibility"
kind: "accessibility"
reviewed: "2026-09-02"
reviewer: "content"
aliases: ["accessible writing", "heading order", "link text"]
---

> Elements written as `<PascalCase … />` below are opsinjs documentation
> components. Their attributes are the content: the values they render are
> generated from `tokens/*.json` and `registry/catalogue.ts` and are
> published separately at https://opsinjs.pensievelabs.org/r/index.json and under the Reference
> section.
> Nothing is missing from this page. The data simply does not live in
> the prose.

<PageTemplate kind="accessibility" />

## What we guarantee [#what-we-guarantee]

Very little, and that is the point of this page. Almost nothing about accessible
writing can be enforced by a component. What the system does provide:

* **A structure that makes correct headings the easy option.** Every page kind in
  these docs has a fixed heading outline, and `assert-ia.mts` fails the build if a
  page invents a heading its kind does not have or skips one it does. That is a
  documentation-site guarantee, not a product guarantee, but it is the same
  discipline we are asking you to apply.
* **A vocabulary you do not have to invent.** The
  [plain-English A to Z](../content/plain-english-a-z.mdx) is the canonical
  clinical-to-plain mapping and is machine-readable, so the same replacement is
  used in your UI, in your help content and in `Term`.
* **Copy rules that are versioned like code.** Everything under
  [Content and language](../content/index.mdx) is part of the system, not a style
  suggestion, and changes to it appear in the changelog.

## What you own [#what-you-own]

**Heading structure.** One `h1` per screen, no skipped levels, and headings that
describe the section rather than decorate it. Screen-reader users navigate by
heading more than by any other mechanism; a screen whose headings read "Overview
/ More / Details" is a screen with no navigation.

**Link text that works out of context.** Assistive technology can list every link
on a page. "Read more", "here" and "click here" are indistinguishable in that
list. Write the destination: "Read how we calculate your range".

**Alternative text for anything that carries data.** A `ScoreDial` is a picture
of a number. A `RangeBar` is a picture of a comparison. Both need a text
equivalent that gives the same answer, and neither is served by
`alt="score dial"`. The method is on
[Alt text and descriptions](../content/alt-text-and-descriptions.mdx).

**Plain language, especially under stress.** A reader who has just been told
their result is outside the expected range has less working memory available than
they had a minute earlier. Reading age is not a vanity metric here. See
[Health literacy](../content/health-literacy.mdx).

**Error and empty copy.** The words in a failure state are accessibility content:
they must say what happened, whether the reader's data is safe, and what to do
next. See [Error and empty messages](../content/error-and-empty-messages.mdx).

## How to check [#how-to-check]

<Steps>
  ### List the links [#list-the-links]

  Extract every link on the screen into a flat list with no surrounding text. If
  two links have the same text and different destinations, or if any entry does not
  say where it goes, rewrite it.

  ### List the headings [#list-the-headings]

  Do the same for headings, in order, with their levels. Read the list aloud. It
  should work as a table of contents for the screen. If it does not, the screen's
  structure is wrong, not just its wording.

  ### Read every number out loud [#read-every-number-out-loud]

  "BP 132/84 mmHg" is read by a screen reader as something close to
  "B P one hundred and thirty two slash eighty four m m h g". Decide whether that
  is acceptable, and if it is not, supply the spoken form. The formatting rules are
  on [Grammar and mechanics](../content/grammar-and-mechanics.mdx) and the clinical
  rules on
  [Numbers, units and precision](../health/numbers-units-precision.mdx).

  ### Cover the picture [#cover-the-picture]

  Hide every chart, dial and icon on the screen and read what remains. If the
  screen no longer answers the question it was built to answer, the missing answer
  is the alternative text you have not written yet.

  ### Check the reading level, then ignore the score [#check-the-reading-level-then-ignore-the-score]

  Run a readability measure over the copy to find the sentences that drag it up,
  then fix those sentences rather than the score. Why the number is a diagnostic
  and not a target is on [Reading level](../content/reading-level.mdx).
</Steps>

## Measured results [#measured-results]

<NoDataYet script="scripts/check-freshness.mts" />

Readability is measured per page rather than per corpus, and no corpus-wide
measurement is published. The freshness report tells you which content pages are
past their review date; it does not score their prose.

## Known gaps [#known-gaps]

* **No readability measurement runs in CI.** `<ReadingLevel>` is a P2 component
  and is not yet implemented, so the check above is manual.
* **The plain-English A to Z is small.** It is authored from scratch, because
  the NHS A to Z is Crown copyright and cannot be reused, so it grows one
  original entry at a time.
* **There is no guidance for translated content,** and the reading-level advice
  here is written for English. See
  [Internationalisation and RTL](../handbook/internationalisation.mdx).

## Updates to this page [#updates-to-this-page]

<Reviewed />
