Markdown Small Text: Subscript, Superscript and Font Size (2026)
TL;DR: Markdown has no font-size syntax at all, in any version. To make text smaller you drop into HTML:
<small>for fine print,<sub>and<sup>for subscript and superscript. Two things that look like they should work do not —<span style="font-size:10px">is stripped by GitHub's sanitizer and by MacMD Viewer's, andH~2~Orenders as a struck-through 2 rather than a subscript, because the single tilde belongs to strikethrough.
Markdown small text is one of those features people assume exists because every other formatting option does. It does not. There is no #size, no {small}, no font-size directive anywhere in the specification — and the workarounds that circulate most widely are the two that fail silently on the platform most readers are actually targeting.
This guide covers the tags that do work, why the inline-CSS trick does not, the subscript syntax collision that turns chemistry formulas into strikethrough, a platform support table, and the three anti-patterns worth refusing. Every rendering claim about MacMD Viewer here was checked against the shipped v1.5.1 source, including the ones that make the app look bad.
How Do You Make Small Text in Markdown?
Wrap the text in an HTML <small> tag. There is no Markdown syntax for it, so raw HTML is the route:
Buy now for $19.99. <small>Prices exclude VAT.</small>Renders as: Buy now for $19.99. Prices exclude VAT.
This works because Markdown parsers pass inline HTML through to their output rather than escaping it. It is the same mechanism behind Markdown comments and collapsible sections — features that feel like Markdown but are really HTML wearing a Markdown coat.
The three tags that carry the whole feature
<small>— side comments and fine print: disclaimers, legal text, attributions. The browser's default stylesheet renders it at roughly 80% of the surrounding text.<sub>— subscript. Chemistry (H<sub>2</sub>O), footnote markers, index notation.<sup>— superscript. Exponents (E = mc<sup>2</sup>), ordinals, reference numbers.
All three carry meaning, not just size. <small> says "this is secondary", which is why it is a better choice than a shrunken <span> even in places where both would render. If what you want is emphasis rather than de-emphasis, Markdown already has native syntax for that — see the bold guide.
Why Markdown Has No Font Size Syntax
Because the specification deliberately stops before presentation. CommonMark 0.31.2, dated January 2024 and current at the time of writing, defines a short list of inline constructs: emphasis, strong emphasis, code spans, links, images and line breaks. There is no sizing construct anywhere in it. GitHub Flavored Markdown adds tables, strikethrough, autolinks and task lists on top — and nothing that touches font size either.
The escape hatch is not an accident. CommonMark specifies raw HTML as a first-class part of the format, in section 4.6 for HTML blocks and section 6.6 for inline tags. The practical upshot: Markdown handles the structure it knows about, and anything beyond that vocabulary you write in HTML directly.
So every technique in this article falls into one of three buckets: HTML passthrough, a non-standard parser extension, or a bad idea. Knowing which bucket you are in is most of the battle. If you want a map of what is native, the Markdown cheat sheet covers it.
Does the span style Font-Size Trick Work in Markdown?
Usually not, and this is the single most useful thing to know here. The advice you will find on most pages about markdown font size is some variant of:
<span style="font-size: 10px">This does not do what you think</span>On GitHub, that renders at normal size. The sanitizer GitHub's Markdown pipeline descends from carries a per-element attribute allowlist, and style does not appear in it — not for span, not globally. The tag survives; the attribute is discarded. I went and read that allowlist rather than trusting the write-ups, because this claim circulates in both directions and a good half of them have it backwards.
MacMD Viewer does the same thing, for the same reason: span is allowlisted, but its permitted attributes are class and id only. The two renderers agree, which is a decent proxy for "this will not work anywhere that sanitizes."
What makes it expensive is that nothing warns you. No error, no literal tags, no visual difference from the text around it — people tweak the pixel value for a while before working out that the attribute never arrived.
It does work on static-site generators that render your Markdown themselves, with no sanitization step in between. If you control the whole pipeline, inline CSS is fine. If your Markdown is going into somebody else's renderer, assume style is gone.
How Do You Write Subscript and Superscript in Markdown?
With <sub> and <sup>. Unlike <small>, these are documented by GitHub itself, in its basic writing and formatting syntax guide:
The formula for water is H<sub>2</sub>O.
Einstein wrote E = mc<sup>2</sup>.Renders as: The formula for water is H2O. Einstein wrote E = mc2.
Both tags shift the baseline and reduce the font size, and both work in any renderer that passes raw HTML through — which is most of them. They are also the correct semantic choice: a screen reader has a chance of announcing <sup> sensibly, whereas a font-size span is invisible to it.
Why Does H~2~O Render as Strikethrough Instead of Subscript?
Because in GitHub Flavored Markdown a single tilde opens a strikethrough, and that rule got there first.
The ~x~ subscript syntax is real, but it is a Pandoc extension, not Markdown. Pandoc names the two extensions subscript and superscript and gives them tildes and carets respectively. GFM never adopted either. What GFM did adopt is strikethrough, and GitHub's formatting guide documents it as accepting one or two tildes.
The collision is exact. Copy H~2~O out of a Pandoc tutorial, paste it into a README, and the 2 comes out struck through. The single-tilde behaviour comes from cmark-gfm's strikethrough extension, which accepts a delimiter run of two tildes, or of one tilde unless the host explicitly enables a double-tilde-only option. Almost no host enables it. There is more on the one-versus-two tilde question in the strikethrough guide.
MacMD Viewer inherits exactly this. It parses through swift-markdown, which wraps the same cmark-gfm engine and never sets that option. I ran it against MacMD's real parser configuration rather than reasoning from the source: single tilde gives a Strikethrough node, and 2^10^ gives plain text with literal carets, since nothing in that pipeline claims the caret at all. That is the right outcome — rendering GFM faithfully means what you see locally is what GitHub will show, including the mistakes.
Where the Tilde and Caret Syntax Actually Works
The Pandoc family, and a short list of editors that opted in:
| Renderer | ~sub~ and ^sup^ | Notes |
|---|---|---|
| Pandoc | Yes | The origin. Spaces must be backslash-escaped: P~a\ cat~ |
| Quarto | Yes | Built on Pandoc's Markdown variant, inherits both |
| R Markdown / bookdown | Yes | Renders through Pandoc, so the same syntax applies |
| Typora | Yes, off by default | Must be enabled in the Markdown tab of preferences |
| MultiMarkdown | Yes | Supports H~2~O and a delimited form for complex cases |
| markdown-it | Plugin only | Needs markdown-it-sub and markdown-it-sup |
| VS Code preview | No | Uses markdown-it without those plugins |
| GitHub / GFM | No | Single tilde is strikethrough; caret is literal text |
| Obsidian | No | No native support; users reach for MathJax or HTML tags |
The Typora row explains a surprising amount of confusion. Two people on the same version of the same editor get different results from the same file, because one of them turned the extension on months ago and forgot.
Which Platforms Support Small Text in Markdown?
Support splits cleanly by whether the platform renders raw HTML at all.
| Platform | <small> | <sub> / <sup> | ~x~ / ^x^ |
|---|---|---|---|
| GitHub | Yes — in the sanitizer allowlist | Yes — documented | No |
| GitLab | Not documented | Yes — documented | No — documented as unsupported |
| VS Code preview | Yes | Yes | No |
| Obsidian (reading view) | HTML rendered, sanitized | HTML rendered, sanitized | No |
| Typora | Yes | Yes | Yes, once enabled |
| Pandoc | Yes | Yes | Yes |
| Quarto | Yes | Yes | Yes |
| MacMD Viewer | Yes — app and QuickLook | Yes — app and QuickLook | No |
| Slack | No HTML layer | No | No |
| Discord | No HTML layer | No | No |
Three corrections to claims that circulate widely, since all three are wrong and all three affect the cells above. GitHub does not strip <small> — it sits in the allowlist next to sub, sup and span; it is undocumented, which is not the same thing. VS Code's preview does not strip HTML — its Markdown engine runs markdown-it with HTML enabled. Obsidian does render HTML, with sanitization, by its own documentation; <sub>, <sup> and <small> are not enumerated on that page, which is why the cell above says "sanitized" rather than "yes".
Notion and Reddit are missing from the table on purpose. I could not confirm either against a primary source — Reddit's help pages returned a 403 to every fetch — and a plausible guess in a support matrix is worse than a gap.
Should You Use #### Headings to Make Text Smaller?
No, and in a lot of renderers it does not even work.
The trick assumes each heading level renders smaller than the last, so #### ought to get you small text for free. It fails on three counts.
It corrupts the document outline. Per the W3C's headings tutorial, heading markup exists so assistive technology can convey structure — screen reader users navigate long documents by jumping heading to heading. A fake ##### that is really a caption puts a phantom section in that list. Visual sizing belongs in CSS, not in the outline.
It pollutes every generated table of contents. Anything that builds navigation from your headings — a docs site, a README's auto-generated TOC, MacMD's outline sidebar — picks up the decoy and shows it as a real section.
And the sizing assumption is often false. In MacMD Viewer, h4 is styled at 1.05em: larger than body text. Even h6, the smallest level available, only reaches 0.875em and arrives uppercased, letter-spaced and in a muted colour, which is a label style, not small body text. Somebody reaching for #### to shrink a line gets a bigger line instead.
Two More Small-Text Anti-Patterns
Screenshots of small text. WCAG 2 Success Criterion 1.4.5 Images of Text (Level AA) asks you to use real text wherever the technology can achieve the visual presentation, with narrow exceptions such as logotypes. An image of text is also not selectable, not searchable, not translatable, and does not reflow when someone zooms. In a Markdown file — a plain-text format whose value proposition is that it diffs cleanly and greps — burying content in a PNG gives up the only thing the format was giving you.
Unicode lookalike characters. The Unicode Superscripts and Subscripts block (U+2070–U+209F) is legitimate, but it is notation, not styling. Screen readers announce these characters by name or skip them rather than reading the word. Coverage is incomplete — there is no superscript q, and several subscript letters do not exist — so the trick works on some words and not others. And the text stops being findable: Ctrl+F for "note" will not match "ⁿᵒᵗᵉ".
For Slack, Discord and other platforms with no HTML layer, the honest answer is: don't. Say the thing plainly, or put it in a thread. Chat messages do not need fine print.
Is Small Text an Accessibility Problem?
It can be, and the web has the receipts. The WebAIM Million accessibility analysis, published February 2026, found low-contrast text on 83.9% of home pages — the most common failure type, as it has been for years running. The same study detected WCAG 2 failures on 95.9% of pages, averaging 56.1 errors each.
Low contrast and small type come from the same instinct: making secondary content look secondary by making it harder to read. Markdown declining to give you a font-size lever is less an oversight than a category decision, and the state of the web is a decent argument that it holds up.
Practical version: use <small> when the content genuinely is an aside, and let the reader's stylesheet decide how small that means. Do not stack it with a lightened colour, and do not use it for anything a reader actually needs.
How Do You Preview Small Text on Mac?
macOS ships no Markdown renderer, so a .md file full of <small> and <sub> tags opens in TextEdit as raw angle brackets. To see what you actually wrote you need something that renders HTML inside Markdown.
MacMD Viewer renders <small>, <sub> and <sup> in both the app window and the QuickLook preview — press Space on a file in Finder and the fine print is fine print, not a tag. It also reproduces both traps in this article rather than papering over them: style attributes are stripped, and H~2~O comes out struck through, exactly as GitHub will render it. That is the point of checking locally — the failures show up before you commit them. Download MacMD Viewer — $19.99, one-time.
VS Code and Cursor render all three tags in their built-in preview panes too, since both run Markdown through markdown-it with raw HTML enabled. If the file is already open in your editor, Cmd+Shift+V is the fastest check available. What neither gives you is the tilde behaviour of the platform you are publishing to, so for anything GitHub-bound, verify there as well.
Frequently Asked Questions
How do you make text smaller in Markdown?
Wrap it in the HTML <small> tag: <small>fine print</small>. Markdown itself has no font-size syntax, so the only portable route is raw HTML, which CommonMark passes through to the output. The tag renders at the browser's default small size, roughly 80% of body text.
Does the span style font-size trick work in Markdown?
Usually not. GitHub's Markdown sanitizer allowlist contains no style attribute at all, so <span style="font-size:10px"> renders as normal-size text with no warning. MacMD Viewer strips it the same way — its span attribute allowlist is class and id only. Inline CSS is the first thing most people try and the most reliable way to waste an afternoon.
How do you write subscript and superscript in Markdown?
Use the HTML <sub> and <sup> tags: H<sub>2</sub>O and E = mc<sup>2</sup>. GitHub documents both in its own writing guide, and they work in any renderer that passes raw HTML through, including VS Code's preview and MacMD Viewer's app window and QuickLook preview.
Why does H~2~O render as strikethrough instead of subscript?
Because the single tilde is a strikethrough delimiter in GitHub Flavored Markdown, not a subscript marker. The ~x~ syntax is a Pandoc extension that GFM never adopted, so pasting H~2~O from a Pandoc tutorial into a README gives you a struck-through 2. GitHub, MacMD Viewer and every other cmark-gfm renderer behave this way.
Is there a native Markdown syntax for font size?
No. CommonMark 0.31.2 defines emphasis, strong emphasis, code spans, links, images and line breaks — there is no presentational sizing construct anywhere in the specification, and GitHub Flavored Markdown does not add one. Every small-text technique is either HTML passthrough or a non-standard parser extension.
Should you use #### headings to make text smaller?
No. Headings carry document structure that screen readers and table-of-contents generators depend on, and using them for sizing corrupts both. It also frequently fails at the one job you wanted: in MacMD Viewer, h4 is styled at 1.05em, which is larger than body text, and h6 arrives uppercased with letter-spacing and a muted colour.
Does the small tag work in GitHub READMEs?
Yes. small sits in the allowlist of the sanitizer GitHub's Markdown pipeline is built on, alongside sub, sup and span. It is not mentioned in GitHub's public formatting documentation, which is why so many articles claim it gets stripped — but it renders. What does get stripped is the style attribute.
Content licensed under CC BY 4.0. Cite with attribution to MacMD Viewer.