【React】Emotionの使い方【基本から応用まで解説】

【React】Emotionの使い方【基本から応用まで解説】
ADVERTISEMENT
  • 「React開発でEmotionを導入したい」

  • 「styled-componentsより使える?」

  • 「TypescriptでEmotionを使いたい」

  • 「Emotion使ってみたけど、なんかCSSが適用されないんだけど...」

上記の悩みにお答えします。

Emotion」はJavaScriptでCSSを記述するために作られたライブラリで、いわゆるCSS-in-JSのひとつです。

同じCSS-in-JSの中で、「styled-components」というものがあります。 Emotionstyled-componentsはよく比べられますよね。

Emotionを使うべきなのか、どうやって使えばいいのか悩んでいる方も多いはず。

そこで、この記事ではReactでEmotionを使う方法を解説します。

内容は以下です。

  • Emotionを使うメリット

  • Emotionの導入

  • 基本的な使い方

  • 応用的な使い方

  • styled-componentsみたいに使う

Emotionを使うメリット

主に以下の2つ。

  • タグが見分けやすい

  • styled-componentsの書き方もできる

タグが見分けやすい

Emotionの方がタグを見分けやすいです。 タグっていうのは、「div」とか「h1」とかのことですね。

styled-componentsだと、タグが見分けにくいと言われています。

サンプルのコードが以下です。

jsx /* styled-componentsの場合 */ <Wrapper> <Title>RalaCode</Title> <SubTitle>Web開発で経験した試行錯誤を発信</SubTitle> <More href="/">詳しく見る</More> </Wrapper>

一部省略してますが、上記がstyled-componentsのコード。 styled-componentsでは「div」や「h1」などのタグを、「Wrapper」や「Title」という自作のタグに変換することになります。

これだとパッと見、どれが「div」なのか「h1」なのかわかりにくいですよね。

Emotionの場合だと、以下です。

jsx /* Emotionの場合 */ <div css={wrapper}> <h1 css={title}>RalaCode</h1> <p css={subTitle}>Web開発で経験した試行錯誤を発信</p> <a href="#" css={more}>詳しく見る</a> </div>

Emotionでは「css」という属性を使います。 これなら、タグを見分けやすいですよね。

styled-componentsの書き方もできる

Emotionはstyled-componentsより後に開発されたものです。 実は、Emotionを導入すればstyled-componentsの書き方もできます。

そのやり方は後ほど解説します。

Emotionの環境さえあれば、Emotionもstyled-componentsも使えます。 万能ですよね。

Emotionの導入

一応、公式サイトにもEmotionの導入方法が解説されています。 リンクは以下です。

>> Emotionの公式サイトへ

公式サイトは英語なので、読むのが少し面倒かもです。 ここでは日本語でわかりやすく解説します。

まず、Reactプロジェクトを作ります。

bash $ npx create-react-app emotion-sample

Typescriptを使う場合は、以下です。

bash $ npx create-react-app emotion-sample --template typescript

プロジェクトのフォルダに移動して、開発サーバーが起動できるか確認しておきましょう。

bash $ cd emotion-sample

bash $ npm start

確認できたら、いったん開発サーバーは終了させておきます。 Windowsなら「Ctrl + "c"」、Macなら「control + "c"」です。

では、Emotionを導入します。

bash $ npm install @emotion/react

これで、Emotionの導入は完了です。 簡単ですね。

Emotionの基本的な使い方

では、実際にEmotionを使ってみます。

コードの書き方

App.jsを以下のように記述してください。

jsx /* App.js */ import { css } from "@emotion/react"; function App() { return ( <h1 css={css` color: red; `} > Hello, world! </h1> ); } export default App;

Hello, world!」という文字を表示してみました。 さらに、Emotionを使って「Hello, world!」の文字を赤色にするように設定しました。

これで、開発サーバーを起動してみましょう。

...ちゃんと表示されたでしょうか。

