Markdownで改行されない原因と直し方|行末スペース2つ・空行・brの使い分け
Markdownで Enter を押して書いた改行が、表示すると1行につながってしまう場合、原因はMarkdownの仕様どおりの動きであることがほとんどです。直す方法は3つで、「行末に半角スペースを2つ」「空行を1行入れて段落を分ける」「行末にバックスラッシュ(\)を置く」のいずれかです。
ただし、行末スペースは全角スペースやタブでは効かず、最終行では意味がなく、自動整形で消されやすいという落とし穴があります。この記事では、主要なパーサーで実際に出力を確かめた結果を示しながら、原因ごとの直し方を解説します。
なぜ Enter だけでは改行されないのか
Markdownでは、ソース上の1回の改行は「ただの改行(ソフトブレーク)」として扱われ、HTMLに変換されるときは<br>にならず、そのまま改行文字として出力されます。ブラウザはHTMLの改行文字を空白1つ分として表示するため、画面上は文章がつながって見えます。
次のソースを、3つのパーサーで変換して確かめました。
1行目
2行目
| パーサー | 出力されるHTML |
|---|---|
| marked 18.1.2 | <p>1行目\n2行目</p> |
| markdown-it 15.0.3 | <p>1行目\n2行目</p> |
| commonmark(JS実装) | <p>1行目\n2行目</p> |
3つとも<br>は出力されず、<p>の中に改行文字が入るだけです。つまり「改行されない」のは不具合ではなく、そういう仕様だと分かります(Node v20.20.1 で実測)。
見出しの直後や引用(>)の中、リスト項目の続きの行でも同じで、改行は<br>になりませんでした。コードブロック(```)の中だけは、改行がそのまま保持されます。
直し方1:行末に半角スペースを2つ入れる
もっとも一般的な方法です。改行したい行の末尾に半角スペースを2つ以上置きます。
1行目
2行目
変換結果は次のとおりです。
| パーサー | 出力されるHTML |
|---|---|
| marked | <p>1行目<br>2行目</p> |
| markdown-it | <p>1行目<br>\n2行目</p> |
| commonmark | <p>1行目<br />\n2行目</p> |
3つとも<br>が出力されました。スペースを3つにしても結果は同じです。一方、半角スペース1つだけでは改行になりません(markedは 1行目 \n2行目 のまま出力)。
行末スペースが効かない4つのパターン
実測で「効かなかった」ものを整理します。
| 書き方 | 結果 |
|---|---|
| 半角スペース1つ | 改行にならない |
全角スペース2つ( ) | 改行にならない。全角スペースがそのまま残るだけ |
| タブ1つ | 改行にならない |
| 段落の最終行の末尾にスペース2つ | <br>は出ない(そこで段落が終わるため無意味) |
日本語入力では、全角スペースが混入しやすい点に注意してください。見た目はほとんど区別できないため、行末のスペースが「半角2つ」になっているか確認します。
直し方2:空行を入れて段落を分ける
改行ではなく段落を分けてよいなら、空行を1行入れるのが最も確実です。
1行目
2行目
3つのパーサーすべてで <p>1行目</p> と <p>2行目</p> に分かれました。行末スペースのように見えない文字に頼らないため、自動整形でも壊れません。
段落を分けると、ブラウザの標準スタイルでは段落の間に余白ができます。詩や住所のように「余白なしで行だけ変えたい」場合は、次の方法を使います。
直し方3:バックスラッシュか <br> を使う
行末のバックスラッシュ(\)も改行として扱われました。marked と markdown-it の両方で、1行目\ の次の行が <br> で区切られて出力されます。この記法は CommonMark の仕様にあるもので、行末スペースと違って目に見えるのが利点です。ただし、対応していないツールもあると考えられるため、使うサービスで確かめてください。
<br>を直接書く方法もありますが、ツールによってはHTMLが無効化されています。
| 入力 | marked | markdown-it(初期設定) |
|---|---|---|
1行目<br> + 改行 + 2行目 | <br>として出力 | <br>とエスケープされ、文字として表示 |
markdown-it は初期設定でHTMLタグを許可しないため、<br>という文字列がそのまま画面に出ます。「<br>と書いたら本当に<br>と表示された」場合は、使っているサービスがHTMLを許可していない可能性があります。
他所ではあまり書かれていない落とし穴
落とし穴1:プレビューでは改行できたのに、公開すると改行されない
Markdownプレビューを使う人が最も引っかかるのが、プレビューの仕様が本番と違うケースです。
当サイトのMarkdownプレビューツールは、ソースを1行ずつ処理し、普通の行をそれぞれ別の<p>にする簡易実装です。ソースを読み、同じ関数に次の入力を渡して確認しました。
| 入力 | ツールの出力 |
|---|---|
1行目 + 改行 + 2行目 | <p>1行目</p> と <p>2行目</p> |
1行目 + 改行 + 2行目(行末スペース2つ) | <p>1行目 </p> と <p>2行目</p>(<br>は出ない) |
- 項目 + 改行 + 続きの行 | リストの後に別の<p>続きの行</p> |
つまり、このツールでは Enter だけで行が分かれて見えます。上の3つのパーサーでは、同じソースが1行につながります。 簡易プレビューで確認して安心し、GitHubなどに貼ったら改行が消えた、という食い違いが起こりえます。
簡易ツールの表示は、あくまで文法の目安として使ってください。改行の最終確認は、実際に公開するサービスのプレビューで行うのが確実です。
落とし穴2:行末スペースは自動整形で消える
行末のスペースは、エディタの設定や整形ツールが「余分な空白」として削除することがあります。たとえばVS Codeには保存時に行末の空白を削除する設定(files.trimTrailingWhitespace)があり、EditorConfigにも同様の項目(trim_trailing_whitespace)があります。これらが有効だと、スペース2つで書いた改行が保存のたびに消えると考えられます(今回、各エディタ上での再現は確認していません)。
「昨日は改行できたのに、保存し直したらつながった」という場合は、行末スペースが消えていないかを疑ってください。対策は、バックスラッシュ方式に変えるか、空行で段落を分ける方法に切り替えることです。
落とし穴3:改行コード(CRLF)は原因ではない
Windowsで書いたファイルの改行コード(CRLF)が原因ではないか、と疑う人は多いようです。実測では、CRLF(\r\n)で書いても結果はLFと同じでした。
- 行末スペース2つ+CRLF:marked・markdown-it ともに
<br>が出力された - スペースなし+CRLF:どちらも
<br>は出ず、改行文字のまま
改行コードの違いは、改行されない原因ではありません。改行コードの基礎は改行コード(CRLF・LF)の違いと変換方法にまとめています。変換が必要な場合は改行コード変換ツールで確認できます。
「Enterだけで改行したい」場合の設定
毎回スペースを入れるのが面倒なら、パーサー側の設定で、ソースの改行をすべて<br>にする方法があります。
| パーサー | 設定 | 実測結果(スペースなしの 1行目+改行+2行目) |
|---|---|---|
| marked | breaks: true | <p>1行目<br>2行目</p> |
| markdown-it | breaks: true | <p>1行目<br>\n2行目</p> |
| commonmark(JS実装) | softbreak: "<br />" | <p>1行目<br />2行目</p> |
import { marked } from "marked";
// Enter だけの改行も <br> にする
const html = marked.parse(source, { breaks: true });
この設定は自分でMarkdownを変換する場合にしか使えません。GitHubやQiitaなど既存のサービスの設定は変えられないため、そちらでは前述の直し方1〜3を使います。
なお、サービスごとの挙動の違い(たとえばGitHubのコメント欄と.mdファイルで扱いが異なるとされる点)は、記事によって記述が食い違っており、今回は確認できていません。公開先の公式ドキュメントと、実際のプレビューで確かめてください。
表(テーブル)の中で改行したいとき
表のセルの中では、行末スペースもバックスラッシュも使えません。セルは1行で書く必要があるためです。この場合は<br>を使います。
| 項目 | 内容 |
| --- | --- |
| 住所 | 1丁目<br>2番地 |
marked では、セル内の<br>はそのまま<br>として出力されました。一方、markdown-it は初期設定だと<br>にエスケープされ、文字として表示されました。表の崩れ全般については、Markdownの表が崩れる原因と直し方で扱っています。
切り分けチェックリスト
改行できないときは、次の順で確認します。
- 行末のスペースは半角で2つ以上か(全角やタブではないか)
- その行は段落の最終行ではないか(最終行の末尾には効かない)
- エディタの保存時整形で、行末スペースが削除されていないか
- 使っているプレビューが簡易実装ではないか(本番サービスのプレビューで確認する)
<br>を書いた場合は、そのサービスがHTMLを許可しているか- 空行で段落を分けても問題ないなら、空行方式に切り替える
箇条書きや引用が崩れて見える場合は、改行とは別の原因もあります。チェックボックスについてはMarkdownのチェックボックスが表示されない原因を、コピー元の改行が消える問題についてはコピペで改行が消える原因を参照してください。
まとめ
- Enter だけの改行は
<br>にならない。marked・markdown-it・commonmark の3つで実測し、すべて同じ結果だった - 直し方は行末に半角スペース2つ、空行で段落を分ける、行末のバックスラッシュの3つ
- 全角スペース・タブ・半角1つ・最終行の末尾のスペースは効かない。CRLFは原因ではない
- 当サイトの簡易プレビューは各行を別の段落にするため、本番と結果が食い違う。最終確認は公開先のプレビューで行う
- 行末スペースは自動整形で消えることがあるため、消えて困る場合は空行方式にする
なお、この記事の実測は Node v20.20.1 と、上記バージョンのパーサーで行ったものです。GitHub・Qiita・Zenn・Notion など各サービス上の表示は今回確認しておらず、サービス側の仕様変更もありえます。一般的な整理であり、個別の環境での結果を保証するものではありません。