🌟

ReactにおけるCSSの書き方いろいろ

2023/02/04に公開

Reactを学んでいる中で、CSSの書き方ありすぎじゃね?ってなったので、忘れる前にφ(..)メモメモ
これ以外にもまだあるみたい(´・ω・`)
奥が深い。。。

inline-style

変数を作成し、その中にCSSを書いていく手法。
レンダリングのたびに計算されてパフォーマンスも低下するため、あまり使わないらしい。(デスヨネー)
後述の注意点も相まって使いにくそうな印象。
逆に言うと、頻繁に計算が必要なスタイルとかでは有効?
あとテスト的にCSS当てたいときとかはとりあえずコレでいいかも。

注意点は
・プロパティはキャメルケースにする。(border-radius → borderRadius)
・値は文字列or数値にする。(color: “blue”, margin:0、など)

jsx
export const InlineStyle = () => {
  const containerStyle = {
    border: "solid 2px #392eff",
    borderRadius: "20px",
    padding: "8px",
    margin: "8px",
    display: "flex",
    justifyContent: "space-around",
    alignItems: "center"
  };
  const titileStyle = {
    margin: "0px",
    color: "#3d84a8"
  };
  const buttonStyle = {
    backgroundColor: "#abedd8",
    border: "none",
    padding: "8px",
    borderRadius: "8px"
  };

  return (
    <div style={containerStyle}>
      <p style={titileStyle}>- Inline Style -</p>
      <button style={buttonStyle}>Click Me!"</button>
    </div>
  );
};

CSS Modules

CSSとかSCSSとかを別ファイルで作って、importして使う方法。
CSSの適用範囲をコンポーネント単位で閉じようという考えで作られたもの。
デザイナーと一緒に進めていくときなんかは、このほうがお互い仕事やりやすそうですよね。
Next.jsに標準で組み込まれているライブラリ。
僕はこれが一番馴染み深いからか、非常に読みやすくわかりやすい。
ちなみに

「非推奨にする予定」という方針が示されてから2年半が経過したが、今のところ非推奨にはなっていない

らしい。
詳細は以下。
https://developer.hatenastaff.com/entry/2022/09/01/093000
sass使うなら「node-sass」のインストールが必要。

jsx
import classes from "./CssModules.module.scss";

export const CssModules = () => {
  return (
    <div className={classes.container}>
      <p className={classes.title}>- CSS Modulus -</p>
      <button className={classes.button}>Click Me!</button>
    </div>
  );
};
scss
.container {
  border: solid 2px #392eff;
  border-radius: 20px;
  padding: 8px;
  margin: 8px;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.title{
  margin: 0px;
  color: #3d84a8;
}

.button {
  background-color: #abedd8;
  border: none;
  padding: 8px;
  border-radius: 8px;
  &:hover {
    background-color: #46cdcf;
    color: #fff;
    cursor: pointer;
  }
};

Styled Jsx

<style jsx="true"></style>の内に書いていく手法。
もちろん``内に書かなくても外だしも可。
Next.jsに標準で組み込まれているライブラリ。
「style-jsx」のインストールが必要。

jsx(内側パターン)
export const StyledJsx = () => {
  return (
    <>
      <div className="container">
        <p className="title">- Styled Jsx -</p>
        <button className="button">Click Me!</button>
      </div>
      <style jsx="true">{`
        .container {
          border: solid 2px #392eff;
          border-radius: 20px;
          padding: 8px;
          margin: 8px;
          display: flex;
          justify-content: space-around;
          align-items: center;
        }

        .title {
          margin: 0px;
          color: #3d84a8;
        }

        .button {
          background-color: #abedd8;
          border: none;
          padding: 8px;
          border-radius: 8px;
        }

        .button:hover {
          background-color: #46cdcf;
          color: #fff;
          cursor: pointer;
        }
      `}</style>
    </>
  );
};
jsx(外出しパターン)
import css from 'styled-jsx/css'

export const StyledJsx = () => {
  return (
    <>
      <div className="container">
        <p className="title">- Styled Jsx -</p>
        <button className="button">Click Me!</button>
      </div>
      <style jsx="true">{style}</style>
    </>
  );
};

const style = css`
{/* 省略 */}
`

Styled Components

タグとCSSを紐付けてComponet化し、そのタグをHTML内に書いていく手法。
人気が高いらしい?
個人的にもCSS-in-JSの中では好きな記法。
ただ、きちんと自作タグなのか、HTMLタグなのかを分類できるようにしておかないと混乱しそう。
(以下の例ではタグ名の頭に”S”をつけている。)
「styled-components」のインストールが必要。

jsx
import styled from "styled-components";

export const StyledComponents = () => {
  return (
    <SContainer>
      <STitle>- Styled Components -</STitle>
      <SButton>!!</SButton>Click ME!</SContainer>
  );
};

const SContainer = styled.div`
  border: solid 2px #392eff;
  border-radius: 20px;
  padding: 8px;
  margin: 8px;
  display: flex;
  justify-content: space-around;
  align-items: center;
`;

const STitle = styled.p`
  margin: 0px;
  color: #3d84a8;
`;
const SButton = styled.button`
  background-color: #abedd8;
  border: none;
  padding: 8px;
  border-radius: 8px;
  &:hover {
    background-color: #46cdcf;
    color: #fff;
    cursor: pointer;
  }
`;

Emotion

もはやよくわからん。これを使う必要性がわからないw
ロマサガ2における七英雄みたいな、合体してこれまでの記法がどれでも使えるみたいなやつ。
(微妙に書き方は異なるが。)
下の例では「@emotion/styled」と「@emotion/react」のインストールが必要。

/** @jsxRuntime classic */
/** @jsx jsx */
import { jsx, css } from "@emotion/react";
import styled from "@emotion/styled";

export const Emotion = () => {
  const containerStyle = css`
    border: solid 2px #392eff;
    border-radius: 20px;
    padding: 8px;
    margin: 8px;
    display: flex;
    justify-content: space-around;
    align-items: center;
  `;

  const titleStyle = css({
    margin: 0,
    color: "#3d84a8"
  });

  return (
    <div css={containerStyle}>
      <p css={titleStyle}>- Emotion -</p>
      <SButton>FIGHT!!</SButton>
    </div>
  );
};

const SButton = styled.button`
  background-color: #abedd8;
  border: none;
  padding: 8px;
  border-radius: 8px;
  &:hover {
    background-color: #46cdcf;
    color: #fff;
    cursor: pointer;
  }
`;

で、結局どれがいいの?

調べてみたらある記事を見つけた。
https://gigazine.net/news/20210625-css-in-js-performance/

プストニクさんは、今回の結果を見たうえで、ページの表示時に実行するJavaScriptの量を増やしてしまう「CSS in JS」は、特にインターネット接続が遅かったり通信料が高額だったりするローエンドのデバイスや地域において、ウェブサイトの表示に大きな影響を与えると結論付けています。プストニクさんが次にライブラリの選定を行う際には、純粋なCSSを利用するか、今回の計測で用いたLinariaのようなビルド時にCSS in JSのコードからCSSを抽出してくれるツールを利用したいとのことです。

確かにレンダリングされたら全部処理走るもんね。。。
ただ1年半以上前の記事だから状況は変わっているかも?

Linariaを学習したらまた追記しようと思う。

Discussion