改行・スペースの扱いとは何か
テキストの改行やスペースは、「どのプロパティで入れるか(textContent/innerText/innerHTML)」と「CSS の white-space 設定」によって見え方が変わります。ここが重要です:文字の“中身”は JS、表示の“整形”は CSS。役割を分けて考えると、意図通りにコントロールできます。
文字の入れ方で変わる挙動(textContent・innerText・innerHTML)
textContent の特徴(素の文字をそのまま)
<p id="a"></p>
<script>
const a = document.getElementById("a");
a.textContent = "一行目\n二行目 倍スペース"; // \n やスペースは「文字」として入る
</script>
HTMLここが重要です:textContent は改行やスペースを文字として保持します。ただし見え方の最終形は CSS の white-space で決まります。
innerText の特徴(表示基準で整形)
<p id="b" style="width:140px; border:1px solid #ddd;"></p>
<script>
const b = document.getElementById("b");
b.innerText = "一行目\n二行目"; // 画面上で改行として表示されやすい
</script>
HTMLここが重要です:innerText は“見え方”に合わせて改行・空白を整形します。取得時にレイアウト計算が走るため、多用は避けます。
innerHTML の特徴(HTMLを展開)
<p id="c"></p>
<script>
const c = document.getElementById("c");
c.innerHTML = "一行目<br>二行目 倍スペース"; // タグで明示的に改行・スペース
</script>
HTMLここが重要です:HTML を意図して使う場面だけ innerHTML。外部データはそのまま混ぜない(XSS対策)。
改行の出し方(JSの \n と HTML の <br> の違い)
\n は「文字」、<br> は「要素」
<div id="x" class="box"></div>
<div id="y" class="box"></div>
<style>
.box { border:1px solid #ddd; width:180px; white-space:pre-wrap; }
</style>
<script>
document.getElementById("x").textContent = "A\nB\nC"; // \n を文字として挿入
document.getElementById("y").innerHTML = "A<br>B<br>C"; // 明示的な改行要素
</script>
HTMLここが重要です:CSS が white-space: normal のままだと \n は折り返しになりません。表示上の改行が欲しいなら、white-space を調整するか <br> を使います。
スペースの出し方(連続スペースは“つぶれる”)
HTML の標準挙動(スペースは1つに圧縮)
<p id="s">A B C</p> <!-- 連続スペースは1つに見える -->
HTMLここが重要です:通常の表示(white-space: normal)では、複数スペースは1個に圧縮されます。
連続スペースを保つ方法
<p id="keep1" style="white-space:pre;">A B C</p> <!-- 全て保持 -->
<p id="keep2" style="white-space:pre-wrap;">A B C</p> <!-- 保ちつつ折り返し -->
<p id="keep3">A B C</p> <!-- HTML の を使用 -->
HTMLここが重要です:スペースを見たまま出したいなら、white-space: pre / pre-wrap か を使います。レイアウトに合わせて選びましょう。
white-space の主要モード(見え方を決めるキー)
よく使う設定
- normal: 改行は無視、連続スペースは圧縮。最も一般的な表示。
- pre: 改行・スペースともにそのまま。テキストそのままを見せたいとき。
- pre-wrap: 改行・スペースを保持しつつ、幅で自動折り返しする。
- pre-line: 連続スペースは圧縮、改行は保持。テキストだけ改行したいとき。
<div class="box normal">A B\nC</div>
<div class="box pre" style="white-space:pre;">A B
C</div>
<div class="box pre-wrap" style="white-space:pre-wrap;">A B
C</div>
HTMLここが重要です:見え方を決めるのは CSS。テキストは textContent で安全に入れ、white-space を目的に合わせて選ぶのが基本設計です。
入力データの整形(余分な空白・改行を扱うコツ)
余分な空白を整理してから表示
function normalizeText(s) {
return String(s ?? "")
.replace(/\r\n?/g, "\n") // 改行コードを統一
.replace(/[ \t]+\n/g, "\n") // 行末の余計な空白を削除
.trim();
}
const text = normalizeText(userInput);
el.textContent = text; // まずは安全に文字として挿入
JavaScriptここが重要です:表示混乱の多くは“入力のばらつき”。前処理で揃えると、CSS と組み合わせて思い通りに見せられます。
テンプレートリテラルのインデントに注意
el.textContent = `
一行目
二行目
`; // 先頭の改行やインデントが混ざる → trim や置換で整える
JavaScriptここが重要です:多行文字は便利ですが、意図しない空白を含みがち。テンプレート生成時に整形する癖を。
用途別の指針(迷ったらこの方針)
表示だけ改行したい
- ラベルや説明文: textContent + CSS の white-space: pre-line / pre-wrap。
- 簡易改行: innerHTML の <br> を使う(外部データは混ぜない)。
連続スペースを見せたい
- 見た目重視: white-space: pre / pre-wrap。
- 部分的に: を挿入(固定テンプレートに限る)。
安全性と性能を守る
- データ挿入: 原則 textContent(または createTextNode)。
- 大量表示: DocumentFragment でバッチ追加、表示整形は CSS に寄せる。
- 取得の読み取り: innerText の多用は避け、必要箇所だけに限定。
実践例:メモビューア(改行保持+安全表示)
<pre id="viewer" class="viewer"></pre>
<textarea id="input" rows="6" cols="30" placeholder="メモを入力(改行そのまま表示)"></textarea>
<button id="show">表示</button>
<style>
.viewer { white-space: pre-wrap; border: 1px solid #ddd; padding: 8px; }
</style>
<script>
const viewer = document.getElementById("viewer");
const input = document.getElementById("input");
const show = document.getElementById("show");
function normalize(s) {
return String(s ?? "").replace(/\r\n?/g, "\n"); // 改行コードを LF に統一
}
show.addEventListener("click", () => {
const text = normalize(input.value);
viewer.textContent = text; // 安全に文字で入れる
// 表示は pre-wrap で改行・スペースを保持しつつ折り返し
});
</script>
HTMLここが重要です:内容は textContent で安全に挿入、見え方は white-space: pre-wrap に任せる。責務分離で意図通りの表示を簡潔に実現できます。
まとめ
改行・スペースは「挿入方法(textContent/innerText/innerHTML)」と「CSS の white-space」で見え方が決まります。原則は“文字は安全に入れる(textContent)”“見え方は CSS で整える”。表示上の改行が欲しければ pre-line / pre-wrap や <br>、連続スペースは pre / pre-wrap や 。入力は整形してから出し、innerText の読み取りは必要最小限に。この指針を守れば、改行・スペースの表示は思い通りで、安全かつ高速にコントロールできます。
