112
56

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

コードの違いを比較!emotionとstyled-componentsの両方を使ってみた

Last updated at Posted at 2020-05-06

この記事はこんな人にオススメ

  • React で CSS in JS の導入に当たって、emotion と styled-components のどちらを使おうかと悩んだので、両方をお試ししてみました。今回はお試しした比較・コードをまとめた記事です。
  • CSS in JS 使ってみたいけどどんな書き方するのかわからないな〜っていう人はこちらを読んでなんとなく書き方を把握してもらえると嬉しいです!

今回のお試しコードについて

  • 本記事はあくまで CSS in JS(emotion / styled-components)のみにフォーカスした記事です。
    • className を使った通常の css でのスタイリングをしない理由は、スタイリングのスコープが可能、変数や関数といった JavaScript のロジックが使用できるというメリットがあるためです。
  • 今回はスタイリングの書き方比較のみをまとめたので、React の導入、import、export などは省略しています。
  • 下記で紹介しているコードはこちらにあります

使ってみた結論

  • 今のところ styled-components より emotion がよさそう!
    • CSS Props が便利!
    • styled-components の機能もほぼ使える
  • 以下にそれぞれのメリット・デメリットとコード例を紹介していきます。

emotion

メリット

  • 何より CSS Props が便利!(追加の import いらずで使用可能)
  • 様々な機能を import なしで利用可能(CSS Props, media Query など)
  • emotion/styled を import すると、styled-components の一部機能が使える

デメリット

  • styled-components と比較して利用者数が少なく、記事なども少ない

styled-compoents

メリット

デメリット

  • スタイリングを目的とした要素を用意する必要がある
    • スタイルは使い回しでタグの要素だけ変更したい場合も、都度新しい要素を作成することになる
  • 要素の宣言がスタイル側にあるため、DOM構造が視覚的に分かりにくい
    button、p などの要素指定がスタイル側に記述される

emotion でのスタイリング

  • インライン記法もできますが、業務ではなかなか使う機会がないため割愛します。
  • 上記メリットにも記載しましたが、styled-components でのスタイリングも可能です。

CSS Props

※分かりやすくするために、以下のコードは React のコードの、レンダリング層とスタイリング層のみ記載しています。

CSS Props(オブジェクト記法)

  • css={hoge}で class 名の指定が可能です。
  • プロパティの書き方が従来の CSS とは少し違う書き方になります。
cssProps.jsx
return (
    <p css={base}>CSS Props(オブジェクト記法)</p>
);

const base = css({
  backgroundColor: "#eee",
  fontSize: "20px",
  padding: "15px"
});

表示結果
スクリーンショット 2020-03-08 19.41.42.png

CSS Props(タグ付きテンプレートリテラル)

  • こちらはプロパティの書き方が従来の CSS と同様の書き方になり、とっつきやすい記法です。
  • emotion で一番ベーシックな書き方になります。
tagliteral.jsx
return (
    <p css={tagliteral}>CSS Props(タグ付きテンプレートリテラル)</p>
);

const tagliteral = css`
  background-color: #ffc0cb;
  font-size: 20px;
  padding: 15px;
`;

表示結果
スクリーンショット 2020-03-08 19.44.49.png

Composition(extend)

  • Composition を使うことで、css で言うところの extend をすることが可能です。
  • 今回は上記に記載した base のスタイルを読み込んでいます。

オブジェクト記法 Composition(extend)

  • プロパティの書き方が従来の CSS とは少し違う書き方の継承法です。
tagcomposition.jsx
return (
    <p css={objectcomposition}>Composition(オブジェクト記法)</p>
);

const objectcomposition = css(base, {
  color: "#db7093"
});

表示結果
スクリーンショット 2020-05-06 13.18.19.png

タグ付きテンプレートリテラルでの Composition(extend)

  • プロパティの書き方が従来の CSS と同様の書き方の継承法です。
  • sass の extend とも見た目が近いですね。
tagcomposition.jsx
return (
  <p css={tagcomposition}>Composition(タグ付きテンプレートリテラル)</p>
);

