Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

UI/UX Design  Module 10 – Content design and UX writing

UX writing: plain language, voice, structure

Write interface text in plain language, keep one voice while the tone follows the moment, put key words first, and know what readability scores miss.

  • Beginner
  • 20 minutes
  • Examples run with Node.js 24.21.0, Python 3.14.8 and Pyodide 314.0.7
  • By MySmartCoPilot
Free lesson, Pro answers: 20 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Write interface text in plain language for the reader's task
  • Define a product voice and choose the tone each moment needs
  • Structure text for scanning, with the key words first in headings, links and buttons
  • Check text with readability, passive-voice and inclusive-language tools, and explain what they miss

Before you start

What you’ll learn · Before you start

What you will learn

  • Write interface text in plain language for the reader's task
  • Define a product voice and choose the tone each moment needs
  • Structure text for scanning, with the key words first in headings, links and buttons
  • Check text with readability, passive-voice and inclusive-language tools, and explain what they miss

Before you start

On this page

MealBox’s notice about pausing a plan, written for this lesson, was one sentence of 43 words, with four passive verbs and the deadline buried in the middle. Rewritten in four moves it says the same thing in 18 words, and it opens with the action and the deadline: “Pause at least 48 hours”.

UX writing: Writing the words of an interface, such as labels, buttons, messages and help, so that people can use the product. It is part of content design. is the work of choosing those words: labels, buttons, messages and help. You will rewrite text in plain language, keep one voice while the tone follows the moment, put the key words first for people who scan, and use readability, passive-voice and inclusive-language checks for what they are good at, knowing what they miss.

Plain language starts from the reader’s task, not from short words

The pause notice failed in a way any reader can feel: by the time the sentence reached “48 hours”, the reader had passed “a temporary suspension of your subscription” and “a request must be submitted by you”. Nothing in it was false. It was written from the company’s side, in the company’s words.

plain language: Writing that its intended readers can find, understand and act on the first time. It is written for their task and knowledge, which can include technical terms, not simplified for an imagined reader. is writing that the intended reader can find, understand and act on the first time. The US Plain Writing Act of 2010 defines plain writing as writing that is “clear, concise, well-organized” and suited to the intended audience. Digital.gov, which publishes the US government’s plain language guides, calls “write for your audience” the first rule, and counts the idea that plain language means dumbing text down among the common myths. Write for what the reader knows and needs to do, which may be technical.

Four moves do most of the work. Use the reader’s words. Say who does what, in the active voice: A sentence whose subject is the person or thing that acts: 'we will send your delivery' rather than 'your delivery will be sent'. It makes clear who does what.; digital.gov notes that the passive can be right in a few cases, such as a step that follows from a law with no one else acting. Put the action first. Cut what the reader skips. Step through them on the pause notice:

Interactive · stage by stage One pause notice, rewritten in four moves Step through the moves. Each box shows the version's words and passive verbs, as the program below counts them.
One pause notice, rewritten in four moves, step 5 of 5. Showing Draft, Reader's words (36 words, 3 passive), Active voice (33 words, 1 passive), Key words first (23 words, no passive), Cut the rest (18 words, no passive). In focus: Cut the rest.Draft43 words, 4 passiveReader's words36 words, 3 passiveActive voice33 words, 1 passiveKey words first23 words, no passiveCut the rest18 words, no passive

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. The draft. "Please be advised that in the event that a temporary suspension of your subscription is required, a request must be submitted by you…" One sentence of 43 words, four passive verbs, and the deadline in the middle.
  2. Use the reader's words. Customers say "pause my plan", not "temporary suspension of my subscription", and "next delivery", not "the scheduled delivery". Swapping in their words cuts 7 words and one passive verb.
  3. Say who does what. "A request must be submitted by you" becomes "you must ask", and "the delivery will be processed and charged" becomes "we will send the delivery and charge you". Each sentence now names the person who acts.
  4. Put the action first. "To pause your plan, ask at least 48 hours before your next delivery." The goal opens the sentence, the opening formula goes, and the warning moves to a second sentence of its own.
  5. Cut what the reader skips. "Pause at least 48 hours before your next delivery, or we send it and charge you as usual." 18 words, 58 % fewer than the draft, and the one fact that matters, 48 hours, is still there.

The program applies the same four moves and counts what each one changed. It flags passive verbs the way digital.gov describes them, a form of “to be” followed by a past participle, and the words that MealBox’s own research found its customers never use:

One notice, four rewrites, counted Python · rewrite/rewrite.py
# One MealBox message rewritten in four moves. For each version the program counts words, the longest sentence, passive
# verbs (a form of "to be" followed by a past participle, the pattern digital.gov describes) and words the team's research
# found customers never use. The message and the word list are invented for this lesson.
import re

VERSIONS = [
    ("Draft", "Please be advised that in the event that a temporary suspension of your subscription is required, "
              "a request must be submitted by you no later than 48 hours prior to the scheduled delivery, otherwise "
              "the delivery will be processed and charged as normal."),
    ("Reader's words", "Please be advised that if you need to pause your plan, a request must be submitted by you at "
                       "least 48 hours before your next delivery, otherwise the delivery will be processed and charged "
                       "as normal."),
    ("Active voice", "Please be advised that if you need to pause your plan, you must ask at least 48 hours before "
                     "your next delivery, otherwise we will send the delivery and charge you as normal."),
    ("Key words first", "To pause your plan, ask at least 48 hours before your next delivery. Otherwise we send the "
                        "delivery and charge you as normal."),
    ("Cut the rest", "Pause at least 48 hours before your next delivery, or we send it and charge you as usual."),
]
NOT_THEIR_WORDS = {"advised", "suspension", "subscription", "submitted", "prior", "scheduled", "processed", "event"}
BE = r"(?:is|are|was|were|be|been|being)"
PARTICIPLE = r"\w+(?:ed|en)"

