Web開発者必見!PrettierのHTML Whitespace Sensitivity徹底ガイド
通常、HTMLにおいて、連続するスペースやタブ、改行の多くはブラウザによって単一のスペースとして扱われたり、無視されたりします。例えば、<span>Hello World!</span>
と <span>Hello World!</span>
は、ほとんどの場合同じように表示されます。
しかし、特定のHTML要素やCSSプロパティ(例: white-space
プロパティ)によっては、空白が意味を持つ場合があります。例えば、pre
タグ内の空白はそのまま表示されます。
Prettierは、コードの整形ツールとして、開発者が書いたコードを読みやすく一貫したスタイルに自動的に修正します。このとき、「HTML Whitespace Sensitivity」の設定は、PrettierがHTMLの空白を削除したり、追加したりする際に、その空白がレンダリング結果に影響を与えないかどうかを判断するための重要な指標となります。
PrettierのhtmlWhitespaceSensitivity
オプションには、通常以下の値があります。
-
ignore
- この設定では、PrettierはHTML内の空白を完全に無視します。
- Prettierは、空白に関していかなる整形も行いません。これは、PrettierのHTML整形機能を事実上無効にするようなもので、通常は推奨されません。
-
strict
- この設定では、すべての空白が意味を持つとみなされます。
- Prettierは、空白をほとんど変更しません。開発者が書いた空白は、可能な限りそのまま保持されます。
- これは、空白の厳密な制御が必要な場合や、意図しない変更を避けたい場合に有用です。
-
- これは最も一般的な設定で、HTMLの空白は通常無視されるとみなされます。
- Prettierは、連続する空白を単一のスペースに縮小したり、改行を削除したりするなど、レンダリングに影響しないと判断される空白を積極的に整形します。
- ただし、CSSの
white-space
プロパティが設定されている要素(例:pre
タグやインラインスタイルでwhite-space: pre;
が指定されている要素)内の空白は保持されます。
なぜこれが重要なのか?
「HTML Whitespace Sensitivity」の設定は、PrettierがHTMLコードを整形する際に、コードの可読性を高めつつ、意図しないレンダリングの変更を防ぐために非常に重要です。
- strict の必要性
特殊なレイアウトや、空白の存在そのものに意味がある場合に、strict
を設定することで、Prettierがそれらの空白を削除してしまうことを防ぎます。 - css (デフォルト) の利点
多くのHTMLコードでは、空白の厳密な制御は不要であり、この設定によりPrettierはコードをよりコンパクトで読みやすく整形できます。
よくあるエラーと問題
-
- 問題
<a>リンク</a>.
のように、インライン要素とテキストの間にスペースを入れたくないのにPrettierがスペースを追加したり、逆に<span>Hello</span><span>World</span>
の間にスペースが必要なのに削除してしまったりする。特に、CSSでdisplay: inline
やinline-block
が適用される要素で発生しやすいです。 - 原因
htmlWhitespaceSensitivity
の設定が、実際のレンダリング結果と合致していない可能性があります。- デフォルトの
"css"
設定は、多くのケースで適切ですが、インライン要素間の空白はブラウザによって単一のスペースに縮小されるため、Prettierがその空白を「重要ではない」と判断して削除したり、逆に改行を挿入してしまったりすることがあります。 - 逆に、スペースを保持したい場合に
"css"
のままだと削除されてしまうことがあります。
- デフォルトの
- 問題
-
pre
タグなどの空白が重要な要素の整形崩れ- 問題
pre
タグやtextarea
タグ、あるいはCSSのwhite-space: pre;
などが適用された要素内のコードやアスキーアートなどが、Prettierによって整形されてしまい、表示が崩れる。 - 原因
htmlWhitespaceSensitivity
が"css"
の場合、これらの要素内の空白は基本的に保持されるはずですが、何らかの理由で他の設定やPrettierのバージョン、あるいは利用しているパーサー(VueやAngularなど)の挙動によって意図しない整形が行われることがあります。
- 問題
-
カスタムコンポーネントでの空白の扱い
- 問題
VueやAngularなどのフレームワークで作成したカスタムコンポーネントにおいて、要素間の空白が意図通りに扱われない(例:コンポーネントの間に余計なスペースが入る、あるいはスペースが削除される)。 - 原因
Prettierはデフォルトで標準のHTML要素のdisplay
プロパティを考慮して空白を処理します。しかし、カスタムコンポーネントのデフォルトのdisplay
値がPrettierに正しく認識されない場合、特にdisplay: inline
のように振る舞うカスタムコンポーネントの場合、strict
モードのように全ての空白を重要視してしまうことがあります。
- 問題
-
Prettier以外のツールとの競合
- 問題
VS Codeの拡張機能(ESLint、他のフォーマッターなど)やビルドツールとPrettierが競合し、HTMLの空白が意図せず変更される。 - 原因
複数のフォーマッターやリンターが同時に動作している場合、それぞれの設定が衝突して予期しない整形結果になることがあります。
- 問題
-
htmlWhitespaceSensitivity
オプションの調整- 最も一般的な解決策です。
.prettierrc
ファイルやpackage.json
のPrettier設定で、htmlWhitespaceSensitivity
オプションを調整します。- "strict" に設定
全ての空白を重要とみなします。- メリット
意図しない空白の削除や追加を防ぎ、開発者が書いた空白を最大限に保持します。pre
タグ内のコードや、インライン要素間の厳密な空白制御が必要な場合に特に有効です。 - デメリット
コードが冗長になり、ファイルサイズが増加する可能性があります。多くのHTMLコードでは不要な空白まで保持されるため、デフォルトでは推奨されません。
- メリット
- "css" (デフォルト) を再確認
問題が解決しない場合は、Prettierのバージョンアップや他の設定との組み合わせで挙動が変わる可能性があるため、デフォルトの"css"
設定が本当に期待通りに動作しているか再確認します。 - "ignore" に設定
全ての空白を無視します。Prettierは空白に関する整形を行いません。- メリット
開発者が空白を完全に手動で管理したい場合に有効です。 - デメリット
コードの一貫性が失われ、可読性が低下する可能性が高いです。通常は推奨されません。
- メリット
- "strict" に設定
- 設定例 (.prettierrc.json)
{ "htmlWhitespaceSensitivity": "strict" }
- 最も一般的な解決策です。
-
`` コメントの使用
- 部分的な問題に有効です。 Prettierに特定のコードブロックを整形させたくない場合は、そのブロックの直前に `` コメントを追加します。
- 使用例
<pre> これは Prettierに 整形されません。 </pre> <span class="some-class" > 特定の空白を保持したい要素 </span>
- これは一時的な解決策として非常に便利ですが、多用するとPrettierの一貫性というメリットが損なわれるため、乱用は避けるべきです。
-
printWidth
オプションの調整- 問題
<a>リンク</a>.
のように、リンクの後に句読点が来てそれが改行されてしまうなどの問題。これは、一行の文字数制限(printWidth
)とHTMLの空白処理が組み合わさって発生することがあります。 - 解決策
printWidth
の値を増やすことで、Prettierが要素を一行に収めようと試み、改行による空白問題が解決する場合があります。 - 設定例
{ "printWidth": 120, // デフォルト80から増やす "htmlWhitespaceSensitivity": "css" // または "strict" }
- 問題
-
CSSの
white-space
プロパティの確認- 問題
HTML要素の空白のレンダリングが期待通りでない場合、関連するCSSでwhite-space
プロパティが設定されていないか確認します。white-space: pre;
やwhite-space: pre-wrap;
などが設定されている場合、その要素内の空白はブラウザによって保持されます。Prettierの"css"
設定はこのCSSプロパティを尊重します。
- 解決策
CSSのwhite-space
プロパティの意図と、Prettierの設定が一致しているか確認します。
- 問題
-
Prettier以外のツールとの競合の解消
- 問題
VS Codeなどのエディタで「Format on Save(保存時に整形)」が有効になっていて、複数のフォーマッターが設定されている場合に問題が発生しやすいです。 - 解決策
- デフォルトフォーマッターの設定
エディタ(VS Codeなど)で、HTMLファイルのデフォルトフォーマッターをPrettierに設定します。 - 競合する拡張機能の無効化/設定変更
他のHTML整形関連の拡張機能がインストールされている場合、一時的に無効にするか、設定を見直してPrettierとの競合を避けます。 - ESLintとの連携
ESLintとPrettierを併用している場合は、eslint-config-prettier
を使用して、ESLintのフォーマットに関するルールを無効にし、Prettierにフォーマットを一任するように設定します。
- デフォルトフォーマッターの設定
- 問題
-
Prettierのバージョン確認とアップデート
- 問題
稀に、Prettierの特定のバージョンにバグが存在し、空白の整形が正しく行われないことがあります。 - 解決策
Prettierを最新バージョンにアップデートし、問題が修正されているか確認します。公式のリリースノートも役立ちます。
- 問題
-
フレームワーク固有のパーサーの確認
- 問題
Vue(*.vue
)やAngular(*.component.html
)などのフレームワーク固有のファイルで問題が発生する場合。 - 解決策
Prettierはファイル名から適切なパーサーを推論しますが、カスタム設定や特定の環境では、parser
オプションを明示的に指定する必要がある場合があります。 - 設定例
{ "overrides": [ { "files": "*.vue", "options": { "parser": "vue" } } ] }
- 問題
設定ファイル (.prettierrc.json
)
まず、Prettierの設定ファイルを作成します。以下の例では、各セクションでこの設定を変更しながら見ていきます。
// .prettierrc.json
{
"tabWidth": 2,
"semi": true,
"singleQuote": true,
// ここに "htmlWhitespaceSensitivity" を設定します
}
htmlWhitespaceSensitivity: "css" (デフォルト)
これは最も一般的な設定で、HTMLの空白は通常ブラウザによって単一のスペースとして扱われるか、無視されるとみなされます。Prettierは、レンダリングに影響しないと判断される空白を積極的に整形します。ただし、CSSのwhite-space
プロパティが設定されている要素内の空白は保持されます。
例1-1: 通常のHTML要素間の空白と改行
入力コード
<div>
<span>Hello</span>
<span>World</span>!
<a href="#">
Link
</a>
</div>
Prettier整形後
<div>
<span>Hello</span> <span>World</span>!
<a href="#">Link</a>
</div>
解説
<span>World</span>!
のように、要素とテキストの間のスペースも保持されます。<span>Hello</span>
と<span>World</span>
の間の改行とスペースが、ブラウザで単一のスペースとしてレンダリングされるため、Prettierはそれを単一のスペースに縮小します。
例1-2: pre
タグ内の空白
入力コード
<pre>
function greet() {
console.log("Hello, world!");
}
</pre>
Prettier整形後
<pre>
function greet() {
console.log("Hello, world!");
}
</pre>
解説
pre
タグはwhite-space: pre;
というCSSのデフォルトスタイルを持つため、その内部の空白(スペースや改行)はそのままレンダリングされます。Prettierは"css"
設定の場合、この挙動を認識し、pre
タグ内の空白には触れません。
例1-3: インライン要素間の空白問題(起こりやすい)
入力コード
<button>
Click
Me
</button>
Prettier整形後
<button>Click Me</button>
解説
htmlWhitespaceSensitivity: "strict"
この設定では、HTML内の全ての空白が意味を持つとみなされます。Prettierは、開発者が書いた空白を可能な限りそのまま保持しようとします。これは、空白の厳密な制御が必要な場合や、意図しない変更を避けたい場合に有用です。
htmlWhitespaceSensitivity 設定
// .prettierrc.json
{
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"htmlWhitespaceSensitivity": "strict"
}
入力コード
<div>
<span>Hello</span>
<span>World</span>!
<a href="#">
Link
</a>
</div>
Prettier整形後
<div>
<span>Hello</span>
<span>World</span>!
<a href="#">
Link
</a>
</div>
解説
- テキストノード(例:
World
と!
の間)の空白は、テキストの一部として扱われるため、通常は保持されます。 <a href="#">
とLink
の間の改行とインデントも保持されます。"css"
設定とは異なり、<span>Hello</span>
と<span>World</span>
の間の改行とインデントがそのまま保持されます。
"strict"
設定の場合、pre
タグ内の空白の扱いは"css"
と変わりません。元々pre
タグ内の空白は重要とみなされるため、どちらの設定でも保持されます。
例2-3: インライン要素間の空白問題の解消
入力コード
<button>
Click
Me
</button>
Prettier整形後
<button>
Click
Me
</button>
解説
htmlWhitespaceSensitivity: "ignore"
この設定では、PrettierはHTML内の空白に関する整形を完全に無視します。これは、PrettierのHTML整形機能を事実上無効にするようなもので、通常は推奨されません。
例3-1: 全ての空白が無視される
htmlWhitespaceSensitivity 設定
// .prettierrc.json
{
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"htmlWhitespaceSensitivity": "ignore"
}
入力コード
<div>
<span>Hello</span>
<span>World</span>!
<a href="#">
Link
</a>
</div>
Prettier整形後 (元のコードがそのまま出力される傾向)
<div>
<span>Hello</span>
<span>World</span>!
<a href="#">
Link
</a>
</div>
解説
"ignore"
設定では、Prettierは空白に関しては何も整形しません。これは、開発者が空白の整形を完全に手動で制御したい場合にのみ使用されます。ただし、これではPrettierを使うメリットが薄れてしまうため、特殊なケース以外では避けるべきです。
特定の場所でのみPrettierの整形を無効にしたい場合は、htmlWhitespaceSensitivity
の設定とは別に、``コメントが非常に役立ちます。
入力コード
<div>
<span>通常の整形</span>
<a href="#">通常のリンク</a>
<pre>
この pre タグ内の
空白は
絶対に
整形しないでほしい。
</pre>
<span>
この
span は
改行を保持したい
</span>
</div>
Prettier整形後
<div>
<span>通常の整形</span> <a href="#">通常のリンク</a>
<pre>
この pre タグ内の
空白は
絶対に
整形しないでほしい。
</pre>
<span>
この
span は
改行を保持したい
</span>
</div>
- ``が指定されたブロックは、Prettierの整形対象から除外されます。これは、部分的に
"strict"
のような挙動をさせたいが、全体を"strict"
にしたくない場合に非常に有効です。
CSSの white-space プロパティの活用
これはHTMLの空白制御において最も基本的で強力な方法です。CSSのwhite-space
プロパティは、要素内の連続する空白、タブ、改行をブラウザがどのように扱うかを定義します。
-
white-space: normal;
(デフォルト): 連続する空白を単一のスペースに縮小し、必要に応じてテキストを折り返します。これが多くのHTML要素のデフォルトの挙動です。 -
white-space: nowrap;
: テキストの折り返しを禁止し、全ての空白を単一のスペースに縮小します。- 用途
強制的に一行で表示したいテキスト。
- 用途
-
white-space: pre-wrap;
:pre
と似ていますが、必要に応じて長い行を折り返します(改行は保持)。- 用途
preフォーマットされたテキストで、表示領域に収まるように折り返したい場合。
- 用途
-
white-space: pre;
: HTMLの<pre>
タグと同じ挙動。連続する空白や改行をそのまま表示します。コードブロックやアスキーアートなど、空白の厳密な保持が必要な場合に最適です。- 用途
ソースコードの表示、フォーマット済みのテキスト、ASCIIアートなど。 - Prettierとの関連
PrettierのhtmlWhitespaceSensitivity: "css"
(デフォルト)は、このプロパティが適用された要素内の空白には触れません。
- 用途
コード例 (CSS)
<style>
.code-block {
white-space: pre; /* このブロック内の空白はそのまま表示される */
font-family: monospace;
}
.no-wrap {
white-space: nowrap; /* このブロック内のテキストは折り返さない */
overflow: hidden; /* はみ出した部分は隠す */
text-overflow: ellipsis; /* はみ出した部分を...で表示 */
}
</style>
<div class="code-block">
function example() {
console.log(" Hello World!");
}
</div>
<p class="no-wrap">
この非常に非常に非常に非常に非常に非常に非常に非常に非常に非常に非常に非常に非常に非常に非常に非常に非常に長いテキストは折り返されません。
</p>
HTMLエンティティの使用
HTMLエンティティ、特に「ノーブレークスペース(Non-breaking space)」
を使用することで、ブラウザが空白を削除したり結合したりするのを防ぎ、強制的にスペースを挿入できます。
(ノーブレークスペース): ブラウザが結合したり削除したりしない強制的なスペースを挿入します。また、
がある場所では改行されません。- 用途
複数の単語間での改行を防ぎたい場合(例: 会社名や日付など)、インライン要素間で特定のスペースを確保したい場合。 - 注意
過度な使用はHTMLの可読性を低下させます。レイアウトのための
はCSSで制御する方が一般的です。
- 用途
コード例
<p>価格:1,200 円</p>
<p>作成日:2023 年 10 月 26 日</p>
<p>
<span>項目A</span> <span>項目B</span>
</p>
CSSの font-size: 0; と letter-spacing を利用したインライン要素間の空白削除ハック
インライン要素(inline
または inline-block
)が隣接している場合、HTMLの改行やスペースがブラウザによって単一のスペースとして解釈され、要素間に意図しない空白(約4px程度)が生じることがあります。これをCSSで完全に削除するハックがあります。
- 親要素に font-size: 0; を適用し、子要素で font-size をリセットする
親要素でフォントサイズを0にすることで、テキストノードとしての空白の幅も0になり、子要素では通常のフォントサイズを再設定します。- メリット
確実かつ柔軟な制御が可能です。 - デメリット
フォントサイズのリセットを忘れるとテキストが見えなくなります。 - 用途
ナビゲーションメニューなど、インラインブロック要素が隙間なく並ぶ必要がある場合。
- メリット
コード例 (CSSハック)
<div class="inline-block-container">
<span>Item 1</span><span>Item 2</span><span>Item 3</span>
</div>
<style>
.inline-block-container {
font-size: 0; /* 子要素間の空白を削除 */
}
.inline-block-container span {
display: inline-block;
font-size: 16px; /* 子要素でフォントサイズをリセット */
background-color: lightblue;
padding: 10px;
}
</style>
- letter-spacing を利用する(一部の場合)
非常に小さなletter-spacing
の負の値を設定することで、隣接するインライン要素間の空白を縮小または削除できる場合があります。これはハック的であり、予測不可能な挙動を示すことがあるため注意が必要です。
HTMLでは、タグの直後にコメントを挿入することで、タグ間の空白をブラウザが認識しないようにできます。これは主に、インラインブロック要素間の空白を削除するために使用されます。
- 注意
コードの可読性がやや低下します。 - 用途
CSSのfont-size: 0;
ハックを使いたくないが、要素間の空白を完全に削除したい場合。
コード例
<div class="button-group">
<button>Button 1</button
><button>Button 2</button
><button>Button 3</button>
</div>
<style>
.button-group button {
display: inline-block;
padding: 10px 20px;
background-color: lightgreen;
border: none;
}
</style>
解説
<button>
タグの終了タグと次の<button>
タグの開始タグの間に`--><div class="flex-container"> <div>Item 1</div> <div>Item 2</div> <div>Item 3</div>
</div>
<style> .flex-container { display: flex; gap: 10px; /* アイテム間の間隔を制御 */ background-color: #f0f0f0; padding: 10px; } .flex-container div { background-color: lightcoral; padding: 10px; } </style>
**解説:**
* `gap: 10px;`を設定することで、HTMLの空白の有無に関わらず、要素間に常に10pxの間隔が生まれます。これが最も推奨される現代的なアプローチです。
### まとめ
Prettierの`htmlWhitespaceSensitivity`は、コードの整形ルールとして空白を管理しますが、上記の代替方法は、ブラウザがHTMLレンダリング時に空白をどのように解釈するかという、より低レベルな制御を提供します。
* **Prettierの設定:** コードの**見た目**(コードベースの一貫性)を管理。
* **HTML/CSSの代替方法:** ブラウザがHTMLを**レンダリング**する際の空白の**振る舞い**を管理。
多くの場合、`htmlWhitespaceSensitivity: "css"`(デフォルト)とFlexbox/Gridのような現代的なCSSレイアウトを組み合わせるのが、最も効率的でメンテナンス性の高いアプローチとなります。特殊な空白の保持が必要な場合にのみ、`white-space`プロパティや` `の使用を検討すると良いでしょう。