Have you ever asked an AI to “put this in a table” and gotten back text littered with pipes (|) and dashes (-)? It looked like a clean table right there in the chat window — but the moment you copied it into a messaging app, it turned into a mess of symbols.

Those symbols are Markdown. These days you run into it everywhere — GitHub READMEs, technical blogs, note-taking apps like Notion, even the replies an AI chatbot sends you.

It takes about ten minutes to learn. Then, without fail, something trips you up not long after — you hit Enter and the line doesn’t break, or your bold text shows up with the literal asterisks still attached. This post covers nine basic syntax rules and three pitfalls that tend to follow right after. At the end, we’ll also look at why writing good Markdown turns out to be an accessibility habit in disguise.

What Is Markdown — “Easy-to-Write Plain Text” That’s Survived Two Decades

Markdown is a syntax for marking up plain text with a handful of symbols. John Gruber created it in 2004, so it’s now more than twenty years old. Instead of clicking a button to make text bold the way you would in Word, you wrap the text in two asterisks.

markdown
**Write it like this** and it comes out bold.

There’s one core idea behind all of it: it should still be readable before it’s rendered. Even without converting the sentence above, you can tell at a glance what’s emphasized. Write the same thing in HTML and you get <strong>Write it like this</strong> — and now the tags start crowding out the content.

The file extension is .md. You can open it in Notepad, VS Code, or any other editor, and GitHub renders it automatically into something clean-looking. That’s a big part of why it’s used so widely.

  • GitHub READMEs — the introduction you see on a repository’s front page is all Markdown.
  • Technical blogs — this very post was written in Markdown and converted to HTML.
  • Note apps like Notion and Obsidian — their internal syntax either is Markdown or imports and exports it.
  • Developer docs — most open-source documentation sites today are built on Markdown.

There isn’t one single, fixed standard. CommonMark is a spec that cleaned up the ambiguities in the original Markdown, and GFM (GitHub Flavored Markdown), which adds tables, checkboxes, and more on top, is by far the most widely used variant in practice. As a beginner, you don’t need to worry about the distinction.

The Markdown Syntax You Actually Need

You don’t need to memorize the entire spec. These nine rules are enough to write a README or a blog post. Read the table as: write it the way the left column shows, and it renders the way the right column shows.