def words(text):
    return re.findall(r"[A-Za-z0-9']+", text)

def sentences(text):
    return [s for s in re.split(r"(?<=[.!?])\s+", text.strip()) if s]

for name, text in VERSIONS:
    longest = max(len(words(s)) for s in sentences(text))
    passive = re.findall(rf"\b{BE}\s+(?:\w+\s+)?{PARTICIPLE}\b", text, flags=re.IGNORECASE)
    jargon = sorted({w.lower() for w in words(text)} & NOT_THEIR_WORDS)
    print(f"{name}: {len(words(text))} words, longest sentence {longest}")
    print(f"  passive: {', '.join(passive) or 'none'}")
    print(f"  not their words: {', '.join(jargon) or 'none'}")

first, last = len(words(VERSIONS[0][1])), len(words(VERSIONS[-1][1]))
print(f"\n{first} words became {last}, {100 * (first - last) / first:.0f} % fewer, and the deadline survived every move:")
result = all("48 hours" in text for _, text in VERSIONS)
print("48 hours in every version:", result)

Output

Draft: 43 words, longest sentence 43
  passive: be advised, is required, be submitted, be processed
  not their words: advised, event, prior, processed, scheduled, submitted, subscription, suspension
Reader's words: 36 words, longest sentence 36
  passive: be advised, be submitted, be processed
  not their words: advised, processed, submitted
Active voice: 33 words, longest sentence 33
  passive: be advised
  not their words: advised
Key words first: 23 words, longest sentence 13
  passive: none
  not their words: none
Cut the rest: 18 words, longest sentence 18
  passive: none
  not their words: none

43 words became 18, 58 % fewer, and the deadline survived every move:
48 hours in every version: True

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 rewrite.py

The draft carries 43 words, four passive verbs and eight words customers do not say. The last version has 18 words and none of either. The last line of the output matters as much as the others: every version still says 48 hours, so no move cut the one fact the reader needs.

Cutting a fact along with the words

Wrong: “Pause before your next delivery”, which is shorter but drops the deadline, so people pause too late and are charged. Right: “Pause at least 48 hours before your next delivery”. Shorter is the means; the reader acting correctly is the goal, so check that every fact survives each cut.

Checkpoint

Check: Plain language for the reader's task

  1. Question 1 of 2 Ward Desk writes help for council engineers who inspect drains. What does plain language mean for that text?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Writing for what engineers know and need to do, technical terms included where they use them

    The Plain Writing Act defines plain writing as clear, concise, well-organized and suited to the intended audience. For engineers that can include technical terms; for residents it usually does not.

  2. Question 2 of 2 Which rewrite of "Your payment details must be updated before the delivery can be processed" uses the active voice and keeps the meaning?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Update your payment details, and we will send your delivery.

    An active sentence puts the person who acts as its subject. The rewrite must also keep both facts: the details need updating, and the delivery depends on it.

One voice, and a tone for each moment

MealBox once showed “Oops, our bad, lunch is on hold” when a card payment failed. Customers wrote in to ask whether they had been charged. The joke was harmless on a confirmation screen and wrong on a payment failure, although the same writer wrote both in the same voice.

A voice: A product's character in words: its vocabulary, its formality and how it speaks to people. The voice stays the same on every screen, while the tone changes with the moment. is the product’s character in words, and it stays the same everywhere. Apple’s writing guidance starts by asking teams to determine their app’s voice, then to match the tone: How a product's voice speaks at a given moment, such as warm, brief or serious. It moves with the reader's situation along scales such as humour, formality, respectfulness and enthusiasm. to the context: what people are doing in the app and in the world around it. Nielsen Norman Group describes tone along four dimensions, humour, formality, respectfulness and enthusiasm, each a scale rather than a switch. GOV.UK goes further for services: avoid humorous error messages, because people often use a service when they are under stress.

MealBox’s voice is plain, warm and direct. Its tone moves along those dimensions with the moment:

Moment Tone What MealBox says
First delivery booked Warm Your first box arrives tomorrow between 12 and 1.
Payment failed Serious, direct Your bank declined the card. Add another card to keep tomorrow’s lunch.
Plan paused Neutral, brief Plan paused. No deliveries until you restart.
A field left empty Calm, exact Enter a phone number with 10 digits.

The same choice can be made for any message by asking three questions about the moment. Answer them in the table, for the payment failure first and then for the first delivery, and watch which tones still fit:

Interactive · answer and compare Which tone fits this MealBox moment? Answer three questions about the moment you are writing for. The table then says which tones of the voice still fit.
Could the reader be worried, rushed or upset at this moment?
Is money, health or personal data involved in this message?
Will the same person read this text many times, such as a label or a daily status?

Answer the questions above: the table then marks what fits your case and says why the rest does not.