多分、「Hello, world!」の文字が黒色になっていませんか? 文字色を赤色に設定したはずなのに、変わっていませんよね?

JSX pragmaを設定する

実は、Emotionを使う場合は「ある設定」をしないといけません。 設定といっても、1行コードを追加するだけです。

では、App.jsに以下のような感じでコードを追加してください。

jsx /* App.js */ /** @jsxImportSource @emotion/react */ import { css } from "@emotion/react"; function App() { return ( <h1 css={css` color: red; `} > Hello, world! </h1> ); } export default App;

一番上の行に、以下のコードを追加しました。

/** @jsxImportSource @emotion/react */

JSX pragma」と呼ばれる記述です。

これでもう一度、「Hello, world!」の文字を確認してみてください。 赤色に変わっているはずです。

Emotionを使うコンポーネントでは、「JSX pragma」を書かないといけません。

Typescriptの場合は?

Typescriptの場合も「JSX pragma」を書いてください。 やることは他にありません。

ネットの情報を見ていると、「tsconfig.jsonに記述を加えましょう」みたいな説明があったりします。

具体的には、以下のような記述です。

javascript /* tsconfig.json */ { "compilerOptions": { ... 略..., "jsxImportSource": "@emotion/react" } }

「"jsxImportSource": "@emotion/react"」という記述ですね。

確かにこれを書けば、Typescript上で「css」というプロパティに型定義が通るようにはなります。 ですが、結局Emotionは動きません

TypescriptでEmotionを使う場合も、JSX pragmaを書かないといけません。 tsconfig.jsonは触る必要ありません。

「じゃあ、tsconfig.jsonに記述を加えるのはどういうときなの?」 って感じですよね。

例えば「NextJS + TypescriptでEmotionを使うとき」です。

NextJSであればJSX pragmaを書かなくてもEmotionが使える設定ができます。 しかし、「Emotionは使えるけどTypescriptで型エラーが出る」という状態になります。

その型エラーを防ぐために、tsconfig.jsonをいじらないといけないわけです。

なんかややこしいですよね。 いったんまとめます。

create-react-appで作ったReactプロジェクトでEmotionを使う場合は、JSX pragmaを書きましょう。 Typescriptの場合もJSX pragmaを書きましょう。 tsconfig.jsonは触らないでいいです。

Emotionの応用的な使い方

いくつかご紹介します。

コードをまとめる

今のApp.jsを見てみると、「Hello, world!」を表示するだけなのにコードがごちゃついてますよね。 まとめた書き方をするとわかりやすくなります。

jsx /* App.js */ /** @jsxImportSource @emotion/react */ import { css } from "@emotion/react"; const hello = css` color: red; ` function App() { return ( <h1 css={hello}>Hello, world!</h1> ); } export default App;

hello」という定数にスタイルをまとめました。

スタイルを結合する

スタイルを複数定義して、結合することができます。