데이터 표
FormatWrite it like thisRenders like this
Heading# Big heading / ## Medium headingHeadings of different sizes (number of # = level)
Bold**important**important
Italic*emphasis*emphasis
List- itemBulleted list
Numbered list1. firstNumbered list
Link[link text](https://url)A clickable link
Image![image description](path.png)An embedded image
Code`code`code on a gray background
Horizontal rule---A horizontal line dividing content

For multi-line code, wrap it in three backticks. Add a language name right after the opening fence and you get syntax highlighting too.

markdown
```javascript
const greeting = "Hello";
console.log(greeting);
```

Blockquotes start with >, and tables split columns with | the way you just saw. That’s basically all of it. People say you can learn it in ten minutes and use it for ten years — and that’s not an exaggeration.

A table showing the nine basic Markdown syntax rules side by side with their source and rendered output - knowing just headings, bold, lists, links, images, code, and horizontal rules is enough to write most documents
A table showing the nine basic Markdown syntax rules side by side with their source and rendered output - knowing just headings, bold, lists, links, images, code, and horizontal rules is enough to write most documents

When Markdown Doesn’t Render the Way You Expect — Three Common Pitfalls

The syntax is easy, but sooner or later the output surprises you anyway. Here are three problems almost every beginner runs into, organized by symptom. Every result shown here was tested directly through this blog’s own Markdown renderer.

My line break disappears and everything runs together

This is usually the first thing that trips people up. You hit Enter, but on screen the text just sticks to the line before it.

markdown
This is the first line
This is the second line

This isn’t a bug — it’s the rule. Markdown treats a single Enter as just a space. It’s meant to let you wrap your source text onto separate lines for readability without it affecting the output, but the first time you hit it, it feels like a betrayal.

If you want a new paragraph, add one empty line. If you want to break the line without starting a new paragraph, add two trailing spaces or a backslash (\) at the end of the line — that becomes a <br>. Use it for things like addresses or lines of a poem, where the line break itself carries meaning.

Bold text shows up with the asterisks still attached

This one is specific to CJK languages — Korean, Japanese, and Chinese — and English writers essentially never run into it. Korean grammatical particles attach directly to the word before them with no space, so a parenthetical note immediately followed by a particle (something like **draft(초안)**을, where 을 is the particle) breaks the closing emphasis marker, and the asterisks show up literally on screen.

Under CommonMark’s rules, a closing ** doesn’t actually close emphasis if the character right before it is punctuation and the character right after it is a letter, with no space between them. English rarely triggers this, since words are separated by spaces — but Korean, where particles attach with zero space, hits exactly this condition all the time.

The simplest fix is to move the punctuation outside the emphasis markers — **draft**(초안)을. If a Markdown renderer supports CJK extensions, as this blog’s does, inserting a backslash and a space right at the boundary (**draft(초안)**\ 을) marks the boundary without adding a visible space to the output.

I added --- and got a heading instead of a horizontal line

This is the horizontal-rule pitfall. If there’s text directly above it, --- doesn’t become a horizontal rule at all.

markdown
That's everything for today
---

Instead of a horizontal line, the line above gets promoted whole into a heading (<h2>). Markdown has an older syntax where underlining text with --- turns it into a heading, and that’s exactly what fires here. When I tested it myself, that sentence even showed up in the table of contents as a heading.

The fix is to add one empty line above it. If you’d rather avoid the ambiguity altogether, use *** or ___ instead — both render as a plain horizontal rule even with text right above them.

As a side note, the block wrapped in --- at the very top of a post isn’t a horizontal rule at all — it’s front matter. It’s where metadata like the title, date, and tags lives, and blogging engines or documentation tools read it separately. The exact same symbol means something completely different depending on where it sits.

Markdown Editor Recommendations — What Should You Actually Use?

I mentioned you can write Markdown in plain Notepad, but once you’re actually using it, you’ll want to see how the output looks right away. Here are five tools with different personalities. If you’re just starting out, the best move is to begin with whatever tool you’re already using.

데이터 표
ToolBest forPriceOne-line pitch
VS CodeDevelopersFreeAlready installed. Preview with Ctrl/Cmd+Shift+V
ObsidianLong-term note-takingFreeSaves plain .md files on your own machine, links notes together
TyporaDistraction-free writing$14.99 one-timeFormats as you type, WYSIWYG-style
MarkTextA free Typora alternativeFree, open sourceSimilar feel, installable app
StackEdit / DillingerQuick, no-install useFreeOpens right in your browser

If you’re a developer, VS Code is more than enough. No extra installation needed — open a .md file, press Ctrl+Shift+V (Cmd+Shift+V on Mac), and a preview pane opens next to it. This blog’s posts are written that way too.

If you’re planning to build up notes over years, I’d recommend Obsidian. Unlike Notion, your files are saved as plain .md on your own computer, so your writing survives even if the service shuts down someday. That’s arguably the real reason to use Markdown in the first place. It’s free for both personal and commercial use, and the paid license is more of a way to support development than something you need.

Typora costs $14.99 as a one-time purchase (not a subscription), covers up to three devices, and offers a 15-day free trial. If you want a similar feel for free, MarkText is the alternative. Old posts claiming MarkText’s development has stalled still turn up in search results, but it shipped release 0.19.1 in June 2026 and kept getting bug-fix commits through July. It’s an actively maintained project.

Markdown and Accessibility — Every Symbol Is Semantic HTML

So far, this has all been about the “how.” Now it’s time for the “why it matters.” Since this blog focuses on accessibility, I’m going to spend a bit more time on this part — it’s worth it.

When Markdown gets converted, it becomes HTML. But not just any HTML — it becomes HTML with meaning baked in.

데이터 표
Write thisYou get this HTMLWhat it tells assistive technology
## Heading<h2>“A new section starts here”
- item<ul><li>“This is a list, with this many items”
1. item<ol><li>“This is an ordered procedure”
> quote<blockquote>“This is quoted from someone else”
| table |<table><th>“This is a header cell in a table”
![description](img)<img alt="description">The sentence read aloud in place of the image

Assistive technology here means software or devices — screen readers, for instance — that help users with disabilities interact with content. Screen reader users don’t scan a page top to bottom. They press the H key to jump heading by heading, building a mental map of the document first, then jump straight to the section they need. The ## symbol is what builds that map.

Here’s why that matters: hand-written HTML often doesn’t turn out this way. Someone wants bigger text, so they reach for <div class="big-text">. They want something that looks like a list, so they add a bullet-shaped background image to a <div>. Visually it looks the same, but to a screen reader, it’s just an undifferentiated blob of text. Markdown can’t do that even if you wanted it to. Its constraints double as a safety net.

Three Things Still Left to the Human

The syntax builds the structure, but it doesn’t fill in the content. Most of what actually fails an accessibility audit lives right here.

1. Image descriptions (alt text) — whatever you write inside the square brackets becomes the alt text, exactly as written.

markdown
![Chart showing monthly visitor trends](chart.png)   ← this is what a meaningful description looks like
![chart.png](chart.png)                              ← the worst case. Reads the filename aloud
![](decoration.png)                                   ← if it's meant to be decorative... this needs care

The second case is more common than you’d think. Editors auto-fill the filename, and people just leave it there. A screen reader reads that out literally as “chart dot p n g.” This maps to KWCAG 5.1.1 (Provide Appropriate Alternative Text), equivalent to WCAG 1.1.1 (Level A), and it’s exactly the kind of thing automated audit tools catch reliably — so it gets flagged immediately in any formal accessibility review.

The third case needs a bit more explanation. For purely decorative images, an empty alt attribute is the correct answer — reading it aloud would only get in the way. But there’s a hidden trap here.

alt="" and no alt attribute at all are completely different things. An empty alt is an explicit signal meaning “this is decorative, skip it” — the screen reader passes over it silently. But if the alt attribute is missing entirely, the screen reader has nothing to read, so it reads the file path aloud instead. That’s the difference between silence and noise.

The catch is that ![](img.png) doesn’t always get converted to alt="". By spec, it should produce an empty alt — but some renderers or themes decide “the value is empty, so let’s just drop the attribute.” While writing this post, I actually checked this blog’s own theme, and it turned out to behave exactly that way. Leaving an image intentionally blank for decoration was, ironically, turning into an accessibility error.

So when you’re working with decorative images, I’d recommend checking the rendered HTML once. Inspect the image with dev tools and you’ll see right away whether alt="" is there or missing. If it’s missing, writing <img src="..." alt=""> directly instead of relying on Markdown is the safer bet.

2. Link text — write [the official Markdown syntax guide](url) instead of Click [here](url). Screen readers have a feature that lists every link on a page in isolation, and if that list reads “here, here, learn more, click” over and over, it carries zero information. This is KWCAG 6.4.3 (Appropriate Link Text), equivalent to WCAG 2.4.4 (Level A).

3. Heading levels — jumping straight from # to ### punches a hole in the document map. The most common cause is using heading symbols just to make text bigger. If the size looks wrong, that’s a job for CSS, not for adding or dropping # characters. This relates to KWCAG 6.4.2 (Provide Headings).

As a side note, in the automated audit tool axe, skipped heading levels (heading-order) and empty table headers (empty-table-header) are classified as “best practice,” not WCAG violations. Missing image alt text and missing link text, on the other hand, are clear WCAG Level A violations. That’s a useful way to prioritize when you’re short on time — though best-practice issues still have a real impact on the actual user experience.

A Common Trap When Writing Tables

When building comparison tables, a lot of people habitually leave the top-left cell blank. Don’t do that.

markdown
<!-- This produces an empty <th></th> header cell -->
|  | Free | Paid |
|---|---|---|
| Price | $0 | $10/month |

<!-- Fill the top-left cell with a label describing the rows -->
| Category | Free | Paid |
|---|---|---|
| Price | $0 | $10/month |

Markdown tables convert the entire first row into <th> header cells, so leaving one blank creates a nameless header cell. This falls under KWCAG 7.3.2 (Table Structure), equivalent to WCAG 1.3.1. This blog made the exact same mistake once, fixed it, and then wrote a hard rule about it into our own writing conventions.

One thing worth knowing as a limitation of Markdown: Markdown tables can only express column headers, not row headers (scope="row"). If you need a complex table with headers on both axes, the right move is to drop Markdown and write the HTML <table> by hand. The same goes for the lang attribute that marks a language change within a document — Markdown alone can’t do that either. It’s not a silver bullet.

One-Page Summary

  • Markdown is a syntax for marking up plain text with symbols. .md extension, opens anywhere.
  • Nine syntax rules (headings, bold, italic, lists, numbered lists, links, images, code, horizontal rules) cover you in practice.
  • Three pitfalls: a single Enter isn’t a line break · bold breaks around CJK particles · --- needs a blank line above it.
  • For an editor, start with VS Code if you’re a developer, or Obsidian if you’re building up notes.
  • Markdown converts to semantic HTML, so structure comes for free — but alt content, link text, and heading levels are still on you.
  • alt="" (a decorative signal) and no alt attribute at all (reads the file path) are different things. Check the rendered HTML.
  • Don’t leave a table’s top-left header cell empty. Complex tables that need row headers should be written in HTML.

질문으로 다시 보기

What is Markdown?
It’s a lightweight writing syntax that lets you add formatting to plain text using a handful of symbols (#, *, -, and so on). It was created in 2004, and it’s since become the de facto standard for GitHub READMEs, technical blogs, and apps like Notion. The file extension is .md, and it opens in any text editor.
Why do I sometimes see literal asterisks (**) instead of bold text?
This is mostly a CJK-language quirk that English writers rarely trigger. CommonMark’s rule says a closing ** doesn’t actually close emphasis if the character right before it is punctuation and the character right after it is a letter with no space in between. Korean, Japanese, and Chinese grammatical particles attach directly to the preceding word with zero space, so a phrase like a parenthetical note immediately followed by a particle hits this condition constantly. English is spared because words are separated by spaces. The fix, when it comes up, is to move the punctuation outside the emphasis markers, or, if the renderer supports CJK extensions, insert a backslash and a space right at the boundary.
Why does my line break disappear when I hit Enter once?
Markdown treats a single line break as just a space. To start a new paragraph, add an empty line between them. If you want to break the line without starting a new paragraph, end the line with two trailing spaces or a backslash ().
What Markdown editor should I use?
If you’re a developer, VS Code, which you probably already have installed, is more than enough. Open a .md file and press Ctrl+Shift+V (Cmd+Shift+V on Mac) for a live preview. If you’re planning to build up notes over the long haul, Obsidian is a good choice, since files are saved as plain .md on your own computer and survive even if the service shuts down. If you want a prettier writing experience, there’s Typora (paid) or MarkText (free, open source).
Does writing in Markdown automatically make my content accessible?
It solves most of the structural side. # becomes headings (h1-h6), - becomes a list (ul), > becomes a blockquote, and tables get proper th header cells, all of which beats stacking divs by a wide margin. But the content itself is still on you. Markdown’s syntax won’t decide what your image alt text should say, whether your link text actually describes its destination, or whether you skipped a heading level.
Can I add row headers (scope=row) to a Markdown table?
No. Markdown tables only convert the first row into header cells (th) and can’t express row-direction headers. If you need a complex table with headers on both axes, write the HTML table by hand and set scope=“col” and scope=“row” explicitly. For a simple comparison table, filling the top-left header cell with a label like ‘Category’ is enough.

Keep Reading

Once you’ve got the syntax down, the natural next step is those files that keep showing up in repositories these days — things like CLAUDE.md, AGENTS.md, and DESIGN.md. They’re all written in the same Markdown you just learned, except they’re documents meant to be read by AI, not humans.

References