CSSは奥が深い!セレクタの書き方・命名や管理を改善する5つの原則
Post on:2019年11月7日
CSSは簡単なコードで書けます。しかし、プロジェクトの規模が大きくなるにつれ、コードが重複したり、未使用のコードが増えたり、!importantでの上書きが増えたり、読みにくいコードになります。
CSSのセレクタの書き方・命名や管理を改善する、シンプルで非常に効果的な5つの原則を紹介します。
Improve your CSS with these 5 principles
by Adrian Bece (@AdrianBDesigns)
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
はじめに
CSSは簡単で分かりやすいのに、CSSを書く時に原則やベストプラクティスが必要になるのはなぜでしょうか。
プロジェクトの規模が大きくなり、携わる人数が増えるにつれて、問題はますます明らかになり、将来的に深刻な問題を引き起こす可能性があります。CSSの問題の修正はより困難になり、コードが重複したり、!importantでの上書きが増えたり、未使用のコードが山のように増えたり、読みにくいコードになります。
CSSをプロのレベルで記述すると、コードの保守性・拡張性・理解性・簡潔性が向上します。ここではあなたのCSSを次のレベルに導く、シンプルで非常に効果的な5つの原則を解説します。
CSSを改善する命名の原則
コンピュータサイエンスには、キャッシュの無効化と命名という2つの難しいことしかありません。
by Phil Karlton
セレクタの適切な命名はCSSを読みやすくし、構造化され、より簡潔にするための最初のステップです。命名に規則や制約をつけることで、コードが標準化され、堅牢で理解しやすくなります。
BEM(Block-Element-Modifier)、SMACSS(Scalable and Modular Architecture for CSS)、OOCSS(Object Oriented CSS)などのコンセプトが多くのフロントエンド開発者の間で人気があるのはこのためです。
BEMやOOCSSをどのように取り入れるか、以下で実際のセレクタを紹介します。
CSSを改善する詳細度の原則
CSSのプロパティを上書きするのは非常に簡単で便利ですが、複雑なプロジェクトではすぐに手に負えなくなる可能性があります。上書きを繰り返すオーバーライドチェーンは非常に長く複雑になる可能性があり、問題を解決するために!importantの使用を余儀なくされる可能性もあり、デバッグまたは新しい機能を追加するときに簡単に失われる可能性があります。
そんな時に役立つのが、CSSの詳細度です。
1 2 3 4 5 6 7 8 9 10 11 |
/* 低詳細度のセレクタ */ .card {} /* 高詳細度のセレクタ */ .card .title {} .blog-list .card img {} .blog-list .card.featured .title {} #js-blog-list .blog-list .card img {} |
ブラウザと詳細度
低詳細度のセレクタを使用する利点の一つはパフォーマンスです。ブラウザはCSSを右から左に解析します。
例えば、下記のセレクタで見てましょう。
1 |
.blog-list .card img {} |
ブラウザはセレクタを下記の順番で解析します
- ページ上のすべてのimg要素を探し、
- .cardクラスの子孫である要素を探し、
- .blog-listクラスの子孫である要素を探します。
特に、div, img, liのような汎用要素をセレクタに使用する場合は、注意が必要です。詳細度がパフォーマンスにどのような影響を与えるかを確認できます。
同じレベルの詳細度を使用する
詳細度はBEMのような命名規則と組み合わせて、低詳細度のセレクタを使用することで、パフォーマンスが向上し、柔軟で、理解しやすいコードを作成できます。
セレクタにclassを使用する理由は、同じレベルの詳細度を維持し、柔軟性を保つことで、複数の要素をターゲットにすることができるようにしたいと考えているからです。要素セレクタやidセレクタには、必要な柔軟性がありません。
さきほどのCSSにBEMを使用して書き直し、詳細度を低く保ちます。
1 2 3 4 5 6 7 8 9 10 11 |
/* 低詳細度のセレクタ */ .card {} /* 高詳細度のセレクタはBEMを使用して修正 */ .card__title {} .blogList__image {} .blogList__title--featured {} .blogList__img--special {} |
高詳細度のセレクタをBEMで修正したことで、単純で理解しやすくなり、必要に応じて簡単に上書きしたり拡張したりすることができます。また、詳細度を低いレベルに保つことで、最適なパフォーマンスと柔軟性が保証されます。
CSSを改善するDRY原則
DRY(Don't repeat yourself)原則は、CSSにも適用できます。CSSでコードが重複すると、コードが肥大化したり、不要な上書きが発生したり、保守性が低下したりする可能性があります。この問題は、コードを適切に構造化し、高品質のドキュメントを作成することで解決できます。
Storybookは、利用可能なフロントエンド・コンポーネントの概要を作成し、高品質なドキュメントを作成するための優れた無料ツールです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* DRY原則無し */ .warningStatus { padding: 0.5rem; font-weight: bold; color: #eba834; } .errorStatus { padding: 0.5rem; font-weight: bold; color: #eb3d34; } .form-errorStatus { padding: 0.5rem 0 0 0; font-weight: bold; color: #eb3d34; } |
DRY原則にしたがって、コードを整理してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* DRY原則有り */ .status { padding: 0.5rem; font-weight: bold; } .status--warning { color: #eba834; } .status--error { color: #eb3d34; } .form__status { padding: 0.5rem 0 0 0; } |
CSSを改善する単一責任の原則
CSSで単一責任の原則(Single Responsibility Principle)を使用することで、CSSのclassを簡単に拡張、および上書きすることができます。下記の例を見てましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
.button { padding: 1rem 2rem; font-size: 2rem; border-radius: 0.2rem; background-color: #eb4934; color: #fff; font-weight: bold; } .button--secondary { border-radius: 0; font-size: 1rem; background-color: #888; } |
.button-secondaryを使用して.buttonを拡張する場合、異なる背景色を適用してデフォルトのスタイルを維持したいだけで、必要なことを実現するために多くの上書きを行っていることが分かります。
このコードの問題点は、.buttonに複数の役割があることです。
- レイアウトの定義(padding)
- タイポグラフィの定義(font-size,font-weight)
- 見栄えの定義(color,background-color, border-radius)
classに複数の役割があると、classを拡張したり、他のclassと組み合わせたりすることが非常に難しくなります。これを念頭に置いて、BEMとOOCSSを使ってCSSを改善しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/* 共有スタイル */ .button { padding: 1rem 2rem; font-weight: bold; color: #fff; } /* 拡張スタイル */ .button--radialBorder { border-radius: 0.2rem; } .button--large { font-size: 2rem; } .button--primary{ background-color: #eb4934; } .button--secondary { background-color: #888; } |
ボタンのスタイルを複数のclassに分割し、ベースの.buttonを拡張できるようにしました。必要に応じてタイポグラフィや見栄えのclassを適用したり、デザインの変更や新しい要素の追加に合わせてclassを追加することもできます。
CSSを改善する開放/閉鎖原則
ソフトウェアエンティティ(クラス、モジュール、関数など)は、拡張に対して開いて (open) いなければならず、修正に対して閉じて (closed) いなければならない。
実はすでに前の例で、開放/閉鎖原則(Open/Close principle)を使用しています。すべての新しい機能とオプションは、拡張機能によって追加する必要があります。下記の例を見てましょう。
1 2 3 4 5 6 7 |
.card { padding: 1rem; } .blog-list .card { padding: 0.5em 1rem; } |
.blog-list .cardセレクタに、は潜在的な問題がほとんどありません
- 一部のスタイルは、.card要素が.blog-list要素の子である場合にのみ適用されます。
- .blog-list要素内に配置すると、スタイルは.card要素に強制的に適用され、予期せぬ結果と不必要な上書きが発生する可能性があります。
このスタイルを調整してみましょう。
1 2 3 4 5 6 7 |
.card { padding: 1rem; } .blogList__card { padding: 0.5em 1rem; } |
この問題はclassセレクタを一つにすることで解決します。このセレクタを使用すると、予期せぬ影響は回避でき、条件付きのネストされたスタイルも必要ありません。
CSSを改善する方法のまとめ
いくつかの原則を適用することで、CSSの記述方法が大幅に改善されることが分かったと思います。
- BEMやOCSSなどを使用した命名と構造の標準化、可読性の改善。
- 低詳細度セレクタを使用することで、パフォーマンスと構造を改善。
- DRY原則によるコード量の削減とコード品質の改善。
- 単一責任の原則によるコードの拡張性を改善。
- 開放/閉鎖原則のよる柔軟性と保守性。
この記事を読んでいただき、ありがとうございます。
sponsors