Alternative Text and Image Meaning
Provide the information or action an image contributes in its actual context, with equivalent detail and source authority kept visible.
Start with purpose and context
Ask what the image contributes to the current task. A diagram, decorative duplicate, thumbnail action and complex chart require different treatment. The same asset can change purpose when its surrounding text or interaction changes; its filename or visual appearance does not decide its alternative.
Describe the useful meaning for someone who cannot use the pixels. Do not inventory every shape, color or object merely because it is visible. For a source photograph, keep uncertain identity, place, species or cultural interpretation qualified rather than turning a guess into a confident description.
| Purpose | Treatment | Contextual question |
|---|---|---|
| Informative image | A useful short text alternative | What information is needed to understand the nearby content? |
| Decorative or redundant image | An explicit empty alternative on img | Does surrounding text already provide the same useful meaning? |
| Image-only action | Name the action or destination | Could someone activate the control correctly without seeing the icon? |
| Complex image | Short identification plus an accessible detailed equivalent | Which values, relationships or steps does the task require? |
Write a useful short alternative
Put the main information first and use ordinary, direct language. Include details that change the task’s interpretation; leave incidental visual decoration out. A description should not require the reader to know a filename, database code or the designer’s internal shorthand.
Avoid adding a routine “image of” prefix to every alternative. Identify a medium or type when it matters: a drawing versus a source photograph, an annotated map, or an archival document may have different evidence value. Concision is a way to reduce repetition, not a fixed character-count rule.
Keep wording specific enough to be useful without inventing facts. An image can show a visible feature without proving the person’s identity, a plant’s classification or a language authority. Link the source and fuller explanation when those questions matter.
| Need | Useful direction | Weak direction |
|---|---|---|
| An icon-only action | Open example values | Chart icon |
| A layout diagram | Reading content precedes the related actions | A picture with boxes |
| A source photo | Describe the task-relevant visible feature and preserve uncertain identification | An unverified species or person name asserted as fact |
| A comparison chart | State the comparison and provide the exact data nearby | Interesting chart |
| An archival page | Identify the document/context and provide the relevant transcription | A scan of writing |
Length advice is contextual, not an HTML limit
The captured Material Content design chapter recommends 140 characters, while its accessibility-writing best-practices page suggests 125. Preserve that difference as editorial guidance from different pages, rather than inventing one universal platform limit or slicing a source description to a fixed length.
Keep the short alternative focused on the image’s purpose. For complex information, identify the subject and provide a structured detailed equivalent. Verify the actual reader/browser setup instead of assuming that a character counter establishes complete speech or braille output. Neither this lab nor the text-visibility example silently cuts the retained value.
Editorial claims versus analytical exploration
For an editorial chart, make the intended takeaway and the important values supporting it understandable. Keep the takeaway consistent with the source data and nearby explanation. A claim about change needs the relevant baseline and scope.
For exploratory analysis with many possible interpretations, explain the structure, measures and route to investigate instead of presenting one chosen conclusion as the whole chart’s meaning. Provide exact values and source detail in an accessible table or genuinely operable chart. Interactive detail must be reachable without a hover-only tooltip. The original fixture’s shared data table provides a concrete non-pixel route; it is not a general analytical-chart engine.
Captions, nearby text and attribution
A caption is visible context for everyone. It can explain the image’s role, source, date, license or limitations. The alternative should work with that context instead of repeating a long caption verbatim or hiding essential qualifications from one group of readers.
Use an explicit empty alt when an img adds no additional meaning beyond its equivalent nearby content. Omitting the attribute is different and can expose an unhelpful filename or URL. Do not mark an image decorative merely to quiet an accessibility warning when the task still depends on it.
Keep credit and publication permission in the relevant source/caption record. A text alternative is not a permission grant, a replacement for attribution or proof of qualified review.
Working purpose and DOM lab
The example image is an original generated vector fixture. Its bars and visible data table share the same illustrative values. Switch purpose, edit the wording, activate the image-only action and inspect the emitted attributes. Removing a required alternative hides that meaningful specimen until corrected; switching purposes retains the separate drafts.
The lab does not infer the image’s purpose, grade prose with a word list or approve language/cultural meaning. A nonempty alternative can still be inaccurate. Its inspection panel reads real DOM attributes and relationships; a named assistive-technology/browser check is needed for spoken behavior.
Illustrative English interface fixture, not corpus measurements. The same generated image can serve different purposes in different contexts. Choose its purpose deliberately; this tool does not infer meaning or approve wording.
Nonempty text enables the specimen. Presence is a structural check; equivalent meaning still needs contextual review.
Attributes inspected from the rendered preview
This is DOM evidence. It does not predict a screen reader’s exact spoken output or judge whether the wording is a good equivalent.
Charts, maps and other complex images
A short alternative can identify a complex image and direct the reader to the detailed equivalent. Keep the important values, relationships, sequence or spatial explanation available as real text, a structured table or another operable representation. Do not cram a whole data table into one alternative string.
Give the detailed equivalent a meaningful heading or caption and a reachable link. Preserve structure so people can navigate rows, columns or steps. A descriptive paragraph can summarize the point while the table carries exact values; a flattened announcement is not a substitute for a usable data structure.
For a map, decide which geographic relationships and destination actions the task needs. A list of marker names alone may not convey the relationship. Retain locality and source uncertainty rather than silently supplying guessed coordinates or identification.
- Keep the image, summary and detailed values synchronized with the same data/revision.
- Make the detailed equivalent useful to sighted readers as well as assistive-technology users.
- Do not expose an interactive drawing as one named image if its individual controls need to be operated.
- Give meaningful chart boundaries and symbols sufficient contrast; text alternatives do not excuse an unreadable visual version.
Functional images and control names
An image inside a link or button can supply the control’s name when it is the only meaningful content. Name the operation or destination, not the icon’s shape. If visible button text already supplies that name, the companion image is normally decorative in that control.
Keep one coherent name rather than layering an image alternative, a title tooltip and an overriding aria-label with conflicting wording. Preserve the visible wording in the accessible name so voice input can refer to it. Ensure the action, availability and focus return are real.
- Use a native link for a destination and a native button for a local operation.
- Keep the image’s alternative when pixels fail to load; provide a visible recovery when the image is essential to the task.
- Do not put nested links or buttons inside an image-only button.
- Verify exactly one activation, the intended result and a surviving focus destination after dismissal.
<button type="button" onClick={openValues}>
<img src="/example-chart.svg" alt="Open example values" />
</button>
<button type="button" onClick={openValues}>
<img src="/example-chart.svg" alt="" />
Open example values
</button>Text inside images, groups and image type
Prefer real text when you control a label, heading or explanatory diagram. It can reflow, enlarge, translate and participate in native semantics. If meaningful text exists only in an image, provide that information through an accessible equivalent; an ornamental label may have a different role.
For a group that conveys one shared idea, choose a coherent group-level explanation and avoid repetitive announcements for every decorative fragment. For independent informative images, keep their separate meaning and relationships. Do not remove useful distinctions such as an overview versus a detail view.
Mention whether an asset is a photograph, illustration, composite or generated reconstruction when that distinction changes how it should be understood. A generated depiction must not become a purported archival or camera-made source through its alternative text.
Video, motion and changing imagery
A poster image or animation summary can orient a reader, but it does not describe every change in a video. Captioning, transcripts, audio description, playback controls and the task’s moving visual information have separate requirements. Preserve an accessible static or textual explanation when motion is unnecessary to the task.
Keep changing diagrams synchronized with their equivalent values. Announce important task changes concisely; repeatedly replacing a long alternative on every frame can overwhelm reading. Give people time and a means to pause or inspect the relevant state.
- Use a short identification for the media and provide the appropriate full equivalents.
- Do not treat background music, a synthetic voice or a waveform as evidence of an attested pronunciation.
- Keep playback, consent and retention state tied to the actual media record and purpose.
- Honor reduced motion without removing the content or outcome.
Implementation and checked source
The compiled specimen below uses native img semantics, a real button action and a structured values section. Meaningful alternatives must be present before their previews are shown. The decorative case emits alt="" explicitly. Complex output associates a concise summary and links to the separately structured table.
All illustration values come from public/fixtures/alternative-counts.json. The SVG generator creates the bars from that file; its check rejects drift. The fixture is labelled illustrative and contains no language entries or actual corpus metrics.
'use client';
import {useEffect,useId,useRef,useState} from 'react';
import {Button} from '@mobtranslate/ui';
import {CodeBlock} from '../components/code-block';
import fixture from '../public/fixtures/alternative-counts.json';
type Purpose='informative'|'decorative'|'functional'|'complex';
interface Inspection {imagePresent:boolean;alt:string|null;descriptionId:string|null;insideButton:boolean;buttonType:string|null}
const highest=Math.max(...fixture.rows.map(row=>row.value));
const leaders=fixture.rows.filter(row=>row.value===highest).map(row=>row.label).join(', ');
export function AlternativeTextExample() {
const [ready,setReady]=useState(false);
const [purpose,setPurpose]=useState<Purpose>('informative');
const [texts,setTexts]=useState<Record<Purpose,string>>({informative:`Example bars. Highest count: ${highest} (${leaders}).`,decorative:'',functional:'Open example values',complex:'Example counts by group; full values follow.'});
const [valuesOpen,setValuesOpen]=useState(false);
const [inspection,setInspection]=useState<Inspection|null>(null);
const preview=useRef<HTMLDivElement>(null);
const heading=useRef<HTMLHeadingElement>(null);
const id=useId();
const alt=purpose==='decorative'?'':texts[purpose];
const valid=purpose==='decorative'||Boolean(alt.trim());
const summary=fixture.rows.map(row=>`${row.label}: ${row.value}`).join('; ');
useEffect(()=>setReady(true),[]);
useEffect(()=>{
const image=preview.current?.querySelector('img'),button=image?.closest('button');
setInspection({imagePresent:Boolean(image),alt:image?.getAttribute('alt')??null,descriptionId:image?.getAttribute('aria-describedby')??null,insideButton:Boolean(button),buttonType:button?.getAttribute('type')??null});
},[purpose,alt,valid]);
useEffect(()=>{if(valuesOpen)heading.current?.focus();},[valuesOpen]);
const image=<img data-alternative-image src="/fixtures/alternative-counts.svg" width="330" height="180" alt={alt} aria-describedby={purpose==='complex'?`${id}-summary`:undefined} style={{display:'block',width:purpose==='functional'?88:'100%',height:'auto',maxWidth:'100%'}} />;
return <div data-alternative-ready={ready} className="space-y-4">
<p>{fixture.kind}. The same generated image can serve different purposes in different contexts. Choose its purpose deliberately; this tool does not infer meaning or approve wording.</p>
<label htmlFor="alternative-purpose" className="block">Purpose in this context</label>
<select id="alternative-purpose" className="mt-input w-full" disabled={!ready} value={purpose} onChange={event=>{setPurpose(event.target.value as Purpose);setValuesOpen(false);}}>
<option value="informative">Informative image</option><option value="decorative">Decorative or redundant image</option><option value="functional">Image-only action</option><option value="complex">Complex chart with full values</option>
</select>
<label htmlFor="alternative-text" className="block">{purpose==='functional'?'Action name supplied by the image':'Short text alternative'}</label>
<textarea id="alternative-text" className="mt-textarea w-full" disabled={!ready||purpose==='decorative'} value={alt} onChange={event=>setTexts(current=>({...current,[purpose]:event.target.value}))} aria-invalid={!valid} aria-describedby="alternative-help" />
<p id="alternative-help">{purpose==='decorative'?'The actual image uses alt="". Omitting alt is different. The visible text below already supplies the values.':purpose==='functional'?'Name what activation does. The image alternative supplies the native button’s name; no extra aria-label overrides it.':'Nonempty text enables the specimen. Presence is a structural check; equivalent meaning still needs contextual review.'}</p>
{!valid&&<p role="status">Add a text alternative before previewing this meaningful image. Your text in other purposes is retained.</p>}
<div ref={preview} data-alternative-preview>
{!valid?<p>The meaningful-image preview is unavailable until its alternative is present.</p>:purpose==='functional'?<div>
<Button type="button" variant="outline" data-alternative-action onClick={()=>setValuesOpen(true)} disabled={!ready} style={{height:'auto',minHeight:44,padding:12,maxWidth:'100%'}}>{image}</Button>
<p className="mt-2">Activate the image-only button to open the same example values. Its action name comes from the image’s alt attribute.</p>
</div>:<figure style={{background:'var(--color-card)',color:'var(--color-card-foreground)',border:'1px solid var(--color-muted-foreground)',borderRadius:'var(--radius-md)',padding:12}}>
{image}<figcaption className="mt-2">{purpose==='decorative'?`Equivalent nearby text: ${summary}.`:`Example group counts. Left-to-right order: ${fixture.rows.map(row=>row.label).join(', ')}.`}</figcaption>
</figure>}
</div>
{purpose==='complex'&&valid&&<div>
<p id={`${id}-summary`}>Illustrative values: {summary}. Highest count: {highest} ({leaders}).</p>
<a href={`#${id}-values`} className="underline inline-flex items-center min-h-11" onClick={()=>requestAnimationFrame(()=>heading.current?.focus())}>Read the full example values</a>
</div>}
{((purpose==='complex'&&valid)||(purpose==='functional'&&valuesOpen))&&<section aria-labelledby={`${id}-values`} data-alternative-values>
<h3 id={`${id}-values`} ref={heading} tabIndex={-1} className="font-semibold text-xl scroll-mt-24">Full example values</h3>
<table className="w-full mt-3"><caption className="text-start">Illustrative English fixture counts</caption><thead><tr><th scope="col" className="text-start p-2">Group</th><th scope="col" className="text-start p-2">Count</th></tr></thead><tbody>{fixture.rows.map(row=><tr key={row.label}><th scope="row" className="text-start p-2">{row.label}</th><td className="p-2">{row.value}</td></tr>)}</tbody></table>
{purpose==='functional'&&<Button type="button" variant="outline" onClick={()=>{setValuesOpen(false);(preview.current?.querySelector<HTMLButtonElement>('button')??document.getElementById('alternative-text'))?.focus();}}>Close example values</Button>}
</section>}
<div><p className="font-semibold">Attributes inspected from the rendered preview</p><p>This is DOM evidence. It does not predict a screen reader’s exact spoken output or judge whether the wording is a good equivalent.</p>{inspection&&<CodeBlock language="json" code={JSON.stringify(inspection,null,2)} />}</div>
</div>;
}
Verification and editorial review
- Inspect the actual alt attribute: absent, empty and nonempty are different states.
- Check the browser accessibility tree and the intended screen-reader/browser pair. Verify image-only control names and actual keyboard results.
- Read the page with the pixels unavailable: can the same task information and actions be understood?
- For complex content, navigate the table or detailed description independently and compare it with the source values/revision.
- Exercise invalid input, purpose changes, retained drafts and close/focus recovery when a meaningful preview is removed.
- Review whether wording is equivalent, concise in context, qualified and appropriate with the responsible author/reviewer. Structural tests cannot approve cultural authority or semantic adequacy.
- Check both themes, text enlargement, long wording and narrow reflow. Retain attribution, captions and source qualifications.