メインコンテンツへ移動

CSS整形

CSS整形ツールは、ブラウザ内でスタイルシートのインデントを整え、最小化します。解析ではなくトークン化で動くため、未知の@ルールも、このツールより新しい構文も、そのまま通ります。パーサーは認識できないものを拒否します。フォーマッターにとって、理解できないものを消すより保存する方が常に正しいからです。

端末内で処理
インデント
CSS
0 B1 行行 1、列 1
整形済み読み取り専用
0 B1 行

CSS整形はどう動きますか?

CSSの整形は、その大半が「対象がどこで始まりどこで終わるか」を知ることに尽きます。そして、素朴なやり方では間違う場所が4つあります。

波括弧は必ずしもブロックではない

content: "}"は文字列の中に閉じ波括弧を含み、/* } */はコメントの中に含みます。こうした状態を追跡せずに波括弧で分割すると、疑似要素のカウンターを含むスタイルシートも、コメントアウトされたルールを含むスタイルシートも、台無しにするフォーマッターができあがります。上のサンプルには、その両方が意図的に入っています。

コロンは必ずしもプロパティの区切りではない

background: url(https://example.com/x.png)は、値の中にコロンを含みます。カスタムプロパティの値には何でも入ります。それこそがカスタムプロパティの有用性です。分割は、括弧の中にない最初のコロンで行われます。

カンマは必ずしもセレクターの区切りではない

:is(a, b) spanはカンマを含む1つのセレクターであり、:nth-child(2n of .x, .y)も同じです。セレクターリストを裸のカンマで分割すると、どちらも壊れます。分割はトップレベルでのみ行われます。これにより、値の中のrgb(0, 0, 0)も無傷で保たれます。

トークナイザーはパーサーより長持ちする

CSSは絶えず構文を増やしています。ネスト、@container、@layer、:has()、相対色構文などです。パーサーはそれぞれをモデル化しなければならず、知らないものは拒否します。つまり、ブラウザがすでに受け付けているCSSで壊れるのです。トークナイザーが知るべきことは、文字列、コメント、ブロック、セミコロンがどこにあるかだけで、それはCSS 1以来変わっていません。未知の構文は捨てられるのではなくそのまま通ります。フォーマッターが責任を持って取れる挙動は、それだけです。

最小化でもライセンスコメントは残る

/*! … */は、ミニファイアーが保持すべきコメントの目印という慣習です。通常そこにはライセンスが書かれており、これを剥がすと、スタイルシートの配布条件に実際に違反しかねません。それ以外はすべて削除します。閉じ波括弧の直前のセミコロンも削除します。宣言と、その後に続く「何もないもの」を区切っているだけだからです。

ここの最小化がしないのは、値の書き換えです。#ffffffを#fffへ短縮しない、ルールをマージしない、順序も変えない。どれも確かな削減効果であると同時に、ミニファイアーがバグの表面を持つコンパイラーと化す場所でもあります。ビルドパイプラインには本物のミニファイアーを使ってください。このツールは、スタイルシートを貼り付けられる大きさにするためのものです。

入力

a,b{color:red;margin:0}

整形結果

a,
b {
  color: red;
  margin: 0;
}

CSS整形が対応するオプションとエッジケースは?

技術リファレンスとオプション
パラメータ型デフォルト動作とエッジケース
インデントスペース2ネストレベルごとに適用され、メディアクエリ内のルールは2インデントされます。
1行に1セレクタ真偽値onカンマ区切りのリスト内の各セレクタを別々の行に配置します。トップレベルでのみ分割されるため、:is(a, b)はそのまま維持されます。
ルール間の空行真偽値on各トップレベルルールの後に空行を入れることで、長いスタイルシートをスキャンしやすくします。
コメント保持真偽値on複数行コメントは、ASCIIアートのセクションヘッダーが一般的で、再整形すると破壊されるため、内部の形状を維持します。
文字列保持—content: "}" には閉じ中括弧が含まれます。文字列の状態を追跡することで、そのブロックの終了を防ぎます。
url()全体を一括処理—引用符のない url() には、データURIのコロンや括弧など、構造上の文字が含まれることがあります。
アットルールネスト—@media, @supports, @layer, @container およびそれ以降のものです。未知のatルールは破棄されずにそのまま通過します。
ミニファイ空白のみ—空白を圧縮し、ブロック内の最後のセミコロンを削除します。値の書き換えやルールの結合は行いません——それはビルドステップの仕事であり、ペーストボックスの仕事ではありません。
ライセンスコメント/*! … */保持すべてのミニファイアが従う規約に従い、ミニファイ時にも保持されます。削除すると、ライセンスに違反する可能性があります。

よくある質問

ネストしたCSSや@containerクエリを壊しませんか?

壊しません。それこそが、解析ではなくトークン化する意味です。フォーマッターが知るべきことは、文字列、コメント、ブロックがどこで始まりどこで終わるかだけです。@ルールの意味を理解する必要はありません。このツールより新しい構文もそのまま通ります。パーサーが未知のものに出会ったときと、正反対の挙動です。

最小化した出力にコメントが残っているのはなぜですか?

そのコメントが/*!で始まっているからです。/*ではなく。これは、残すべきコメントに対してすべてのミニファイアーが従う慣習であり、たいていライセンスが書かれています。剥がすと、スタイルシートの配布条件に違反しかねません。通常のブロックコメントは削除されます。

本物のビルドツールより、最小化で減るサイズが小さいのはなぜですか?

ここでは空白を取り除くだけだからです。本番用のミニファイアーは、さらに色を短縮し、重複するルールをマージし、上書きされた宣言を落とし、ショートハンドを書き換えます。どれも確かな削減効果であると同時に、エッジケースを誤れば挙動を変えかねない変換でもあります。ビルドパイプラインには本物のミニファイアーを。このツールは、スタイルシートをどこかに貼り付けられる大きさにするためのものです。

セレクターリストがカンマごとに分割されなかったのはなぜですか?

カンマの一部が関数型疑似クラスの中にあるからです。:is(.card, .panel)は、たまたまカンマを含む1つのセレクターであり、そこで分割すると、どちらも不正な2つのセレクターができあがります。分割はトップレベルでのみ行われます。値の中のrgb(0, 0, 0)を無傷で保つのと同じルールです。

CSSの検証もしてくれますか?

しません。プロパティのスペルミスや不正な値を含むスタイルシートも、警告なしに整形します。未知のプロパティを拒否するフォーマッターは、すべてのベンダープレフィックスとすべての新機能を拒否することになるからです。検証が必要なら、ブラウザ自身のDevToolsがStylesパネルで未知のプロパティに印を付けてくれます。どの静的なリストよりも信頼できるシグナルです。

スタイルシートはアップロードされますか?

いいえ。トークン化と整形はブラウザ内で動作します。CSSはペイロードほどの重要度ではありませんが、それでも意味はあります。未公開製品のスタイルシートはその製品について記述し、内部ツールのスタイルシートはその内部ツールについて記述しているのです。