🎨

BEMとCSS ModulesとStyled componentsでクラス名の名前空間はどう違う?

3 min read

はじめに

有名なCSSの開発パターンであるBEM, CSS Modules, Styled componentsにおいて、それぞれのクラス名がどのような名前空間になっているのか把握したく整理してみました。

前提条件はフロントエンドの最大公約数と思わしきcreate-react-appです。CSS Modulesはこれ以外にも設定を自由に変えられるのでその点ご了承ください。

TL:DR

BEM CSS Modules Styled components
"Block__element--modifier" "Filename_className__Hash" "ComponentName-sc-Hash Hash"
"FileName__ComponentName-sc-Hash Hash"

BEM

お馴染みのBlock__element--modifierです。

Button.css
.Button {
  background-color: black;
  color: white;
}

.Button--primary {
  background-color: blue;
}

.Button--danger {
  background-color: red;
}
Button.js
import './Button.css'

// variant propが指定されたらmodifierに対応するクラス名を追加
// このようなクラス名の出し分けは色々な書き方がありそうですが...
const getClassNameArray = (variant) => ['Button', ...(variant ? [`Button--${variant}`] : [])]

const Button = ({ variant, ...rest }) => {
  return <button className={getClassNameArray(variant).join(' ')} {...rest} />
}

export default Button

CSS Modules

Filename_className__Hashになります。

Button.module.css
.base {
  background-color: black;
  color: white;
}

.primary {
  background-color: blue;
}

.danger {
  background-color: red;
}

Button.js
import styles from './Button.module.css'

const getClassNameArray = (variant) => [styles.base, ...(variant ? [styles[variant]] : [])]

const Button = ({ variant, ...rest }) => {
  return <button className={getClassNameArray(variant).join(' ')} {...rest} />
}

export default Button

Styled components (Babelプラグイン前提)

暗黙的な処理があります。
大抵は前者のパターンで書くのではないかと思います。

コンポーネント名 = コンポーネントを記述したファイル名

コンポーネント名-Hashになります。

Button.js

import styled, { css } from 'styled-components/macro'

const Button = styled.button`
  background-color: black;
  color: white;

  ${({ variant }) =>
    variant === 'primary' &&
    css`
      background-color: blue;
    `}

  ${({ variant }) =>
    variant === 'danger' &&
    css`
      background-color: red;
    `}
`

export default Button

コンポーネント名 ≠ コンポーネントを記述したファイル名

ファイル名__コンポーネント名-Hashになります。

Button.js

import styled, { css } from 'styled-components/macro'

const Component = styled.button`
  background-color: black;
  color: white;

  ${({ variant }) =>
    variant === 'primary' &&
    css`
      background-color: blue;
    `}

  ${({ variant }) =>
    variant === 'danger' &&
    css`
      background-color: red;
    `}
`

export default Component

おわりに

BEMとCSS ModulesとStyled components、ブロックスコープと名前空間という点では似た設計思想ですが細かい実装となると1対1で対応してはいないのでそれぞれ把握しておきたいですね。

サンプルはこちらです。

ちなみに私はEmotionが一番好きです。

Discussion

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