Four tones of one MealBox voice, against four things a moment can ask of them.
Tone Reader under stress Money or data at stake Seen many times Something went well
Playful Sounds like: a joke about lunch Poor a joke reads as not listening when someone is worried or rushed Poor humour next to a failed payment makes people doubt what happened Poor a pun that charms once grates by the tenth time Good a first delivery or a finished plan can carry some fun
Warm Sounds like: a friend who helps Mixed kind words help only if the fix comes first Mixed fine if the facts are exact: amount, date and what to do Mixed keep it short, or the warmth turns into padding Good suits a welcome or a thank-you
Neutral and brief Sounds like: a clear label Good says what happened and what to do, with nothing to read past Good exact and calm: the amount, the card, the next step Good labels and status lines people read daily stay easy to skip Mixed correct, but can feel flat after a big step
Serious and direct Sounds like: careful, exact words Good right for a payment failure or a problem with safety Good names the risk and the action without softening them Poor too heavy for routine text, so people stop reading it Poor sounds like a warning when nothing is wrong
How the answers decide
  • “Could the reader be worried, rushed or upset at this moment?” Yes, it may be a bad moment: rules out Playful and adds a caveat to Warm. Someone who is worried wants to know what happened and what to do. A joke reads as not listening, and warmth helps only after the fix is clear.
  • “Is money, health or personal data involved in this message?” Yes, something is at stake: rules out Playful. Where money, health or data is at stake, people need exact facts: what happened, how much, and the next step. Humour makes them doubt the message.
  • “Will the same person read this text many times, such as a label or a daily status?” Yes, it is routine text: rules out Serious and direct and adds a caveat to Playful and Warm. Routine text is read many times. Heavy words make people stop reading it, and charm wears out, so keep it brief.
  • “Could the reader be worried, rushed or upset at this moment?” No, nothing is wrong and “Is money, health or personal data involved in this message?” No, nothing is at stake and “Will the same person read this text many times, such as a label or a daily status?” No, it appears once or rarely: adds a caveat to Serious and direct. With nothing wrong and nothing at stake, a serious tone sounds like a warning. A rare happy moment can be warm or even playful.

A payment failure rules out the playful tone twice: the reader may be worried and money is at stake. A rare happy moment leaves every tone open, with a caveat on the serious one, which sounds like a warning when nothing is wrong. Routine text, such as a status shown every day, keeps to neutral and brief.

Key idea

The voice says who is speaking and never changes; the tone says how they speak right now, and the reader’s moment decides it.

Checkpoint

Check: One voice, a tone per moment

  1. Question 1 of 2 A MealBox customer's refund has failed twice. Which message fits the moment?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: We could not refund 450 rupees to your card. We will try again tonight, or you can choose a bank transfer.

    The reader may be worried and money is at stake, so the playful tone is out and warmth only helps after the facts. The best message names what happened, how much, and what comes next.

  2. Question 2 of 2 What stays the same across MealBox's welcome screen, its payment errors and its daily status lines?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The voice

    Apple's guidance asks teams to determine the app's voice first and then match the tone to the context, which is why one voice can have many tones.

Readers scan, so the key words go first

Ward Desk’s help page listed links such as “Click here to report a broken streetlight” and “Learn more”. None of its eight links started with the word a resident would scan for, so someone looking for streetlights could not tell the links apart by their first words. GOV.UK’s guidance for services is blunt about why that fails: people scan rather than read, especially in a task, so put the important words first and drop the words they do not need.

Nielsen Norman Group measured how little a scan takes in. Its test gave people only the first 11 characters of each link, about two words, which is how much of a list item a scanning reader usually sees. Screen reader users scan too, by structure: in WebAIM’s eleventh survey of screen reader users, with 1,780 responses, 67.8 % said they move through the headings first when looking for information on a long page, and 88.3 % found heading levels very or somewhat useful. The sample was not controlled, so take the numbers as a strong signal, not a census. GOV.UK adds that screen reader users often hear a list of links on its own, so “click here” tells them nothing.

front-loading: Putting the words a reader is looking for at the start of a heading, link, button or sentence, because people scanning a page read only the first words of each item. means putting the word the reader is scanning for at the start of a heading, link or button. The program checks eight Ward Desk links before and after a rewrite, using the same 11-character lead:

The first 11 characters of eight Ward Desk links Python · front_load/front_load.py
# What a scanning reader gets from the start of each Ward Desk link: its first 11 characters, about two words, the size
# of the lead Nielsen Norman Group tested. The links and their key words are invented for this lesson.
LINKS = [
    # (before, after, the word a resident is scanning for)
    ("Click here to report a broken streetlight", "Streetlight broken: report it", "streetlight"),
    ("Information about checking the status of a complaint", "Complaint status", "complaint"),
    ("If you want to change your contact details, go here", "Contact details: change them", "contact"),
    ("Frequently asked questions about blocked drains", "Blocked drains: questions", "drains"),
    ("Please read our guidance before uploading photos", "Photos: size and format rules", "photos"),
    ("Learn more", "Rubbish collection days", "rubbish"),
    ("Our commitment to accessibility", "Accessibility statement", "accessibility"),
    ("Ward Desk form for reporting water supply problems", "Water supply: report a problem", "water"),
]
LEAD = 11

def found_in_lead(text, word):
    return word in text[:LEAD].lower() or text.lower().startswith(word[:LEAD])

