Closed22

日報:CSS設計について学習

ようへい | Reactエンジニアようへい | Reactエンジニア

背景

コーディングをできるようになるために勉強中。
CSS設計について知り、興味を持った。

前回までのあらすじ

どんな設計論があるのか。
BEM、OOCSS、SMACSS、FLOCSSがあるのを知った。
BEMとOOCSSについては、深く勉強するまでもないと高をくくっている。
まずはSMACSSについて学習することにした。
公式っぽい資料を見つけたので、それを読んで学習していく。
https://smacss.com/files/smacss-ja.pdf
SMACSSでは、ベース、レイアウト、モジュール、ステート、テーマにCSSを分けるという設計思想。

ようへい | Reactエンジニアようへい | Reactエンジニア

ベースとレイアウトについて学んだ。
ベースではリセット系のCSSを定義していくらしい。
また、bodyタグの背景色を指定することを強く推していたが、理由についてはあまり理解できなかった。
この資料は2012年に出版されたものみたいで、10年以上前の考え方であるという前提で見なければならないなと思った。
というのも、今だと要素を横並びにするスタイルにdisplay: flex;があるが、この資料にはfloat: left;が登場してくる。
float: left;で頑張って勉強していた時代が懐かしいなと余計なことを考えながら、そういった歴史を踏まえた前提でこの資料も読んでいく必要があると思った。
他にもCSSには、当時と比べるとたくさんの機能が追加されているので、実際の現場ではSMACSSの設計論を現代版として改善して使われているのだと思った。
後に学習するFLOCSSもまさにSMACSSのいいところどりをしたと前読んだ記事に書いてあった。
レイアウトについて驚いたのが、idセレクタに普通にスタイルを当てていることだった。
当時はまだidセレクタにスタイルをなるべく当てないほうがいいということが常識ではなかったのだろう。
そういう意味でもここ10年くらいのCSSの進化はめざましいなと思った。
明日はレイアウトの続きを学習していく。

ようへい | Reactエンジニアようへい | Reactエンジニア

モジュールについて

IDセレクタや要素セレクタを使わない

IDセレクタや要素セレクタに対してスタイルを当ててしまうと、要素数の変化や内部構造の変化に適応できなくなり、拡張性が低くなる。
h1などのセマンティック性が高い(divやspanはタグの中では意味が弱いので、セマンティック性が低い)ものは要素セレクタを使っても衝突しづらいが、基本的にクラスセレクタで書くことがベター。

モジュールを拡張するときはサブクラスをつける

1つのクラスだけでモジュールを拡張しようとすると、詳細度を上書きするか、important!(あまりに使うことがないので!の位置を間違えてしまった)を使うことになってしまう。
これらはCSS設計としてどちらも悪手になりやすい。
サブクラスをつけることでそれぞれのスタイルを独立させつつ、モジュールを拡張していくことができる。

ようへい | Reactエンジニアようへい | Reactエンジニア

ステート

モジュールとの違い

  • レイアウトとモジュールの両方に対して当てることができる。
  • JavaScriptに依存するスタイル。

唯一importantの使用が認められている

状態はimportantを使用しても競合することが稀なため、importantの使用が認められている。

所感

モジュールやレイアウトのスタイルの詳細度が高いとクラスを当てても相殺されてしまうため、むしろimportantを使ったほうがいいまであると思う。

特定のモジュールが状態を保つ場合

特定のモジュールが状態を保つ場合は、モジュールのスタイルの中に状態のスタイルを書くべき。

ようへい | Reactエンジニアようへい | Reactエンジニア

テーマ

これは使わないプロジェクトがほとんどのため、切り分けるか筆者も悩んだらしい。
テーマを切り替えたりするようなプロジェクトでは必要になる。
サイト全体の見た目やフィーリングを表現するのに必要な定義。
例えば、ダークモードなどの色の変更や言語切り替えによるフォントを再定義に使用する。
theme-プレフィックスを付ける。

ようへい | Reactエンジニアようへい | Reactエンジニア

状態の変更

いろんな状態の変更方法がある。

クラスによる状態の変更

クラスによる変更はHTMLの構造の依存度が高い。
そのため、変更に弱いコードになりやすい。

属性セレクタによる状態の変更

属性セレクタは衝突なく変更できる1つのソリューション。

アニメーションについて

CSSで見た目を定義して、JSで状態を変更する。
JSでインラインのCSSを書くべきではない(当時はReactやVueも一般的ではなかった)。

擬似クラスによる状態の変更

当時のCSS2では、:hoverや:focus、:activeはあったが、:nth-childや:last-childはなかったらしい。
モジュールの種類、状態、擬似クラスによる状態でUIが多様化するので、程々に抑えておいたほうがメンテンナンスが簡単になる。

メディアクエリ

今となっては、@mediaをCSSで書くやり方が主流になっていると思うが、linkタグにmedia属性をつけることでメディアクエリを書くやり方もあるらしい。しらなんだ。
SMACSSの理念として、1つのスタイルは他のスタイルとは独立するというものがあるため、メディアクエリはレイアウト、モジュールの近くに書く。そうすることで、モジュールのスタイルが1箇所にまとまって管理しやすい。

ようへい | Reactエンジニアようへい | Reactエンジニア

適応度の深度