const tagcomposition = css`
  ${base};
  font-weight: bold;
`;

表示結果
スクリーンショット 2020-05-06 13.18.45.png

並列 class

  • 複数のスタイル設定を同時に指定することも可能です。
parallel.jsx
return (
  <p css={[base, parallel]}>並列 class</p>
);

const parallel = css`
  border: solid #4682b4 2px;
`;

表示結果
スクリーンショット 2020-05-06 12.53.05.png

ネスト(入れ子)

  • sass のようにネストすることができます。
  • ただ、後からコンポーネント分割するときに分割しずらくなることがあり、あまりオススメはしません。
nest.jsx
return (
  <p css={nest}>
  <span>ネスト</span>記法
  </p>
);

const nest = css`
  background-color: #b0c4de;
  font-size: 20px;
  padding: 10px;
  span {
    background-color: #4682b4;
    padding: 5px;
  }
`;

表示結果
スクリーンショット 2020-03-08 18.57.57.png

グローバル

  • Groba を import した上で使用します

    import { Global, css, jsx } from "emotion/core";
grobal.jsx
return (
  <Global styles={globalStyle} />
);

const globalStyle = css`
  html {
    background-color: #008b8b;
  }
`;

style宣言のコードをまとめる

  • class 毎に毎回 const で宣言するのではなく、ひとまとめにして固まり毎に記載することができます。
styles.jsx
return (
  <p css={[styles.basetext, styles.boldtext]}>CSS 宣言をひとまとめに</p>
);
const styles = {
  basetext: css`
    background-color: #eee;
    font-size: 20px;
    padding: 15px;
  `,
  boldtext: css`
    font-weight: bold;
  `
};

表示結果
スクリーンショット 2020-05-06 13.01.23.png

styled-components でのスタイリング

基本系

  • DOM 要素の宣言はpdivなどではなく、任意で作成した名前を宣言します。
  • スタイル設定時に DOM 要素を設定します。
base.jsx
return (
  <BaseText>基本のスタイリング</BaseText>
)

const BaseText = styled.p`
  background-color: #eee;
  font-size: 20px;
  padding: 15px;
`;

表示結果
スクリーンショット 2020-05-06 0.22.16.png

extend

  • emotion の オブジェクト記法での Composition に近い書き方になりますが、こちらは CSS プロパティが従来と同様の書き方になります。
extend.jsx
return (
  <ExtendText>extend</ExtendText>
)

const ExtendText = styled(BaseText)`
  font-weight: bold;
`;

表示結果
スクリーンショット 2020-05-06 12.34.54.png

ネスト(入れ子)

  • sass と同様の書き方で記載が可能です。
nest.jsx
return (
  <NestText>
    <span>ネスト</span>記法
  </NestText>
)

const NestText = styled.p`
  background-color: #b0c4de;
  font-size: 20px;
  padding: 10px;
  span {
    background-color: #4682b4;
    padding: 5px;
  }
`;

表示結果
スクリーンショット 2020-05-06 12.35.17.png

グローバル

grobal.jsx
return (
  <GlobalStyle />
)

const GlobalStyle = createGlobalStyle`
  html {
    background-color: #008b8b;
  }
`;

CSS Props

  • styled-components の v4 から CSS Props が使用可能です。

    詳細はこちら
  • 2020/5/5 現時点で、emotion の CSS Props のように、class 名のような形での機能はありません。
cssprops.jsx
return (
  <p
    css={`
      background-color: #ffc0cb;
      font-size: 20px;
      padding: 15px;
    `}
  >
    CSS Props
  </p>
)

表示結果
スクリーンショット 2020-05-06 12.35.25.png

最後に

  • 書き方は色々あれども、結構通常の CSS の書き方に近いので、最初の導入ハードルを超えてしまえば運用自体はなんとかなりそうですね。
  • styled-components で emotion のような CSS Props(class名を指定する形)が実現すると一番いいなぁと思います。これからのバージョンアップに期待…!
112
56
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
112
56

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?