hits_before = hits_after = 0
for before, after, word in LINKS:
    b, a = found_in_lead(before, word), found_in_lead(after, word)
    hits_before += b
    hits_after += a
    print(f"{word}:")
    print(f"  before  '{before[:LEAD]}'  {'found' if b else 'missing'}")
    print(f"  after   '{after[:LEAD]}'  {'found' if a else 'missing'}")

print(f"\nKey word inside the first {LEAD} characters: {hits_before} of {len(LINKS)} before, {hits_after} of {len(LINKS)} after")
lengths = [len(after) for _, after, _ in LINKS]
summary = f"Rewritten links: {min(lengths)} to {max(lengths)} characters"
print(summary)

Output

streetlight:
  before  'Click here '  missing
  after   'Streetlight'  found
complaint:
  before  'Information'  missing
  after   'Complaint s'  found
contact:
  before  'If you want'  missing
  after   'Contact det'  found
drains:
  before  'Frequently '  missing
  after   'Blocked dra'  missing
photos:
  before  'Please read'  missing
  after   'Photos: siz'  found
rubbish:
  before  'Learn more'  missing
  after   'Rubbish col'  found
accessibility:
  before  'Our commitm'  missing
  after   'Accessibili'  found
water:
  before  'Ward Desk f'  missing
  after   'Water suppl'  found

Key word inside the first 11 characters: 0 of 8 before, 7 of 8 after
Rewritten links: 16 to 30 characters

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 front_load.py

No old link puts its key word in the lead; seven of the eight rewrites do. The one miss is instructive: “Blocked drains” reads well, yet the scan stops at “Blocked dra”, before the word residents look for.

Fix the last link

Press Edit, change “Blocked drains: questions” to “Drains: blocked or flooded” and run it again. The count reaches 8 of 8, and the link still says what the page covers.

The same rule gives a whole page its structure, with the key information at the top: one idea per sentence, headings that describe what follows, and lists for steps or choices, which digital.gov recommends for detail that would otherwise overload readers. Write the real words before the layout is fixed. W3C’s article on text size in translation shows that translated text is usually longer than English, and that the shorter the source, the larger the expansion can be, which is the text expansion: The tendency of text to grow in length when translated, often most for short source strings, so a label that fits in one language may overflow in another. a layout must leave room for.

Checkpoint

Check: Key words first for scanning

  1. Question 1 of 2 A resident scans Ward Desk's help links for one about potholes. Which link puts the key word inside the first 11 characters?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Potholes: report one

    Nielsen Norman Group's test used the first 11 characters, about two words. A link that starts with the word the reader scans for passes; one that starts with a verb, a filler word or "Click here" does not.

  2. Question 2 of 2 Why is "Learn more" a weak link for screen reader users in particular?
    Show the answer: Question 2 of 2

    Answer: They often hear the links of a page as a list on their own, and every "Learn more" sounds the same

    A link out of context has to say where it goes. "Rubbish collection days" works alone; "Learn more" does not.

Readability scores estimate difficulty; readers measure it

A MealBox manager asked for a number to prove the refund help was easier after its rewrite. A readability formula: A formula that estimates how hard a text is to read from counts such as words per sentence and syllables per word. It cannot see meaning, order or accuracy. gives one, such as Rudolph Flesch’s 1948 Flesch reading ease: Rudolph Flesch's 1948 score: 206.835 minus 1.015 times the words per sentence minus 84.6 times the syllables per word. Higher means easier; English text only.. It reads only two things: how long the sentences are and how long the words are.

ease=206.835−1.015×wordssentences−84.6×syllableswords\text{ease} = 206.835 - 1.015 \times \frac{\text{words}}{\text{sentences}} - 84.6 \times \frac{\text{syllables}}{\text{words}}

In words: start from 206.835, take away about one point for each word in an average sentence, and 84.6 points for each syllable in an average word. A passage of 10-word sentences with 1.5 syllables a word scores 206.835 − 10.15 − 126.9 = 69.8. Higher is easier, and the Flesch–Kincaid grade turns the same two ratios into a US school grade. The program scores five MealBox texts before and after rewriting, with syllables estimated from vowel groups:

Reading ease and grade for five MealBox texts Python · readability/readability.py
# Flesch Reading Ease (Flesch 1948) and the Flesch-Kincaid grade for five MealBox messages, before and after a rewrite.
# Syllables are estimated by counting vowel groups, so scores can differ by a few points from a tool that uses a
# dictionary. The messages are invented for this lesson.
import re

PAIRS = [
    ("Paused plan",
     "Your subscription has been temporarily suspended pending verification of your payment information.",
     "We paused your plan. Check your card details to restart it."),
    ("Delivery change",
     "Modifications to delivery preferences are effective from the subsequent delivery cycle.",
     "Changes start from your next delivery."),
    ("Wrong code",
     "An authentication failure occurred. Please reinitiate the verification procedure.",
     "That code did not work. Ask for a new code."),
    ("Address check",
     "Kindly ensure that the delivery address provided is accurate and complete prior to confirmation.",
     "Check your address before you confirm."),
    ("Refund help",
     "In order to facilitate the efficient processing of your refund request, it is necessary that the relevant "
     "order reference number be provided. This information can be located within the confirmation communication "
     "that was dispatched to your registered email address at the time of purchase. Requests lacking this "
     "information will not be processed.",
     "To get a refund, give us your order number. You can find it in the confirmation email we sent when you "
     "ordered. We cannot refund an order without it."),
]

