🐹

CSS Modules の composes: xxx from global; って知ってる?

2022/11/09に公開

はじめに

ドワンゴでニコニコ生放送のWebフロントエンジニアをやっています misuken です。

今回は、意外と知られてないかもしれないCSS Modulesの機能 composes: xxx from global; について紹介します。

from global とは

公式ドキュメントのComposing from global class namesに書いてある通り、以下のように書いたセレクタをコンポーネントに適用すると、ハッシュなしのクラス名をHTMLへ反映することができます。

foo.module.css
.foo {
  composes: a b c from global;
}
Foo.tsx
import classNames from "./foo.module.css";

export const Foo = () => <div className={classNames.foo}></div>;
<div class="foo a b c"></div>

from global の使いみち

CSS Modulesを使うと、全てのクラスにハッシュが付いてくれるので便利な半面、ハッシュなしのクラスを使えたほうが良い場合もあります。(:global的な使い方ではなく)

  • グローバルなクラスセレクタと連携したい場合
  • ハッシュ付きクラス名とハッシュなしクラス名を子結合子子孫結合子を組み合わせる場合
  • ファイル間を横断して作用させたい場合

特にスタイルに依存した理由でハッシュなしクラス名を使用したい場合、js側で追加するよりも、CSS側で指定できたほうが、責務を適切に閉じられます。

当然影響範囲が広がればリスクも生じるので、適切な管理のもとに使用しましょう。

from global は知られているのか?

最初に「意外と知られてないかもしれない」と書いたには理由があります。

個人的にcomposesでハッシュなしクラス名を指定したい場面は、2016年頃にCSS Modulesを使い始めた頃から存在し、色々な書き方を試してみたものの実現することができず諦めていたからです。

その後も何度もcomposesでハッシュなしクラス名が指定できたら便利なんだけどなぁ。。。と思ったことがありました。

そんな中、公式ドキュメントを眺めていたところ、なんか見慣れない記述が記載されていました。
公式ドキュメントはやっぱりちゃんと読むべきだなぁ、と思ったのですが。。。

たしか2016年の段階で記述方法に関してはしっかり見た気がするので、改めてリポジトリを見てみました。

すると、2017年10月になにやら更新された様子が見て取れます。

このissue経由でドキュメントに追加されたようです。
https://github.com/css-modules/css-modules/issues/267#issuecomment-339756464

どおりで気付かなかったわけですね。
2017年10月以降にCSS Modulesを使い始めた人のほうが認知度が高いかもしれません。

from global はいつから使えたのか?

ここで新たに一つ疑問が生まれます。
ドキュメントに追加されたのは2017年10月。
しかし、css-loaderなどに含まれる実装側はいつから使えるようになったのか?

それがわかる情報が以下のissueに書いてあります。
https://github.com/css-modules/css-modules/issues/49#issuecomment-149479041

どうやら、2015年の段階ですでに使える状態だったようです。
issueのやり取りの中で、何度もドキュメントに追加する流れがあったことが見て取れますが、なぜか記載されることはなく、知る人ぞ知る隠し機能として存在していたと思われます。

2016年に知りたかった。。。

Next.jsのCSS Modules

CSS ModulesをビルトインサポートしているNext.jsでも問題なくfrom globalはサポートされていました。

まとめ

使う場面はそれほど多くないかもしれませんが、使いたくなったときに知ってると知らないでは大きく手間が変わってくるfrom globalは、少し特殊な歴史を辿ってきたことがわかりました。

ニコニコ生放送では、これが使えることで実装を大きく改善できた部分があり、非常に重宝しています。

composesでハッシュなしセレクタを使いたいなぁと思ったことのある方は、ぜひ試してみてはいかがでしょうか。

Discussion