Web開発者必見!PrettierのHTML Whitespace Sensitivity徹底ガイド

2025-06-06

通常、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: inlineinline-blockが適用される要素で発生しやすいです。
    • 原因
      htmlWhitespaceSensitivity の設定が、実際のレンダリング結果と合致していない可能性があります。
      • デフォルトの"css"設定は、多くのケースで適切ですが、インライン要素間の空白はブラウザによって単一のスペースに縮小されるため、Prettierがその空白を「重要ではない」と判断して削除したり、逆に改行を挿入してしまったりすることがあります。
      • 逆に、スペースを保持したい場合に"css"のままだと削除されてしまうことがあります。
  1. preタグなどの空白が重要な要素の整形崩れ

    • 問題
      preタグやtextareaタグ、あるいはCSSのwhite-space: pre;などが適用された要素内のコードやアスキーアートなどが、Prettierによって整形されてしまい、表示が崩れる。
    • 原因
      htmlWhitespaceSensitivity"css"の場合、これらの要素内の空白は基本的に保持されるはずですが、何らかの理由で他の設定やPrettierのバージョン、あるいは利用しているパーサー(VueやAngularなど)の挙動によって意図しない整形が行われることがあります。
  2. カスタムコンポーネントでの空白の扱い

    • 問題
      VueやAngularなどのフレームワークで作成したカスタムコンポーネントにおいて、要素間の空白が意図通りに扱われない(例:コンポーネントの間に余計なスペースが入る、あるいはスペースが削除される)。
    • 原因
      Prettierはデフォルトで標準のHTML要素のdisplayプロパティを考慮して空白を処理します。しかし、カスタムコンポーネントのデフォルトのdisplay値がPrettierに正しく認識されない場合、特にdisplay: inlineのように振る舞うカスタムコンポーネントの場合、strictモードのように全ての空白を重要視してしまうことがあります。
  3. Prettier以外のツールとの競合

    • 問題
      VS Codeの拡張機能(ESLint、他のフォーマッターなど)やビルドツールとPrettierが競合し、HTMLの空白が意図せず変更される。
    • 原因
      複数のフォーマッターやリンターが同時に動作している場合、それぞれの設定が衝突して予期しない整形結果になることがあります。
  1. htmlWhitespaceSensitivity オプションの調整

    • 最も一般的な解決策です。 .prettierrc ファイルや package.json のPrettier設定で、htmlWhitespaceSensitivity オプションを調整します。
      • "strict" に設定
        全ての空白を重要とみなします。
        • メリット
          意図しない空白の削除や追加を防ぎ、開発者が書いた空白を最大限に保持します。preタグ内のコードや、インライン要素間の厳密な空白制御が必要な場合に特に有効です。
        • デメリット
          コードが冗長になり、ファイルサイズが増加する可能性があります。多くのHTMLコードでは不要な空白まで保持されるため、デフォルトでは推奨されません。
      • "css" (デフォルト) を再確認
        問題が解決しない場合は、Prettierのバージョンアップや他の設定との組み合わせで挙動が変わる可能性があるため、デフォルトの"css"設定が本当に期待通りに動作しているか再確認します。
      • "ignore" に設定
        全ての空白を無視します。Prettierは空白に関する整形を行いません。
        • メリット
          開発者が空白を完全に手動で管理したい場合に有効です。
        • デメリット
          コードの一貫性が失われ、可読性が低下する可能性が高いです。通常は推奨されません。
    • 設定例 (.prettierrc.json)
      {
        "htmlWhitespaceSensitivity": "strict"
      }
      
  2. `` コメントの使用

    • 部分的な問題に有効です。 Prettierに特定のコードブロックを整形させたくない場合は、そのブロックの直前に `` コメントを追加します。
    • 使用例
      <pre>
          これは
              Prettierに
                  整形されません。
      </pre>
      
      <span
        class="some-class"
      >
          特定の空白を保持したい要素
      </span>
      
    • これは一時的な解決策として非常に便利ですが、多用するとPrettierの一貫性というメリットが損なわれるため、乱用は避けるべきです。
  3. printWidth オプションの調整

    • 問題
      <a>リンク</a>. のように、リンクの後に句読点が来てそれが改行されてしまうなどの問題。これは、一行の文字数制限(printWidth)とHTMLの空白処理が組み合わさって発生することがあります。
    • 解決策
      printWidth の値を増やすことで、Prettierが要素を一行に収めようと試み、改行による空白問題が解決する場合があります。
    • 設定例
      {
        "printWidth": 120, // デフォルト80から増やす
        "htmlWhitespaceSensitivity": "css" // または "strict"
      }
      
  4. CSSのwhite-spaceプロパティの確認

    • 問題
      HTML要素の空白のレンダリングが期待通りでない場合、関連するCSSでwhite-spaceプロパティが設定されていないか確認します。
      • white-space: pre;white-space: pre-wrap; などが設定されている場合、その要素内の空白はブラウザによって保持されます。Prettierの"css"設定はこのCSSプロパティを尊重します。
    • 解決策
      CSSのwhite-spaceプロパティの意図と、Prettierの設定が一致しているか確認します。
  5. Prettier以外のツールとの競合の解消

    • 問題
      VS Codeなどのエディタで「Format on Save(保存時に整形)」が有効になっていて、複数のフォーマッターが設定されている場合に問題が発生しやすいです。
    • 解決策
      • デフォルトフォーマッターの設定
        エディタ(VS Codeなど)で、HTMLファイルのデフォルトフォーマッターをPrettierに設定します。
      • 競合する拡張機能の無効化/設定変更
        他のHTML整形関連の拡張機能がインストールされている場合、一時的に無効にするか、設定を見直してPrettierとの競合を避けます。
      • ESLintとの連携
        ESLintとPrettierを併用している場合は、eslint-config-prettier を使用して、ESLintのフォーマットに関するルールを無効にし、Prettierにフォーマットを一任するように設定します。
  6. Prettierのバージョン確認とアップデート

    • 問題
      稀に、Prettierの特定のバージョンにバグが存在し、空白の整形が正しく行われないことがあります。
    • 解決策
      Prettierを最新バージョンにアップデートし、問題が修正されているか確認します。公式のリリースノートも役立ちます。
  7. フレームワーク固有のパーサーの確認

    • 問題
      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)」&nbsp; を使用することで、ブラウザが空白を削除したり結合したりするのを防ぎ、強制的にスペースを挿入できます。

  • &nbsp; (ノーブレークスペース): ブラウザが結合したり削除したりしない強制的なスペースを挿入します。また、&nbsp;がある場所では改行されません。
    • 用途
      複数の単語間での改行を防ぎたい場合(例: 会社名や日付など)、インライン要素間で特定のスペースを確保したい場合。
    • 注意
      過度な使用はHTMLの可読性を低下させます。レイアウトのための&nbsp;はCSSで制御する方が一般的です。