def syllables(word):
    w = word.lower()
    if not w.isalpha():
        return 1
    groups = len(re.findall(r"[aeiouy]+", w))
    if w.endswith("e") and not w.endswith(("le", "ee")) and groups > 1:
        groups -= 1
    if w.endswith(("es", "ed")) and not w.endswith(("ted", "ded", "ses", "zes", "ces", "ges")) and groups > 1:
        groups -= 1
    return max(1, groups)

def scores(text):
    sents = [s for s in re.split(r"(?<=[.!?])\s+", text.strip()) if s]
    words = re.findall(r"[A-Za-z0-9']+", text)
    syl = sum(syllables(w) for w in words)
    wps, spw = len(words) / len(sents), syl / len(words)
    ease = 206.835 - 1.015 * wps - 84.6 * spw
    grade = 0.39 * wps + 11.8 * spw - 15.59
    return ease, grade, len(words)

for name, before, after in PAIRS:
    eb, gb, nb = scores(before)
    ea, ga, na = scores(after)
    print(f"{name}: ease {eb:.1f} -> {ea:.1f}, grade {gb:.1f} -> {ga:.1f}, words {nb} -> {na}")

text = PAIRS[1][2]
shuffled = " ".join(reversed(text.rstrip(".").split())) + "."
print(f"\nSame words, reversed: '{shuffled}'")
same = scores(text)[0] == scores(shuffled)[0]
print(f"Ease {scores(text)[0]:.1f} and {scores(shuffled)[0]:.1f}: the formula cannot tell them apart ({same})")

Output

Paused plan: ease -9.8 -> 101.3, grade 17.6 -> 0.5, words 12 -> 11
Delivery change: ease -27.4 -> 59.7, grade 19.8 -> 6.4, words 11 -> 6
Wrong code: ease -13.9 -> 117.2, grade 16.3 -> -1.8, words 9 -> 10
Address check: ease 23.4 -> 73.8, grade 13.5 -> 4.5, words 14 -> 6
Refund help: ease 29.8 -> 77.4, grade 13.4 -> 4.9, words 52 -> 29

Same words, reversed: 'delivery next your from start Changes.'
Ease 59.7 and 59.7: the formula cannot tell them apart (True)

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 readability.py

The refund help rose from 29.8 to 77.4 and fell from 52 to 29 words, the kind of passage the formula was made for. The one-line strings show its limits. Their scores run off both ends of the scale, from −27.4 to 117.2, and “Changes start from your next delivery”, as plain as a sentence gets, scores 59.7 because one four-syllable word weighs heavily in six words. The last line is the deepest limit: the same words in reverse order score exactly the same, so the formula cannot see order, meaning or accuracy. Its weights were also fitted to English text, so the score means nothing for a Hindi string.

inclusive language: Words that do not exclude or demean people, avoiding ableist phrases, gendered defaults and idioms that many readers will not understand or that will not translate. checks have a similar shape. They flag the kinds of words Apple’s inclusion guidance warns about: idioms that will not translate, phrases that use a disability to mean something bad, such as “blind to” or “crazy”, and gendered defaults, where GOV.UK suggests “they” instead of “he or she”. A flag is a question for a person, not a verdict. MySmartCoPilot’s Readability Checker, Passive Voice Checker and Inclusive Language Checker each run one such check on your own text.

What measures clarity is a reader. Digital.gov describes paraphrase testing for short pages, where a person says in their own words what the text means, and usability testing for longer content and forms. It asks teams to start testing early, revise and test again, at least twice.

Key idea

A readability score is a cheap first check on sentence and word length; whether a reader understands and acts correctly is measured only by testing with readers.

Checkpoint

Check: What readability scores and checks measure

  1. Question 1 of 2 A passage averages 15 words a sentence and 1.4 syllables a word. What is its Flesch reading ease, to one decimal place?

    Type a number.

    A hint

    206.835 − 1.015 × 15 − 84.6 × 1.4.

    Show the answer: Question 1 of 2

    Answer: 73.2 points (anything from 73.1 to 73.3 counts)

    1.015 × 15 = 15.225 and 84.6 × 1.4 = 118.44, so 206.835 − 15.225 − 118.44 = 73.17, which rounds to 73.2. Shorter sentences or shorter words would raise it.

  2. Question 2 of 2 The program reversed the words of "Changes start from your next delivery" and got the same score, 59.7. What does that show?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: The formula counts sentences, words and syllables, so it cannot see order or meaning

    A readability formula is a function of two averages. Anything that keeps the words and the sentences, such as a reordered, wrong or misleading text, keeps the score.

Practise

Ward Desk’s help page about reporting a streetlight needs the treatment this lesson describes. Rewrite its heading, its paragraphs and five interface strings so that the sample tests pass: the same simple counts as the examples, plus limits for each kind of string.

Exercise · Easy · Python

Rewrite a Ward Desk help page and five strings

Ward Desk's help page about reporting a broken streetlight is in solution.py: a heading, two paragraphs and five interface strings. Rewrite the text so that:

  1. Facts: every phrase in FACTS still appears in the heading or the paragraphs.
  2. Plain paragraphs: no sentence is longer than 20 words, no sentence uses a passive verb (a form of "to be" followed by a word ending in -ed or -en), and the paragraphs together score at least 60 on Flesch reading ease, counted the way the lesson's example counts it.
  3. Key words first: the heading is at most 60 characters and does not start with a filler word such as "Information", "About" or "Welcome".
  4. Strings: buttons and error messages start with a verb that names the action (see ACTION_VERBS in the tests); buttons are at most 24 characters, labels at most 30, links at most 40 and errors at most 80; no link says only "click here", "learn more", "here" or "read more".
  5. No flagged words: none of the phrases in FLAGGED in the tests appears anywhere.

