css-loaderでscoped cssを手に入れる


この記事はcss-loaderでscoped cssを触ってみたときのメモ程度の記事です。実際にこれを使ってなにか作ってみたわけではないのでハマりどころなど理解していません。間違いがあればご指摘よろしくお願いします。


webpack/css-loader: css loader module for webpack

css-loaderでscoped cssを実現する方法としてlocal scopecss modulesという2つ方法がある。2つの違いはdefaultのscopeがlocalになるかglobalになるかだけ。

どちらも該当のclassセレクタを他と名前が衝突しない一意性のあるclass名に変換してscoped cssの実現している。つまりBEMのような命名規則を意識せずによくなる。

local scope

css-loaderはdefaultがglobal scopeで:local(.className)または:local{...}と宣言した場合にclassNameがハッシュ化されexportされる。

selectorはJavaScriptから参照しやすいようにキャメルケースが推奨されている。

CSS Modules

css-loaderの設定にmodulesオプションを渡すとdefaultでセレクタがscoped cssの対象となりハッシュ化され、逆に:globalを宣言した場合にglobal scopeとして処理される。

"css-loader?modules"

HTMLへの適用方法

React.js

foo.css
:local {
  .foo {
    background: blue;
  }
}
import styles from './foo.css';
export default class Foo extends Component {
  render() {
    return <div className={styles.foo} />;
  }
};

Vue.js

Introduction | Introduction
Scoped CSS | Introduction

vue-loaderを使って単一ファイルコンポーネントを使うのが手軽。vue-loaderも裏でcss-loaderを使ってる。

<style scoped>
.foo {
  color: red;
}
</style>

<template>
  <div class="foo">hi</div>
</template>

その他

React.js, Vue.jsしか触ったことないので他のことはわからないが、ReactのようにJavaScriptの世界にテンプレートを持つようなフレームワークならReactと同じようにいけそう。

またcss-loaderやJavaScriptフレームワークを使わない場合はcss-modules/postcss-modules: PostCSS plugin to use CSS Modules everywhereを使ってlocal classをHTMLに適用できるらしい。

scoped cssを導入した際のCSS設計

CSS設計を意識しているつもりでいつの間にか破綻する自分向けCSS戦略。(実際に使ってみたわけではないので思いつきレベルです。)

local scopeで書かれているclassはcomposeという他のlocal scope classのstyle定義を再利用するための特別なプロパティがあるが、これはsassのextendみたいなもの(間違っていたらごめんなさい)で、一貫性をもって使っていくのが難しい気がする。

cssをすべてmoduleで書きJavaScriptファイルで呼び出して依存classを適用するのはつらそうなので、FLOCSSでいうところのFoundation, Layout, Object/Component層はお気に入りのCSSフレームワークをglobal scopeで今まで通り適用し、Object/Project層でBEMで頑張っていた箇所をscoped cssにするくらいが今までの方針を大きく変えずに導入していけそう。

感想

いままでcss modulesの存在だけ知っていて、どうせ導入めんどくさいんでしょと思ってまったくチェックしてなかったんだけど、あまりの手軽さに驚いた。BEMが苦手な自分としては採用しない理由はない。

webpack, css-loaderを使っていたならまったく難しいことせず、すぐ導入できるかと思います。
詳しい解説は以下に目を通してください。
webpack/css-loader: css loader module for webpack
CSS Modules 所感 - morishitter blog