コード例

<p>価格:1,200&nbsp;</p>
<p>作成日:2023&nbsp;&nbsp;10&nbsp;&nbsp;26&nbsp;</p>
<p>
  <span>項目A</span>&nbsp;&nbsp;<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>タグの開始タグの間に`-->&lt;div class="flex-container"> &lt;div>Item 1&lt;/div> &lt;div>Item 2&lt;/div> &lt;div>Item 3&lt;/div>

&lt;/div>

&lt;style> .flex-container { display: flex; gap: 10px; /* アイテム間の間隔を制御 */ background-color: #f0f0f0; padding: 10px; } .flex-container div { background-color: lightcoral; padding: 10px; } &lt;/style>


**解説:**
* `gap: 10px;`を設定することで、HTMLの空白の有無に関わらず、要素間に常に10pxの間隔が生まれます。これが最も推奨される現代的なアプローチです。

### まとめ

Prettierの`htmlWhitespaceSensitivity`は、コードの整形ルールとして空白を管理しますが、上記の代替方法は、ブラウザがHTMLレンダリング時に空白をどのように解釈するかという、より低レベルな制御を提供します。

* **Prettierの設定:** コードの**見た目**(コードベースの一貫性)を管理。
* **HTML/CSSの代替方法:** ブラウザがHTMLを**レンダリング**する際の空白の**振る舞い**を管理。

多くの場合、`htmlWhitespaceSensitivity: "css"`(デフォルト)とFlexbox/Gridのような現代的なCSSレイアウトを組み合わせるのが、最も効率的でメンテナンス性の高いアプローチとなります。特殊な空白の保持が必要な場合にのみ、`white-space`プロパティや`&nbsp;`の使用を検討すると良いでしょう。