🥨
Prettier で HTML を整形しただけでデザインが崩れることがある
概要
コードフォーマッタの Prettier (v2.2.1) でコードを整形しただけで、Web上でのデザインが崩れてしまった事例を紹介します。
元 HTML
<body>
<div class="content">
<div class="div-a">A</div><div class="div-b">B</div>
</div>
</body>
オリジナルの HTML は div
内に div
が複数あるだけのシンプル構造です。
Prettier 適用後
<body>
<div class="content">
<div class="div-a">A</div>
<div class="div-b">B</div>
</div>
</body>
デフォルト設定の Prettier を HTML に実行すると、1行に複数の div
を記述していた箇所が、改行で分割されます。
フォーマット前後でデグレが発生
フォーマッターを適用しただけなら挙動は変わらないと思い込んでいましたが、動作を確認してみると、フォーマット前後で以下のようなデグレが発生していました。
フォーマット前
フォーマット後
原因
A
B
が横並びで表示されている時点で察した方もいると思いますが、この HTML ファイルは以下のようなスタイルが適用されていました。
<style>
.div-a,
.div-b {
display: inline;
}
</style>
これによって、 .div-a
.div-b
は、インライン要素となってしまい、改行が半角スペースとして扱われるようになってしまいました。
Prettier
から見れば、 div
はブロック要素なのだから改行してフォーマットを整えても影響は無いと判断していたようです。
解決策
要素のデフォルトの display
属性を無闇矢鱈を変えるものじゃないなと学んだので、 display: inline
の設定を削除し、横並びのスタイルを維持するために flex
を活用するようにすることで、デザインを維持しながらコードのスタイルを自動修正できるようにしました。
<style>
.content {
display: flex;
}
</style>
学んだこと
ただのフォーマッタだからって、プロジェクト全体に Prettier をまとめて実行すると事故ることがある。
- 本業では、ここまで単純な話ではなく、入り組んだコードの中でこのような問題が意図せず発生していました
- ちなみにスナップショットテストがちゃんと機能して差分を検知してくれたので、デグレがリリースされることはありませんでした。
Discussion
この問題僕もときどきハマります。Prettierのオプションで
htmlWhitespaceSensitivity: "strict"
にすれば、勝手にwhite-spaceができることはなくなるのですが、整形の結果がひどくなるのですよね…。僕も今は「display 属性を無闇矢鱈を変えるものじゃないな」という感じで気をつけながら書いてます。
htmlWhitespaceSensitivity
は初めて知りました!確かに
a
のようなインライン要素だと、文字数的に改行したいけどスタイルは崩せないからやむを得ずっていう結果になってビックリしちゃうんですよねぇ。。それもあって最近は Prettier がお気に召すようなコードを意識して書くようになって、ちょっと本末転倒だなとも感じちゃってます。