jsx /* App.js */ /** @jsxImportSource @emotion/react */ import { css } from "@emotion/react"; /* ↓これ追加 */ const largeFont = css` font-size: 54px; @media (min-width: 768px) { font-size: 72px; } ` const hello = css` color: red; ` function App() { return ( // largeFontを追加↓ <h1 css={[hello, largeFont]}>Hello, world!</h1> ); } export default App;

largeFont」という新たなスタイルを定義して、結合してみました。 結合する場合は「css={[hello, largeFont]}のように、配列形式になるので注意です。

スタイルの中ではメディアクエリも使っています。

これで「Hello, world!」という文字が大きくなったと思います。

また、スタイル自体をまとめることもできます。

jsx /* App.js */ /** @jsxImportSource @emotion/react */ import { css } from "@emotion/react"; const largeFont = css` font-size: 54px; @media (min-width: 768px) { font-size: 72px; } ` const hello = css` /* ↓これ追加 */ ${largeFont} color: red; ` function App() { return ( // helloのみでOK↓ <h1 css={hello}>Hello, world!</h1> ); } export default App;

「largeFont」というスタイルを「hello」の中にまとめました。 「hello」というスタイルを適用するだけでよくなります。

「Hello, world!」の文字は、赤色で大きいままのはず。

グローバルスタイルを設定する

例えば、bodyタグにCSSを適用させたいときありますよね?

Emotionなら、それも簡単にできます。

App.jsを書き換えてみましょう。

jsx /* App.js */ /** @jsxImportSource @emotion/react */ /* 「Global」をimportする↓ */ import { css, Global } from "@emotion/react"; const largeFont = css` ... 略... ` const hello = css` ... 略 ... ` function App() { return ( <> {/* ↓「Global」を使ってbodyタグにスタイルを適用 */} <Global styles={css` body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",Helvetica, Arial, sans-serif; } `} /> <h1 css={hello}>Hello, world!</h1> </> ); } export default App;

まず、「Global」を@emotion/reactからimportします。 そして、「Global」でbodyタグにCSSを適用させています。

以下のように、グローバルスタイルをまとめてもOK。

jsx /* App.js */ /** @jsxImportSource @emotion/react */ import { css, Global } from "@emotion/react"; const largeFont = css` ... 略... ` const hello = css` ... 略 ... ` /* ↓グローバルスタイルを定義する */ const globalStyle = css` body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",Helvetica, Arial, sans-serif; } ` function App() { return ( <> {/* ↓「styles」の中身は「globalStyle」のみでOK */} <Global styles={globalStyle} /> <h1 css={hello}>Hello, world!</h1> </> ); } export default App;

これで、コードがすっきりしますね。

また、「Global」はApp.jsだけでなく、どのコンポーネントで使っても大丈夫です。

styled-componentsみたいに使う

Emotionを導入すれば、styled-componentsの書き方もできます。 そのためには、「@emotion/styled」というパッケージを追加でインストールします。

bash $ npm install @emotion/styled

では、App.jsを以下のようにごっそり書き換えてみます。

jsx /* App.js */ import styled from "@emotion/styled"; const Hello = styled.h1` color: red; ` function App() { return ( <Hello>Hello, world!</Hello> ); } export default App;

これで、「Hello, world!」が赤文字で表示されるはずです。

「@emotion/styled」でCSSを適用する場合は、「JSX pragma」は書かなくていいです。

ところで、

なんでわざわざstyled-componentsの書き方する必要があるの?

って思いませんでしたか?

styled-componentsのいいところは、「動的にCSSを変化させられること」です。

例えば、以下のようなことができます。

  • ある条件下では文字をにする

  • 別の条件下では文字をにする

App.jsを書き換えてみます。

jsx /* App.js */ import styled from "@emotion/styled"; const Hello = styled.h1` /* ↓このように書き換えます */ color: ${props => (props.blue ? "blue" : "red")}; ` function App() { return ( <> <Hello>Hello, world!</Hello> {/* ↓これ追加 */} <Hello blue>Hello, world!</Hello> </> ); } export default App;

「Hello, world!」を2つにしてみました。

片方には「blue」という条件をつけています。 「blue」という条件があるときは、文字色を青にするようにCSSを設定しました。

もう少し複雑なこともできます。 例えば、「ボタンを押すと文字色が変わる」みたいな機能。

そのやり方は以下の記事で解説してますので、合わせてどうぞ。

まとめ

最後に記事をまとめます。

React開発でEmotionを使うメリットは以下です。

  • タグが見分けやすい

  • styled-componentsの書き方もできる

@emotion/react」を使う場合は、「JSX pragma」を使わないといけないのが少しだけ面倒ですかね。

さらに、「@emotion/styled」を使えばstyled-componentsの書き方もできます。

styled-componentsなら、動的にCSSを変化させられます。

状況に応じて柔軟に使い分けられるのが、Emotionのいいところですね。

というわけで記事は以上です。

ADVERTISEMENT