💡

CSSモジュールはこう書きたい

2022/09/07に公開約2,300字

React.jsとCSSモジュール(CSS Modules)を採用するとき、こういう指針でコーディングできたらという所感です。

CSSよりSass

CSS1本で抽象化できるメンバーが揃うと言い切れる場合を除き、基本的にはスタイル抽象化のためにSass(scss)を導入するのが無難です。

理想とは違い、現実的に全てのスタイル定義がコンポーネントの区切りに適合する訳ではないと感じます。例えばcreate-react-app公式に書いてあるような「コンポーネントがあればプリプロセッサは不要(要約)」[1]という世界はまだ遠いです。

コンポーネントとscssは1対1

これが一番の原則で、Some.tsxSome.module.scssを1対1で関連付けることを守って欲しいです。 そうでないと途端に治安が悪化します。

# 例
src/path/Todo.module.scss
src/path/Todo.tsx
src/another-path/Header.module.scss
src/another-path/Header.tsx
...

冒頭の原則がプロジェククトに浸透するかはコンポーネント志向CSSがどれだけ共有できるかに依ります。SMACSSやFLOCSSなどの多機能なCSSクラスを統制して実装されたアプリケーションも普通に存在し、その選択肢も含めて方向性を認識する必要があります。

ネストは最小限に抑える

3重以上の親子・子孫セレクタを駆使するよりは粒度の小さいセレクタが好みです。言い換えれば、こちらの記事では「CSSがDOMを知っている」より「DOMがCSSを知っている」タイプ。

https://zenn.dev/takepepe/articles/css-always-breaks#「詳細度・dom-概念は無視した方が楽」という選択

単にコーディング量を削減するためではなく、次のように「個別のスタイルよりも2つ揃って完成する」度合いが強いときに数段階のネストを適用します。

  • ulに対するli、dlに対するdiv
  • パーツ単位のUIに被せるための親スタイル
  • その他、フクロウセレクタ等...

クラスは気楽に命名する

CSSモジュールを採用する場合、大抵はCRAデフォルトのようにコンポーネント名が先頭に付きます。このBlock名でスコープが担保されていると考えると、末端の命名は多少こだわりすぎなくてもOKです。

例えば「blog」のような機能名も、「leftArea」「rightArea」「bigText」といったスタイルの名称もアリです。そのように直感的な想像しやすさを重視します。

汎用クラスを適度に当てる

CSSモジュールは「utility first」ではないですが、第2の選択肢として適度に取り入れると楽です。ただし迷うなら基本的には汎用クラスは使わないという気持ちで挑むことを推奨します。

composesは使わない

composesは共通クラスをセレクタに挿入して自動適用してくれる機能で、スタイルシートのファイルがDRYになります。プロセスは次のように、HTMLに共通クラスが当てられる結果になります。[2]

Foo.module.scss
.common { /* ... */}
.primary {composes: common; /* ... */}
.danger {composes: common; /* ... */}
Foo.tsx
return <div className={styles.primary} />
// output: class="Foo_common_hash Foo_primary_hash"
return <div className={styles.danger} />
// output: class="Foo_common_hash Foo_danger_hash"

この隠蔽はさほど旨味を感じないので、混乱を避けるために使わなくていいと思っています。

CSS-in-JSをできるだけ入れない

動的なスタイルのpropsを受け取るコンポーネントを作りたくEmotion等を入れたくなるときが来ますが、スタイルの優先順位から一貫性が消えて狂うので可能な限り他のCSSライブラリを入れないことを推奨します。代わりの対処は次のものがあります:

  • 愚直に静的なスタイルを頑張って書く
  • Sassの機能を使う
  • インラインスタイルの機能を使う

ビルドしてから初めてスタイルが崩れて、本番の画面を見て落ち込んだりします(実体験)

脚注
  1. https://create-react-app.dev/docs/adding-a-sass-stylesheet/ ↩︎

  2. https://github.com/css-modules/css-modules#composition ↩︎

Discussion

ログインするとコメントできます