How to underline text in markdown

Updated

Markdown has no underline syntax. Wrapping text in _underscores_ gives you italics, not an underline, and there is no other marker to try. Where inline HTML is allowed, use the <ins> tag, which works on GitHub, GitLab, Obsidian and most docs generators:

This is <ins>underlined</ins> with HTML.

On GitHub the word "underlined" renders with an underline and nothing else changes. That one line is the portable answer. The rest of this guide covers why <u> is the wrong tag on GitHub, the chat apps that have their own underline markers (Discord, Telegram), the apps with none (Slack, WhatsApp, Reddit) and what to use instead when the text must be emphasised and underline is unavailable.

Why doesn't markdown have underline?

Because on the web underlined text means "link". Markdown was designed to turn plain-text conventions into clean HTML, and its author left underline out deliberately: readers confuse underlined words with hyperlinks, so typographic convention reserves the underline for links and uses italic or bold for emphasis. CommonMark, GFM and every mainstream flavour kept that decision. If the goal is emphasis, bold or italic is the portable, semantic choice; if the goal is "look at this", a highlight (==text== or <mark>) is closer to what people reach for underline to do.

What HTML tags underline text?

Two tags render underlined by default, and only one of them survives GitHub:

TagMeaningGitHubGitLabObsidian
<ins>text</ins>Inserted text, the counterpart of <del>RenderedRenderedRendered
<u>text</u>Unarticulated annotation; purely visualStripped: the tag is removed and plain text remainsRenderedRendered
<span style="text-decoration: underline">CSS underlineStripped (style is removed)StrippedRendered

GitHub's basic formatting docs list <ins> as the underline syntax, and u is absent from the element allowlist in the html-pipeline sanitizer GitHub uses, so <u> silently disappears in READMEs, issues and comments. <ins> is therefore the tag to use everywhere: it underlines in every browser, it is allowed on GitHub, and its meaning ("this was added") is at least honest when you are marking an edit. Screen readers do not announce either tag by default, so an underline carries no meaning for non-sighted readers; if the emphasis matters, add bold or say it in words.

How do you underline in Discord, Telegram, Slack and WhatsApp?

Each chat app has its own rules, and none of them accept HTML:

AppUnderlineNote
Discord__text__ (two underscores)Discord's Markdown Text 101 lists it; __*text*__ is underline italic, __**text**__ underline bold. In real markdown __text__ is bold, so do not copy it elsewhere
Telegram__text__ in MarkdownV2Bot API only; the desktop and mobile apps use Ctrl/Cmd+U
SlackNonemrkdwn has *bold*, _italic_, ~strike~ and nothing else (Slack formatting)
WhatsAppNone*bold*, _italic_, ~strike~, `mono` only
RedditNoneHTML is escaped and shown as text; the fancy editor has no underline button either

The Discord markdown sheet and Slack markdown sheet cover the rest of each app's syntax.

How do you underline in Obsidian, Notion and Jira?

Obsidian renders inline HTML in Reading view, so <u> and <ins> both work there; <u> is what its community plugins and themes expect. Notion has no markdown shortcut for underline but applies it with Ctrl/Cmd+U on selected text, per its keyboard shortcuts; an <ins> tag pasted or imported from a .md file arrives as plain text. Jira Cloud's editor is the same: Ctrl/Cmd+U, no markdown form (Jira shortcuts). Jira's legacy wiki markup (Jira Server and Data Center, and the {noformat} world of Confluence) underlines with plus signs: +underlined+. The Notion markdown sheet and Jira markdown page have the full mappings.

How do you underline in Pandoc, MDX and docs generators?

ToolSyntaxOutput
Pandoc[text]{.underline} (bracketed spans)Underline in HTML, LaTeX (\underline), docx and ODT; the Pandoc manual documents the underline extension
MDX (Docusaurus, Astro, Next.js)<u>text</u> or <ins>text</ins> as JSXRendered; style={{textDecoration: 'underline'}} also works because MDX accepts JSX style objects
MkDocs (Python-Markdown)^^text^^ with the pymdownx.caret extension; otherwise <ins><ins> in both cases
Hugo, Jekyll (Goldmark, kramdown)<ins> or <u>Rendered; raw HTML is on by default in Jekyll and needs unsafe = true in Hugo's Goldmark config
Typora, Bear, iA Writer<u>text</u>Rendered; Typora also has Ctrl/Cmd+U

Pandoc's form is the one worth memorising if you export to Word or PDF: HTML tags survive to HTML output only, while [text]{.underline} converts to a real underline in every output format.

What about underlining headings?

Markdown's "setext" heading style puts === or --- under a line of text, which looks like underlining in the source but creates an H1 or H2; the rendered heading is not underlined. It covers only two levels, so the # form is preferred (headings guide). If you want a visible rule under a heading, that is a horizontal rule on the next line, or CSS in the site theme, not an underline.

Where does underline work?

PlatformUnderline availableHow
GitHubYes<ins> only
GitLabYes<ins> or <u>
ObsidianYes<u> or <ins>
NotionYesCtrl/Cmd+U, no syntax
DiscordYes__text__
TelegramYes__text__ (bots), Ctrl/Cmd+U (apps)
Jira CloudYesCtrl/Cmd+U; +text+ in legacy wiki markup
MDX, Hugo, Jekyll, TyporaYes<ins> or <u>
PandocYes[text]{.underline}
Slack, WhatsApp, RedditNoNone; use bold or italic
Plain CommonMark with HTML disabledNoTags are escaped and printed

Why is my underline showing as <u> text or disappearing?

The underline is being removed by the platform or was never underline syntax to begin with; three causes cover nearly every report:

  1. GitHub removed the tag. <u> is not allowed; the text stays but the underline goes. Switch to <ins>.
  2. The renderer escapes HTML. Reddit, Slack, Discord and any site with raw HTML disabled print <ins>text</ins> literally. There is no markdown fallback.
  3. Underscores. _text_ and __text__ are italic and bold in markdown; they only underline in Discord and Telegram.

Paste the snippet into the markdown viewer to see what a GFM renderer does with it before posting.

What should you use instead of underline?

Prefer the formatting that carries meaning in every renderer: bold for the thing the reader must not miss, italic for titles and a change of voice, code for identifiers, and a highlight when the text is quoted and you are pointing at part of it. For "this text changed", <ins> for additions and <del> (or ~~strikethrough~~, see the strikethrough guide) for removals is the pair that screen readers and diff tools understand. The markdown cheat sheet lists every inline style side by side.

Keep going