Keep the five strings in their order and with their kinds. Change only the text.

Starter code · solution.py

"""
Ward Desk's help page for reporting a broken streetlight, and five interface strings, written for this exercise.
Rewrite HEADING, PARAGRAPHS and the text of each string in STRINGS so that the sample tests pass.
Keep every phrase of FACTS somewhere in the heading or the paragraphs.
"""

FACTS = ["24 hours", "pole number", "photo"]

HEADING = "Information regarding the procedure for the reporting of streetlight faults"

PARAGRAPHS = [
    "In the event that a streetlight in your area is observed to be non-functional, a report may be submitted "
    "through Ward Desk, and it is requested that the pole number, which is located on a metal plate affixed to "
    "the pole, be included in the report.",
    "Reports that are received will be processed by the electrical department within 24 hours, and residents are "
    "encouraged to attach a photo, which will facilitate the identification of the fault by maintenance personnel.",
]

# (kind, text): kind is one of button, link, error, label
STRINGS = [
    ("button", "Click here to submit your report"),
    ("button", "Proceed"),
    ("link", "Learn more"),
    ("error", "Invalid input. Please try again"),
    ("label", "Pole identification number (as displayed on the pole)"),
]
The sample tests · test_solution.py
"""Sample tests for the rewrite-ward-desk-help exercise. The counts match the lesson's examples."""

import re

from solution import FACTS, HEADING, PARAGRAPHS, STRINGS

KINDS = ["button", "button", "link", "error", "label"]
LIMITS = {"button": 24, "label": 30, "link": 40, "error": 80}
ACTION_VERBS = {"add", "call", "cancel", "change", "check", "choose", "edit", "enter", "find", "give", "pause",
                "remove", "report", "restart", "save", "send", "upload"}
FILLER_STARTS = {"information", "about", "welcome", "introduction", "click", "please", "the", "a", "an"}
VAGUE_LINKS = {"click here", "learn more", "here", "read more"}
FLAGGED = ["click here", "please be advised", "kindly", "simply", "obviously", "invalid", "crazy", "insane",
           "lame", "dumb", "he or she", "guys"]
BE = r"(?:is|are|was|were|be|been|being)"


def syllables(word):
    w = word.lower()
    if not w.isalpha():
        return 1
    groups = len(re.findall(r"[aeiouy]+", w))
    if w.endswith("e") and not w.endswith(("le", "ee")) and groups > 1:
        groups -= 1
    if w.endswith(("es", "ed")) and not w.endswith(("ted", "ded", "ses", "zes", "ces", "ges")) and groups > 1:
        groups -= 1
    return max(1, groups)


def sentences(text):
    return [s for s in re.split(r"(?<=[.!?])\s+", text.strip()) if s]


def words(text):
    return re.findall(r"[A-Za-z0-9']+", text)


def ease(text):
    sents, ws = sentences(text), words(text)
    return 206.835 - 1.015 * len(ws) / len(sents) - 84.6 * sum(syllables(w) for w in ws) / len(ws)


def test_every_fact_survives():
    page = (HEADING + " " + " ".join(PARAGRAPHS)).lower()
    missing = [f for f in FACTS if f.lower() not in page]
    assert not missing, f"facts missing from the page: {missing}"


def test_sentences_of_20_words_or_fewer():
    long = [s for p in PARAGRAPHS for s in sentences(p) if len(words(s)) > 20]
    assert not long, f"{len(long)} sentence(s) over 20 words, the first: '{long[0][:60]}…'" if long else ""


def test_no_passive_verbs():
    found = [m.group(0) for p in PARAGRAPHS for m in re.finditer(rf"\b{BE}\s+(?:\w+\s+)?\w+(?:ed|en)\b", p, re.I)]
    assert not found, f"passive verbs: {found}"


def test_reading_ease_at_least_60():
    score = ease(" ".join(PARAGRAPHS))
    assert score >= 60, f"reading ease {score:.1f}, below 60"


def test_heading_puts_the_key_word_first():
    assert len(HEADING) <= 60, f"heading is {len(HEADING)} characters"
    first = words(HEADING)[0].lower()
    assert first not in FILLER_STARTS, f"the heading starts with '{first}'"


def test_strings_keep_their_kinds():
    assert [k for k, _ in STRINGS] == KINDS, "keep the five strings in their order and with their kinds"


def test_string_lengths():
    over = [(k, t, len(t)) for k, t in STRINGS if len(t) > LIMITS[k]]
    assert not over, f"over the limit for its kind: {over}"


def test_buttons_and_errors_start_with_an_action():
    for kind, text in STRINGS:
        if kind in ("button", "error"):
            first = words(text)[0].lower()
            assert first in ACTION_VERBS, f"{kind} '{text}' starts with '{first}', not an action verb"


def test_links_say_where_they_go():
    vague = [t for k, t in STRINGS if k == "link" and t.strip(" .").lower() in VAGUE_LINKS]
    assert not vague, f"links that say nothing out of context: {vague}"


