15
9

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.

[React] styled-component を利用する際の最初に知っておきたいことまとめ

Posted at

はじめに

これまでVuejsで開発をしてきたのですが、新しいプロジェクトでReactを利用することになりました。
キャッチアップのために、CSS in JS の代表的なライブラリの1つであるstyled-componentsを利用して簡単なWebサイトを作成しました。

実装を進める中で自分が調査して、なるほどと思ったポイントをまとめました。

[作成したサイト]

[Github]

CSS in JS について

Reactのスタイリングの方法について

CSS in JS について説明する前にまず基本として、Reactでは要素をどのようにスタイリングするかについて記載します。

Reactでは、要素のスタイリングに下記の2つの方法を用意しています。

  1. 通常のHTMLでスタイリングをするようにcssファイルを別に指定して、classNameプロパティに指定する
  2. Reactエレメントのstyleプロパティにcssに解釈できるオブジェクトを渡して、スタイリングを行う

React公式では、パフォーマンスの観点から1の方法を推奨しています。

この公式の見解をそのまま当てはめるとcssファイルでスタイリングは定義したほうがいいとなります。

ただしCSSはグローバルスコープなので、比較的大きめのアプリケーションを実装する場合には名前の衝突やスタイルの影響範囲などをどのように担保するかの解決方法を検討する必要があります。

CSS in JS をなぜ利用するか

CSS in JS は、cssの定義をjsファイルに記載して、上記の2のようにインラインスタイルで定義することでcssのスコープをそのコンポーネントに閉じようというコンセプトでスタイリングを行う手法です。

Facebookの@Vjeuxさんの「React: CSS in JS」 でこの手法が有名になったようで現在では様々なライブラリが実装されています。

CSS in JS を採用する理由は、主に下記です。

  • cssのスコープを対象のコンポーネントに閉じることでスタイル崩れを心配することなく開発したい
  • JSXで記載したHTMLの構造とcssのスタイルを一緒に管理できる
  • JSの既存のツールを利用して、静的解析やコードの入力補完がしやすい

[CSS in JS の各ライブラリ]

2021年 CSS in JS のライブラリはかなり色々と出ています。

  • Emotion
  • styled-components
  • JSS
  • glamorous
  • Linaria
  • CSS Modules

などがざっと調べただけでも出てきます。

npm trend を確認すると、emotion が一番人気ですが、jss / styled-components もかなり近いレベルで採用されているようです。

最初はemotionを利用してみようと思ったのですが、css記法を利用する際には JSX Pragmaの対応が必要とのことでまずはReactに慣れることを優先して簡単に導入できるstyled-componentsを採用しました。

(v4以降ではstyled-componentsでもcss propに対応したため、css propを利用したいという場合でもstyled-componentsで対応できるようになりました。)

styled-componentsでできること

styled-componentsはReactコンポーネントをCSSでスタイルすることが主な目的なのですが、下記のように様々なスタイリングのパターンに対応しています。

styled-componentsの使い方をざっくり知りたいという入門者向けの情報

まずは、ざっくりstyled-componentsの使い方が知りたいという方は下記のリンクが参考になります。

公式サイト:
https://styled-components.com/docs/basics#motivation

styled-componentsの使い方の初歩を丁寧に解説してくれている
https://www.webprofessional.jp/style-react-components-styled-components/

styled-componentsの基本的な使い方、Theme, Global
https://akabeko.me/blog/2020/11/styled-components/

比較的新しめのstyled-componentsの機能の紹介

個人的にこんなことまでできるんだと驚いた最後に比較的新しめの機能を3つ紹介させていただきます。

  1. ポリモーフィズムによるHTMLタグの動的な切り替え
  2. css prop への対応
  3. transient props

1. ポリモーフィズムによるHTMLタグの動的な切り替え

これまではstyledの適用をする際にラップするHTML要素を決めなれけばならず、cssは同じだけどタグだけ変更したいとかpropsによって動的にHTMLの属性を変更したいというケースでは対応が難しい状態でした。

しかし、この機能を利用すれば、HTMLの属性をas propsによってrenderする際に決めることができます。
(乱用すると定義した場所でのタグの意味がなくなるので、注意は必要です。)

データによって表示を切り替える必要のある複雑なリストやグリッドを実装するときには重宝すると思います。

// as propsを利用した例:
import styled from "styled-components";

const Component = styled.div`
  color: red;
`;

render(
  <Component
    as="button"
  >
    Hello World!
  </Component>
)
 

上記のJSXは下記のようにbuttonタグに解釈されます。

// render されたHTML
<button class="sc-bqyKva ehfErK">Hello World!</button>
 

2. css prop への対応

以前はstyled-composentはcss propに対応できておらず、必ずスタイリング対象のHTMLタグが必要となっていたため無駄なDOMが構築されてしまうケースがありました。

CSS in JS系の有名なライブリとしてはemotionはcss propに対応できていたため、css prop が利用したい場合はstyled-composentを採用せず、emotionを利用することが多かったようです。

css propに対応できたことで今後はstyled-composentが採用されることも増えるかと思います。

補足ですが、Typescriptで利用する場合には、下記の記載を追加しないと型エラーが出るようなのでご注意ください。

import {} from 'styled-components/cssprop'

3. transient props

styled-composentで既存コンポーネントのスタイリングをpropsを利用して行う場合に、propsが意図せず伝播してしまうことがありました。

少しわかりにくいので、例で説明します。

下記のように普通にスタイリングを行うと、Containerコンポーネントにのみprops.colorを適用させたい場合でもTextにまでprops.colorが伝播されてしまいます。

// 普通にスタイリングした場合
import styled from "styled-components";
const Text = props => <p {...props} />;
const Container = styled(Text)`
  color: ${p => p.color};
`;
// colorがTextにまで伝播してしまう
<Container color="blue">Hello world!</Container>

この例のように自作コンポーネントの場合は、注意して実装すれば問題ないのですが、ライブラリなどで実装されたコンポーネント(例えば react-routerのなど) は自分でpropsを設定できないので伝播させたくない場合に困ってしまいます。

このような場合には、対象のpropsに$を利用することでpropsを伝播させなくするのがtransient props の機能です。

// 普通にスタイリングした場合
import styled from "styled-components";
const Text = props => <p {...props} />;
const Container = styled(Text)`
  color: ${p => p.$color};
`;
// colorはContainer
<Container $color="blue">Hello world!</Container>

transient props の詳細な仕様については下記の記事が詳しいので、気になる方はご参照ください。

参考リンク

15
9
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
15
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?