詳細度を高くしすぎないのは納得できたが、かといって子要素はクラスセレクタではなく要素セレクタにすることを推奨しているのは意外だった。
クラスセレクタのほうが柔軟な変更に対応できるから良いと考えていたが、クラスだらけになるのは「当然のことながらすべてのパラグラフ(子要素)に対してクラス名を付与するような少し前の時代に戻ることは避けたい。」ということらしい。
個人的にはそこも説明してほしかったが、そこまで柔軟性をもたせる必要がほとんどの規模のサイトではないということで理解することにした。

ようへい | Reactエンジニアようへい | Reactエンジニア

パフォーマンスについて

大前提、当時時点の話。
HTMLは上から下に読み込まれることは知っていたが、実際に読み込みと描画の順番までは知らなかったので興味深かった。
この動画も古いけど、興味深かった。
https://youtu.be/ZTnIxIA5KGw
また、CSSは右から左に評価されていくため、一番右のセレクタをクラスセレクタにすることでパフォーマンスが上がりやすいのも興味深かった。
ただしワーストケースとベストケースのパフォーマンスを比較しても50msくらいの差しかなかったので、考慮してもいいけど多くの時間を費やすのはもったいないとのこと。

ようへい | Reactエンジニアようへい | Reactエンジニア

HTML5とSMACSS

SMACSSの思想はHTML4でもHTML5でも関係なく使えるようにしてある。
今ではHTML5が標準だが、当時はまだHTML5はでたばかりだったのだろう。
SMACSSはHTMLに依存しないようにするという設計思想があるので、要素セレクタではなくクラスセレクタを用いるのを推奨している。これは納得している。ただ「適応度の深度」のところでクラスセレクタをディスってたのはなんだったんだろう。未だにわからない。
もう1つ強調していたのは、子孫セレクタに対してスタイルを当てるのではなく、子セレクタに対してスタイルを当てることを推奨していた。
そうすることで同じスタイルを子孫要素に対しても使用することができるから。これは納得だ。

ようへい | Reactエンジニアようへい | Reactエンジニア

プリプロセッサの話が出てきたが、確かに最近のコーディングではCSSをそのまま記述することは少なくなってきている。
SCSSなどで記述したものをビルドして使用するのが一般的になりつつある。
もちろんnpmなどに抵抗のない人限定だとは思うが。
ともかく今はそういったプリプロセッサに合わせた設計論が必要になっているのだろう。

ようへい | Reactエンジニアようへい | Reactエンジニア

SCSSでメディアクエリを入れ子にできるのも確かに便利。
SMACSSのメディアクエリをモジュールの近くに記述するという原理をシンプルに表現できる。

ようへい | Reactエンジニアようへい | Reactエンジニア

基本的にベースルールには変更の必要がないスタイルを記述する。
変更の必要がありそうなスタイルの場合は、モジュールとして記述する。
確かにこの辺は混乱しがちなので気をつけたい。

ようへい | Reactエンジニアようへい | Reactエンジニア

CSSスプライトという実装方法があるのを初めて知った。
現代に生きる自分的には複数画像で対応しなよって思ってしまうが、当時は通信の許容量も少なかっただろうからいろんな工夫をしていたんだろう。
今もコーダーの人たちは使っている技法なのだろうか?
ちょっと調べた感じだと今はあまりやられてなさそう。
CSSで画像をずらすなんて古典的な感じがするもんなぁ。
考え方としては勉強になるので、知識としてはあってもいいかもしれない。

ようへい | Reactエンジニアようへい | Reactエンジニア

FLOCSS

FLOCSSはいろんな設計パターンを組み合わせて今風にした感じ。
SCSSを使うことを想定した設計パターンになっている。
とはいえ最終更新日が7年前(2018年)だからもしかするとまた新しい設計論が出てるかも。

componentに色はつけない

componentで「最低限の機能を持ったものとして定義されるべきであり、それ自体が固有の幅や色などの特色を持つことは避けるのが望ましい」と書いてあったが、知らなかったのでちゃんと学んでおいてよかった。普通にやっちゃってたしやっちゃってるコードを見たことある。

modifier自体にはスタイルをつけない

命名規則のところで、modifierにはis-*というクラス名を使うが、それ自体にはスタイルを当てないというのは、あまりやる必要がなかったのでやらなかったがすごく大事なことだなと思った。
デフォルトのスタイルが本来のスタイルを汚染してしまうというのは、かなり重要な視点だなと思った。

プレフィクス

ハイフンじゃなくてキャメルケースでもいいってことかな。
ならキャメルケースの方が個人的にはいい。

ようへい | Reactエンジニアようへい | Reactエンジニア

カスケーディング

  • 同じレイヤーでカスケーディングするのはだめ。
  • componentがprojectからカスケーディングするのはokだが、逆はだめ。
  • カスケーディングする場合は親セレクタは1つだけ。
  • カスケーディングする場合はなるべく>を使って子要素だけに限定する。
  • modifierやbemのelementの使用も検討してみる。

componentの内部に関するスタイルはcomponentの分岐としてコーディングすればいいから、基本的にはmarginなどのレイアウトに関わる部分のスタイルを想定しているんだろうな。

Extend

smacssの思想と同じ。他のモジュールではextendしない。

このスクラップは2025/02/28にクローズされました