def test_no_flagged_words():
    everything = " ".join([HEADING, *PARAGRAPHS, *(t for _, t in STRINGS)]).lower()
    hits = [f for f in FLAGGED if re.search(rf"\b{re.escape(f)}\b", everything)]
    assert not hits, f"flagged: {hits}"
A hint

Start with the paragraphs. Split each long sentence into two or three, and give each one a person who acts: "Report a broken streetlight", "The electrical team visits", "Add a photo". Then check that 24 hours, the pole number and the photo are all still there.

The sample tests run on this device, in your browser (Pyodide): nothing is sent to mysmartcopilot.com. The first run downloads Python (about 13.5 MB), which is kept for the next runs. A check in your browser is feedback for you, not proof that the code is right for every input.

Then take the questions, which start from the idea you have answered least well:

Practice that adapts to you

Practise this lesson

13 questions about 4 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 13 How does the US Plain Writing Act of 2010 define plain writing?

    Choose one answer.

    Show the answer: Question 1 of 13

    Answer: Clear, concise, well-organized writing suited to the intended audience

    The definition is about the reader: clear, concise, well-organized and following practices suited to the field and the intended audience.

  2. Question 2 of 13 The pause notice went from 43 words to 18. By what percentage did the word count fall, to the nearest whole number?

    Type a number.

    A hint

    Divide the words removed by the words in the draft.

    Show the answer: Question 2 of 13

    Answer: 58 % (anything from 57.5 to 58.5 counts)

    43 − 18 = 25 words removed, and 25 ÷ 43 = 0.581, so 58 % fewer, as the program prints.

  3. Question 3 of 13 A writer cuts MealBox's refund notice from 31 words to 9, and the new version leaves out the 5-day wait for the money. Is the rewrite better?

    Choose one answer.

    Show the answer: Question 3 of 13

    Answer: No, because the reader no longer knows when to expect the money, so the cut removed a fact they need

    The lesson's program checks that 48 hours survives every move for this reason: each cut has to keep every fact the reader needs to act.

  4. Question 4 of 13 Which of these are among Nielsen Norman Group's four dimensions of tone of voice?

    Choose every answer that is right.

    Show the answer: Question 4 of 13

    Answer:

    • Enthusiasm
    • Formality
    • Humour

    The four dimensions are humour, formality, respectfulness and enthusiasm, each a scale on which a piece of copy can sit anywhere.

  5. Question 5 of 13 Why does GOV.UK advise against humorous error messages in services?

    Choose one answer.

    Show the answer: Question 5 of 13

    Answer: People often use services for serious things or when they are under stress

    Tone follows the reader's moment. An error usually means something has gone wrong for the reader, so the tone is calm and exact.

  6. Question 6 of 13 A new MealBox writer drafts the daily delivery status "Woohoo, your lunch is zooming over!" for every order. Using the tone table, what is the problem?

    Choose one answer.

    Show the answer: Question 6 of 13

    Answer: Routine text seen many times wears out playful charm, so a daily status should be neutral and brief

    The moment decides the tone. A line people read every day should be quick to read and easy to skip, such as "On its way. Arrives 12:30 to 1:00."

  7. Question 7 of 13 How many characters of each link did Nielsen Norman Group show people in its test of how scanning readers understand links?

    Type a number.

    Show the answer: Question 7 of 13

    Answer: 11 characters

    The test showed the first 11 characters, about two words, which is how much of a list item a scanning reader usually takes in.

  8. Question 8 of 13 In WebAIM's eleventh survey of screen reader users, what did most respondents say they do first to find information on a long page?

    Choose one answer.

    Show the answer: Question 8 of 13

    Answer: Navigate through the headings

    Headings are how most screen reader users find information, so a heading must say what the section holds. The sample was not controlled, so the figure is a strong signal rather than a census.

  9. Question 9 of 13 A Ward Desk button reads "Click here to continue to the next step of your complaint". What would you change, and why?

    Choose one answer.

    Show the answer: Question 9 of 13

    Answer: Name the action in a few words, such as "Add photos", so the button says what comes next

    The first words of a button carry its meaning. Front-loading means starting with the action the reader is looking for.

  10. Question 10 of 13 What two things does the Flesch reading ease formula measure?

    Choose one answer.

    Show the answer: Question 10 of 13

    Answer: Average sentence length in words and average word length in syllables

    The score starts at 206.835 and takes away points for long sentences and long words, which is why it can only estimate difficulty.

  11. Question 11 of 13 The one-line MealBox strings scored from −27.4 to 117.2. What should a team take from that?

    Choose one answer.

    Show the answer: Question 11 of 13

    Answer: The formula gives unreliable numbers on very short strings, so test those with readers instead

    A score is an average over the text. With six words, one long word moves it by many points, so a team uses scores on passages and tests short strings with readers.

  12. Question 12 of 13 MealBox's message "Refund unsuccessful. Error code R-22." has no passive verb and no word an inclusive-language check flags. What do the two clean results tell you?

    Choose one answer.

    Show the answer: Question 12 of 13

    Answer: Only that those two patterns are absent; whether a customer knows what to do next takes a reader to show

    A passive-voice check looks for a form of "to be" followed by a past participle, and an inclusive-language check looks for listed words. A message can avoid both and still leave the reader stuck, which only a paraphrase or usability test shows.

  13. Question 13 of 13 MealBox launches in Hindi and a manager asks for Flesch scores of the Hindi strings. What do you say?

    Choose one answer.

    Show the answer: Question 13 of 13

    Answer: The formula's weights were fitted to English text, so its score means nothing for Hindi; test the Hindi strings with Hindi-speaking readers

    A formula fitted to one language is not a measure in another. Paraphrase testing, where readers say in their own words what the text means, works in every language.

