🌀

Vite+React+TypeScriptで、CSSスタイルについて調べて、Emotionに流れ着いた

2022/02/25に公開

React調べること多すぎ・・・🤯
今回はReactのCSSスタイルついて調べてみました。

まとめ

いきなりまとめです。

ReactのCSSスタイルについての結論

  • これといった正解はない。
  • 将来どうなるかはわからない。
  • 今のメンバのスキルセットで、使いたいものを使えばいいんじゃないだろうか?

ということで、React(Vite + TypeScript)のCSSスタイルについて調べて、Emotionに流れ着いた経緯と、Emotionの導入方法についての記事です。

主要なもの

2022年2月24日時点で、ザクっと調べた主要なものです。
マイナーなものを含めるともっとありますが、今回は主要な以下の8つから選択します。

  1. Inline Styles
  2. Css Modules
  3. Styled JSX
  4. Styled Components
  5. Emotion
  6. Linaria
  7. Tailwind CSS
  8. Windi CSS

1. Inline Styles

Style属性に直接スタイルを指定します。
Css in JS (JavaScriptのコード中にCSSを書く手法)です。
開発時にちょこっと使うのに使用するようです。

サンプル
InlineStyle.tsx
export function InlineStyle() {
  return (
    <div style={{ width: "100%", padding: "20px", backgroundColor:"#CE6270"}}>
      <p style={{ color: "#FBBDAE", textAlign: "center" }}>Inline Style</p>
    </div>
  )
}

事前定義してスタイルに適用することもできます。

InlineStyle.tsx
const divStyle = {
  width: "100%", 
  padding: "20px", 
  backgroundColor:"#CE6270"
}
const textStyle = {
  color: "#FBBDAE",
  textAlign: "center"
}

export function InlineStyle() {
  return (
    <div style={divStyle}>
      <p style={textStyle}>Inline Style</p>
    </div>
  )
}

2. Css Modules

コンポーネントファイルとは別にcssファイルを用意し、従来のCSSの書き方で記述します。
Viteで標準サポートされています。
コンポーネントファイルとCSSファイルを分けるのでファイル数が増え見通しが悪くなります。

サンプル
CssModule.tsx
import styles from './CssModule.module.css';

export function CssModule() {
  return (
    <div className={styles.divstyle}>
      <p className={styles.textstyle}>CssModule</p>
    </div>
  )
}

「コンポーネント名.module.css」という名前でファイルを作る。

CssModule.module.css
.divstyle {
  width: 100%; 
  padding: 20px; 
  background-color: #CE6270;
}
.textstyle {
  color: #FBBDAE;
  text-align: center;
}

3. Styled JSX

コンポーネントファイルにcssを文字列で定義します。
従来のcssの書き方ができます。
Next.jsで標準サポートされています。
Vite+React+typescript環境で試したところ、TypeScriptコンパイラエラーと実行時に警告が発生しました。

サンプル
npm install styled-jsx --save-dev
export function StyledJsx() {
  return (
    <>
      <div className="divstyle">
        <p className="textstyle">StyledJsx</p>
      </div>
      <style jsx>{`
        .divstyle { 
          width: 100%; 
          padding: 20px; 
          background-color: #CE6270;
        }
        .textstyle { 
          color: #FBBDAE; 
          text-align: center;
        }
      `}</style>
    </>
  )
}

スタイルを事前定義することも可能です。
ただし、グローバルスタイルとスコープ付きスタイルを生成するそうです。
コチラのパターンはVite+React+typescript環境でエラーが発生し実行できませんでした。

import css from 'styled-jsx/css'

export function StyledJsx() {
  const styles = css`
  divStyle {
    width: '100%',
    padding: '20px', 
    background-color: '#CE6270'
  }

  textstyle = {
    color: '#FBBDAE',
    text-align: 'center'
  }
`
    return (
      <>
        <div className="divstyle">
          <p className="textstyle">StyledJsx2</p>
        </div>
        <style jsx>{styles}</style>
      </>
    )
  }

4. Styled Components

スタイルを当てたコンポーネントを定義します。
CSSを設定する要素ごとにコンポーネントを作ることになるため、HTMLとしての可読性が低くなります。

サンプル
npm install styled-components

npm install @types/styled-components --save-dev
import styled from 'styled-components'

export function StyledComponents() {
  return (
    <>
      <StyledDiv>
        <StyledP>StyledComponents</StyledP>
      </StyledDiv>
    </>
  )
}

const StyledDiv = styled.div`
  width: 100%; 
  padding: 20px; 
  background-color: #CE6270;
`

const StyledP = styled.p`
  color: #FBBDAE;
  text-align: center;
`

5. Emotion

Inline Styles、Styled JSX、Styled Componentsと同様の書き方ができます。
https://emotion.sh/docs/introduction

6. Linaria

Css in Js。
Cssはビルド時にCSSファイルに抽出される、ゼロランタイム。
Viteに導入するのは時期尚早のよう。
https://linaria.dev/
https://github.com/callstack/linaria/issues/735

7. Tailwind CSS

