🌞

CSS in JSライブラリ「emotion」のすすめ

2020/12/27に公開

React/Nextでスタイリングをどうすればいいか最近ずっと考えていた(いる)のですが、だんだんまとまってきたので書いておこうと思います。

CSS ModuleからCSS in JSへ

自分はもともとCSS Modules(SASS)を使っていたのですが、アニメーションライブラリとの相性で不具合があった(後に解決したのですが)ことや、Atomic Designを導入するとファイル構造をどうすればいいのか迷いまくっていたことから、CSS in JSに乗り換えを検討する流れになりました。

一番困っていたのがファイル構造で、atomsに当たるような一番小さいコンポーネントにもcss/sassファイルを作らなければならないのが個人的にすごく嫌で、小さくコンポーネントを分離させるのに抵抗ができてしまうなぁと思っていました。

CSS in JSライブラリ選定

主な検討項目としては

  1. マークアップのタグ自体を変数にはしたくない(どれがピュアなhtmlかぱっと見でわかりづらくなるので)
  2. mixinやconfigなどは一つにまとめて、グローバルで使いまわせるようにしたい
  3. コンポーネント間で柔軟にスタイルの上書きなどができるようにしたい
  4. なるべくReact/Nextを使わないひとでも理解しやすいものにしたい

といったことを中心にライブラリ選定しました。

検討したのは、主に次の3つです。

  • styled-components
  • styled-jsx
  • emotion

styled-componentsは、1が解決できなそうだったので×
styled-jsxは2が解決できなそうだったので×

ということで、emotionを使うことにしました。

emotionの良さ

コードはNext.jsを使ってる例です。

使い勝手

cssプロパティに@emotion/reactからインポートしたcssを返せばいいので、ピュアなhtmlのタグ名のままスタイルを適用することができます。

import { css } from '@emotion/react'

export const Hoge: React.FC = () => (
  <div css={hoge}>
    <p>hoge</p>
  </div>
)
const hoge = css`
  margin: 100px auto 0;
`

関数化して柔軟にスタイルの上書き等も行うことができます。(これが良いかは別として)
同じように、グローバルにメディアクエリなどのmixinの関数を置いておいて使いまわすこともできます。

import { css, SerializedStyles } from '@emotion/react'

type Props = {
  text: string
  _css?: SerializedStyles
}

const H1: React.FC<Props> = ({ text, _css }) => (
  <h1 css={title(_css)}>{text}</h1>
)

const title = (_css: SerializedStyles): SerializedStyles => css`
  position: relative;
  font-size: 50px;
  line-height: 1;
  ${_css}
`

パフォーマンス

styled-componentsよりも若干emotionのほうがパフォーマンスが良いようです。
参考:Styled components vs Emotion js: A performance perspective

今後のメンテナンス性(トレンド)

現在はstyled-componentsのほうがemotionよりも人気のようです。
参考:SassからCSS Modules、そしてstyled-componentsに乗り換えた話
運用を伴う大きなプロジェクトで使用するには今後のメンテンナンス性が大きく影響しますが、自分は広告制作会社勤務で運用なども発生する案件が少ないため、そこまで重要視しませんでした。

GitHubで編集を提案

Discussion