Interview questions

Warm-up: how do voice and tone differ in interface writing?

Voice is who the product is in words: its vocabulary, how formal it is, whether it says “we” and “you”. It stays the same on every screen, so the product sounds like one thing. Tone is how that voice speaks at a given moment, and it moves with the reader’s situation: lighter for a first delivery, brief for a routine status, serious and exact for a failed payment. A useful way to show it is a chart with one voice and a few moments, each with its tone and an example line, because a team can then check a new message against it instead of arguing about taste.

Warm-up: why put the important words first in a heading, link or button?

Because people scan. They read the start of each heading or link and decide from that whether to keep reading, and a screen reader user who moves through a list of links or headings hears each one out of context. If the start is “Click here” or “Information about”, every item begins the same and the reader learns nothing. Starting with the word they are looking for, such as “Streetlight broken: report it”, lets the eye or the ear stop at the right item.

Two harder questions follow. Decide what you would want to know before changing a single word, then open either:

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Mid to staff

    MealBox's release pipeline blocks any interface string scoring under 70 on Flesch reading ease. Its first run blocks "Changes start from your next delivery" and 140 other strings, most of them a single line. The product manager still wants a quality gate. What should it check instead, and how would you show that it works?

    Model answer, Pro. First step and follow-ups

Flashcards · 8 cards

Recall it, then check

Say the answer to yourself before you look: recalling it is what makes it stick.

  1. What is plain language?

    Writing that the intended reader can find, understand and act on the first time. It is written for what the reader knows and needs to do, which may be technical, so it is not dumbing text down.

  2. Which four moves do most of the work of plain language?

    Use the reader's words, say who does what in the active voice, put the action first, and cut what the reader skips. Then check that every fact survives the cuts: a shorter pause notice that drops the 48-hour deadline gets people charged.

  3. What is the difference between a product's voice and its tone?

    The voice is the product's character in words and stays the same everywhere. The tone is how it speaks right now, and the reader's moment decides it: never playful when someone may be worried or money is at stake.

  4. Along which four dimensions does Nielsen Norman Group describe tone?

    Humour, formality, respectfulness and enthusiasm, each a scale rather than a switch. GOV.UK adds that services avoid humorous error messages, because people often use a service under stress.

  5. What is front-loading, and why does it matter?

    Putting the word the reader is scanning for at the start of a heading, link or button. People scan rather than read, and a scanning reader usually takes in only about the first 11 characters of a link, about two words.

  6. What does a readability formula such as Flesch reading ease measure?

    Only how long the sentences are and how long the words are; higher is easier, and 10-word sentences of 1.5 syllables a word score 69.8. It cannot see order, meaning or accuracy: the same words in reverse order score exactly the same.

  7. Where are readability scores unreliable?

    On one-line strings, whose scores run off both ends of the scale, and on other languages, because the weights were fitted to English text. A score means nothing for a Hindi string.

  8. What measures whether interface text is clear?

    Readers. Paraphrase testing asks a person to say in their own words what a short text means, and usability testing covers longer content and forms; test early, revise and test again, at least twice. A flag from a checker is a question for a person, not a verdict.

Key takeaways

  • Plain language is written for the reader’s task and knowledge, using their words, the active voice, the action first and no words they would skip, and every fact survives the cuts.
  • A product has one voice everywhere, and its tone moves with the reader’s moment: never playful when someone is worried or money is at stake.
  • Readers scan headings, links and buttons by their first words, so the word they are looking for goes first, and link text makes sense on its own.
  • Readability formulas count only sentence and word length, so they cannot see order, meaning or accuracy, and they are unreliable on one-line strings and other languages.
  • Tools flag candidates for a person to judge, and paraphrase and usability tests with readers measure whether the words work.

Terms in this lesson

active voice
A sentence whose subject is the person or thing that acts: 'we will send your delivery' rather than 'your delivery will be sent'. It makes clear who does what.
Flesch reading ease
Rudolph Flesch's 1948 score: 206.835 minus 1.015 times the words per sentence minus 84.6 times the syllables per word. Higher means easier; English text only.
front-loading
Putting the words a reader is looking for at the start of a heading, link, button or sentence, because people scanning a page read only the first words of each item.
inclusive language
Words that do not exclude or demean people, avoiding ableist phrases, gendered defaults and idioms that many readers will not understand or that will not translate.
plain language
Writing that its intended readers can find, understand and act on the first time. It is written for their task and knowledge, which can include technical terms, not simplified for an imagined reader.
readability formula
A formula that estimates how hard a text is to read from counts such as words per sentence and syllables per word. It cannot see meaning, order or accuracy.
tone
How a product's voice speaks at a given moment, such as warm, brief or serious. It moves with the reader's situation along scales such as humour, formality, respectfulness and enthusiasm.
UX writing
Writing the words of an interface, such as labels, buttons, messages and help, so that people can use the product. It is part of content design.
voice
A product's character in words: its vocabulary, its formality and how it speaks to people. The voice stays the same on every screen, while the tone changes with the moment.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.