Tailwind v2.0と完全互換なWindi Cssがあります。
そちらの方がビルド時間が速いので、導入するならWindi CSSがよいのではと思います。
https://tailwindcss.com/

8. Windi CSS

Viteに対応しています。
Bootstrapみたいな書き方をします。

サンプル
<p className="text-gray-500 font-medium">Product Engineer</p>

https://marketplace.visualstudio.com/items?itemName=voorjaar.windicss-intellisense
https://qiita.com/Takazudo/items/78ee15564bfefdea844c
https://qiita.com/70ki8suda/items/b95aeb4d4d3cab57a8fe

選択肢を絞るまでの経緯

1. Inline Style

開発用にちょこっと使用するものなので選択肢から外します。

2. Css Modules

Vite標準なので、導入コストがないのは有難いです。
試してみたのですが、やはりファイルが分かれることがネックです。
コンポーネントを分けようと思うときに躊躇してしまいます。
今回は選択肢から外しました。

3. Styled JSX

Viteで使用するのにコンパイルエラーや実行時の警告を解消する調査が手間なので、選択肢から外します。

4. Styled Components

試してみたのですが、やはり可読性が悪いと感じました。
スタイルを付けたコンポーネントは、ネーミングを工夫して「Styled●●●●●Div」とか「Styled●●●●●P」とかしてみたのですが、HTMLの構造がパッとみて掴みづらかったです。
今回は選択肢から外しました。

5. Emotion

最終的に選択肢に残りました。
Emotion で Styled JSX のような書き方を使用したいと思います。

6. Linaria

Viteに導入するのは時期尚早のようなので、選択肢から外します。

7. Tailwind CSS

導入するならWindi Cssなので選択肢から外します。

8. Windi CSS

個人的な好みの問題で、選択肢から外します。
HTMLはできる限りスッキリさせときたい派でCSSは分離させたいです。
あとは CSS と WindiCSSのクラス との変換が面倒です。

Emotionを導入する

Emotionは Inline Styles、Styled JSX、Styled Componentsと同様の書き方ができます。
今回は Styled JSX のような書き方で Object Style を使用したいと思います。

インストール

@emotion/react をインストールします。
(@emotion/babel-plugin は必要ありません)
※ styled component のような書き方をする場合は「@emotion/styled」のインストールが必要です。

npm install @emotion/react

設定

各tsxファイルにプラグマ [import jsx from '@emotion/react'] の記述がないと、コンパイルエラーになるため、tsconfig.jsonに記述します。

tsconfig.json(抜粋)
"compilerOptions": {
    ・・・中略・・・
    "jsxImportSource": "@emotion/react",

vite.config.tsは、tsconfig.json の jsxImportSource を参照しないので、こちらにも追記します。

vite.config.ts(抜粋)
  plugins: [react({
    jsxImportSource: '@emotion/react',
  })]

サンプル

Inline Style の書き方

Emotion の Inline Styleは、Css in Js の書き方で記述します。

<div css={{ color: 'red' }}>Inline Style</div>
Styled JSX のような書き方 (String Style)

Emotion の String Styleは、 従来の css の書き方で記述します。

import { css } from '@emotion/react'

const styles = {
  divstyle: css`
    width: 100%;
    padding: 20px;
    background-color: #CE6270;    
  `,
  textstyle: css`
    color: #FBBDAE;
    text-align: center;
  `
}
  
export function EmotionStringStyle() {
  return (
      <div css={styles.divstyle}>
        <p css={styles.textstyle}>Emotion String Style</p>
      </div>
  )
}

String Styleを使用する際は、VsCode 拡張機能 vscode-styled-components
を使用すると、インテリセンスとシンタックスハイライトが効くようになります。
https://marketplace.visualstudio.com/items?itemName=styled-components.vscode-styled-components

Styled JSX のような書き方 (Object Style)

Emotion の Object Styleは、 Css in Js の書き方で記述します。

import { css } from '@emotion/react'

const styles = {
  divstyle: css({
    width: '100%',
    padding: '20px',
    backgroundColor: '#234867'
  }),
  textstyle: css({
    color: '#30A6BC',
    textAlign: 'center'
  })
}

export function EmotionObjectStyle() {
  return (
    <div css={styles.divstyle}>
      <p css={styles.textstyle}>Emotion Objectg Style</p>
    </div>
  )
}



以上
React(Vite + TypeScript)のCSSスタイルについて調べて、Emotionに流れ着いた経緯と、Emotionの導入方法についてでした。




技術選定の際に参考にしたサイト

https://techlife.cookpad.com/entry/2021/03/15/090000

https://zenn.dev/uhyo/articles/next-gen-css-in-js

https://qiita.com/Takepepe/items/41e3e7a2f612d7eb094a

https://blog.ojisan.io/s-c-refactor/

https://blog.cybozu.io/entry/2020/06/25/105457

https://note.com/tabelog_frontend/n/n2541778b81e3

https://kenzoblog.vercel.app/posts/css-manage

https://ramble.impl.co.jp/1414/#toc2

Discussion