ここ最近の CSS を取り巻く状況の変化は目覚ましいものがあり、これまでにはない速度でブラウザのサポートも進んでいます。その反面、使用できるプロパティが大幅に増えたことで、CSS プロパティ(宣言)の記述順の一貫性を保つことが難しくなりました。
そのような状況を踏まえ、この記事では、CSS を書くときのプロパティ(宣言)の記述順の再考と、Stylelint を導入して自動的に修正を適用する方法を検討していきます。
紹介する CSS プロパティの記述順はあくまでも個人の主観にとどまります。
CSS プロパティの分類
見出し「CSS プロパティの分類」膨大な CSS プロパティを 1 つずつ検討して並べていくのは現実的ではないので、まずはいくつかのグループに分けます。
いくつかの分類方法が考えられますが、CSS の仕様はモジュールごとに開発が進んでいるので、このモジュール単位で分類すれば、プロパティが増えたときにも対応しやすく合理的だと感じました。
そこで、W3C が提供する、CSS の仕様の進捗状況をまとめた CSS Snapshot 2023 の References に掲載されているモジュールをベースに考えていきます。
ここに必要なプロパティを追加した計 492 のプロパティを、仕様の各モジュールごとに以下の 43 のグループごとに並べていきます。
- Cascading and Inheritance
all
- Generated Content
content
、quotes
- Positioned Layout
position
、inset
など - Anchor Positioning
anchor-name
、position-anchor
など - Containment Module
conatiner
、contain
など - Display
display
、order
、visibility
- Grid Layout
grid
、grid-comumn
など - Flexible Box
flex
、flex-flow
など - Box Alignment Module
gap
、align-content
、jusitify-content
など - Float
float
、clear
- Multi-column Layout
conatiner
、contain
など - Overflow
overlfow
、text-overflow
など - Overscroll Behavior
overscroll-behavior
など - Masking
clip
、mask
など - Box Sizing
box-sizing
、inline-size
、block-size
など - Box Model
margin
、padding
など - Backgrounds and Borders (border)
border
、border-radius
など - Shapes
shape-outside
など - Images
object-fit
、image-rendering
など - Lists and Counters
list-style
、counter-reset
など - Tables
table-layout
、border-collapse
など - Color Adjustment
color-scheme
など - Backgrounds and Borders (background)
background
、background-color
など - Color
color
、opacity
など - Compositing and Blending
mix-blend-mode
、background-blend-mode
など - Fragmentation
box-decoration-break
など - Writing Modes
writing-mode
、direction
など - Fonts
font-family
、font-size
など - Inline Layouts
line-height
、vertical-align
など - Text Module
text-align
、white-space
など - Text Decoration
text-decoration
、text-shadow
など - Ruby Annotation Layout
ruby-position
など - Filter Effects
filter
など - SVG's Presentation
fill
、stroke
など - Scroll Snap
scroll-snap-type
、scroll-snap-align
など - Scrollbars Styling
scrollbar-color
、scrollbar-width
- Basic User Interface
outline
、resize
、pointer-events
など - Motion Path
offset-path
など - Viewport
zoom
- Transforms
transform
、translate
など - Will Change
will-change
- Transitions
transition
など - Animations
animation
など - Scroll-driven Animations
animation-range
、scroll-timeline
など - View Transitions Module
view-transition-name
2024/06/20 追記 Anchor Positioning グループを追加しました。
2024/07/29 追記 Viewport グループを追加しました。
グループの順番はスタイルを適用したときの影響範囲の外側から内側へとなるように並べていますが、そこまで厳密ではなく、いくつか例外もあります。
例えば、影響範囲が全体に及ぶ可能性のある Writing Modes を関連性の強い Fonts の直前に配置していたり、UI や変形、アニメーションに関連するプロパティは最後に配置したりと、個人的な使い勝手を考慮したアレンジを加えています。
Stylelint の導入
見出し「Stylelint の導入」プロパティの順番が決まったので、スタイルに反映していきますが、当然ながらこの順番を正確に記憶するのは不可能ですし、すでに存在する CSS の記述順を手作業で変更するのも論外です。
そこで、CSS の Linter(静的解析ツール)である Stylelint と、そのプラグインである stylelint-order を使用します。
まずは、Stylelint と stylelint-order をインストールします。
本サイトのフレームワークは Astro を使用しており、.astro
ファイル内の <style>
にも反映する必要があるため、postcss-html と stylelint-config-html をインストールします。
続いて、Stylelint の設定ファイル .stylelintrc.yml
をルートディレクトリに作成します。この設定ファイルは JSON 形式や JS 形式にも対応していますが、コメントが使えて簡潔に記述できるため YAML 形式を選択しました。
まず、extends
で .astro
ファイルにも対応するようにし、plugins
には stylelint-order
を指定し、rules
でプロパティの並び順を指定しています。
前述した 43 のグループの並び順以外でのルールとしては以下のとおりです。
- ショートハンドプロパティを優先
-webkit-
などのベンダープレフィックスは除く(stylelint-order 上で補完してくれるため)- モジュールには含まれないが関連性が強いものは含めてもよい(例:
z-index
を Positioned Layout に追加) - SVG のプレゼンテーション属性(
fill
やstroke
)については、必要最小限なプロパティのみを抜粋 - 使用する可能性が極めて低いプロパティは、処理の負担を抑えるためにコメントアウトで無効化
コードの全体は、以下の GitHub Gist から確認できます。
https://gist.github.com/griponminds/e5a17150ea8ce69e33d20972eafcaa79
ちなみに、この rules
の order/properties-order
では、groupName
を付与してプロパティのグループを明示的に階層化することもできますが、コメントでも十分なのと、ループ処理の負担を低くするために使用は見送りました。
また、unspecified
オプションでは含まれていないプロパティの処理を指定できますが、デフォルトから変更していないので単純に並び順のチェックから無視されます。
すべてのオプションについては、stylelint-order の GitHub リポジトリを参照してください。
これで、Stylelint が実行できるようになったので、npm-scripts に追加します。
ここでは、解析のみを実行する lint
と、解析結果のエラーを修正する lint:fix
の 2 つのスクリプトを追加しました。試しに npm run lint
を実行すると、以下のように解析結果がコンソールに表示されるようになります。
CLI の詳細については、Stylelint の公式ドキュメントを参照してください。
ここまでの設定で、CSS のプロパティの記述順を統一することができました。次のセクションでは、Stylelint を自動的に適用する方法を紹介します。
Lefthook の導入
見出し「Lefthook の導入」CSS プロパティ(宣言)の記述順のルールを徹底するために、Git フックを使用して、コミットするタイミングで Stylelint の解析と修正を適用するようにします。
Git フックマネージャとしては、husky が有名ですが、ここでは軽量で使い勝手の良さそうな Lefthook を選択しました。
まずは、Lefthook をインストールします。
次に、Lefthook の設定ファイル lefthook.yml
をルートディレクトリに用意します。
ここでは、コミットのタイミングで npx stylelint --fix
コマンドが、src/**/*.{css,astro}
に一致するファイルで、なおかつステージングされたファイルに対して実行するように指示しています。
最後の行の stage_fixed: true
によって、コマンドでステージングされたファイルが修正されたときに、その変更をコミットに含めることができます。
設定ファイルを用意したら、Git フックを設定するためのコマンドを実行します。
この状態で Git にコミットすると、設定した Stylelint が実行されます。
Stylelint を Git フックに設定すべきか
見出し「Stylelint を Git フックに設定すべきか」ここまでで、Lefthook 経由で Git フックが設定され、コミットするたびに Stylelint が実行されるようになり、CSS プロパティ(宣言)の記述順の一貫性を保つことができるようになりました。
宣言ブロックの順番とは異なり、プロパティ(宣言)の順番が変わることでのスタイルへの影響のリスクは、同一のプロパティや、競合するプロパティ(margin-top
と margin-block-start
など)が含まれていない限り考えられません。
しかし、最近ではネスト記法や多くの at-rules が登場し、CSS の書き方が変わってきており、プロパティ(宣言)の順番を変更することによるスタイルへの影響が発生しないとも言い切れません。自動化した場合にはこの影響に気づかずにデプロイしてしまう可能性があります。
また、コミットするたびにスクリプトが実行されるので、わずかながら待ち時間が追加されてしまうのも少しだけ気になる点です。
このような懸念は残りますが、ひとまず Git フックによる自動化は有効にしたまま様子見とし、問題があるようであれば手法を見直したいと考えています。
おわりに
見出し「おわりに」この記事では、CSS の仕様のモジュールごとに CSS プロパティを分類する方法で記述順のルールを作成しました。Stylelint を使うことで、この CSS プロパティの記述順のルールの解析と修正を委ねることができました。
さらに、Git フックマネージャ(Lefthook)を導入することでコミット時に自動的に Stylelint が実行されることで一貫性を持たせることができました。
今回作成したルールについては、実際に運用しながら気になった点があれば調整していきます。