Writing Accessible Markdown: Headings, Alt Text, and Links for Screen Readers
Quick answer
Accessible Markdown comes down to three habits: a sequential heading hierarchy, real alt text on every meaningful image, and link text that makes sense out of context. This isn't a separate accessibility layer you bolt on afterward — it's the direct result of how Markdown's plain syntax becomes HTML. Get the syntax right, and a screen reader gets a usable document for free.
The rest of this guide walks through each habit, the exact Markdown syntax behind it, and the mistakes that show up most often in real notes, READMEs, and docs.
Step-by-step
Build a sequential heading hierarchy
Screen reader users navigate mostly by jumping between headings, not by reading top to bottom. It's the most common way assistive technology users orient themselves in a document. Markdown's heading syntax maps directly to that structure: one # is an H1, ## is an H2, and so on down to ######.
That mapping is exactly why you can't pick a heading level for how big you want the text to look. Skip a level — an H2 followed by an H4, with no H3 in between — and you break the outline a screen reader relies on, the same way you would in hand-written HTML.
## Setting up the project
### Installing dependencies
### Configuring the environment
## Running the testsThat sequence is navigable — a reader can jump straight to "Running the tests" and know where they are. This one isn't:
## Setting up the project
#### Configuring the environment
## Running the testsIf you're working in Carets, our outlining feature for long Markdown documents is built around exactly this: headings as structure, not a font-size shortcut. The underlying ATX heading syntax — the # style, not the older underline-based Setext style — is what GitHub, CommonMark, and nearly every modern renderer expects.
Write alt text that actually describes the image
GFM's image syntax is . The bracketed text isn't a caption or a label — it's the HTML alt attribute, the entire description a screen reader announces for that image. Leave the brackets empty on an image that carries information, and that information vanishes for anyone who can't see the picture.
Keep the description short. A phrase or one to two sentences does the job. Skip redundant lead-ins like "Image of" or "Screenshot of" — the screen reader already knows it's an image. Capitalize the first word and end with a period, which gives the screen reader a natural pause before moving on.
Empty alt text (![](), which renders as alt="") has a real, narrow use: images that are purely decorative and add nothing if removed, like a divider graphic. Anything that carries actual information — an annotated screenshot, a flowchart, a chart — needs a real description. And if that image shows something your reader genuinely needs to know, say the same thing in the surrounding text too. Don't make an image the only place a fact lives.
Write link text that stands alone
Markdown's link syntax is [link text](url), and the bracketed portion is the only text a screen reader announces for that link — not the destination URL, not the surrounding sentence. Plenty of screen reader users scan a page by jumping from link to link, out of context, specifically to find what they need quickly.
Read the [CommonMark spec](https://spec.commonmark.org) for the full grammar.versus
[Click here](https://spec.commonmark.org) for the full grammar.The second version tells a sighted reader scanning the paragraph where to click. It tells a screen reader user jumping link-to-link nothing. And if a document repeats "click here" for five different links, all five are indistinguishable out of context. This matters just as much for inline versus reference-style links — the syntax you choose only changes how the link is written in source, not what gets announced, so the fix always lives in the bracketed text itself.
Common problems and fixes
- Filename left as alt text.
tells a screen reader user nothing. Go back and write what the image actually shows. - Headings chosen by visual weight. If a long document's headings don't make sense read as a list on their own, the hierarchy needs fixing — not just the formatting.
- Decorative dividers used as headings. A row of emoji or a horizontal rule isn't a heading. Use real heading syntax so it shows up in heading-based navigation.
- One line of alt text on a complex diagram. A flowchart or multi-step diagram needs a short alt-text summary plus a fuller explanation in the body — alt text alone isn't the place to explain something complicated.
Doing this with Carets
Carets is a fast, native notes and code editor for iPhone, iPad, and Mac — Markdown, plain text, and code with syntax highlighting, organized into files, projects, and tags.
Because Carets keeps your Markdown as Markdown, not hidden behind a rich-text toggle, the syntax behind each of these habits stays visible as you write. A heading that jumps from ## to #### is something you'll spot in the raw text, not something buried in a formatting panel. Your files stay plain text, so auditing a document's heading hierarchy, alt text, or link text is just reading the file — and it stays portable if you ever move it somewhere else. Organized into files, projects, and tags, a personal style checklist like this one can live right next to the docs and READMEs it's meant to govern.
To be honest about the trade-off: Carets doesn't run an automated accessibility checker. These are habits you build into how you write, not something a feature enforces for you.
Carets is available for iPhone, iPad, and Mac — find it on the App Store.
Frequently Asked Questions
Does Markdown support alt text for images?
Yes — Markdown's image syntax is ; the bracketed portion renders directly to the HTML alt attribute a screen reader announces. Leave the brackets empty, and the image has no accessible description unless it's genuinely decorative.
Is it OK to skip a heading level in Markdown, like going from an H2 straight to an H4?
No. Screen reader users navigate by jumping between headings, and a skipped level breaks that outline the same way it would in hand-written HTML. Keep heading levels sequential — H2, then H3, then H4, without gaps.
Why is "click here" a problem in Markdown links?
Markdown link syntax [link text](url) exposes only the bracketed text to a screen reader. Many screen reader users scan a page by jumping link to link, so text like "click here" or "read this document" carries no information when heard out of context.
Do empty brackets in image syntax ever make sense?
Yes, for purely decorative images that add nothing if removed. Empty alt text (![]()) tells the screen reader to skip the image entirely rather than announcing a useless filename. Anything carrying real information, including screenshots and diagrams, needs real alt text instead.
Conclusion
Accessible Markdown isn't a separate skill — it's three habits layered on syntax you already use: a sequential heading hierarchy, alt text that actually describes the image, and link text that stands on its own. Each one follows directly from how Markdown becomes HTML, which is exactly why each one is quick to check. Open an older note or README and read just its headings, its alt text, and its link text in isolation. It's usually obvious within a minute whether it would make sense to someone who couldn't see the rest of the page.