[CSS in JS] styled関数で受け取るpropsを短く書く方法

4 min read

概要

CSS in JS で実装されているstyled関数では、テンプレートリテラルを使ってスタイルを定義できる。

const Button = styled.button`
  color: #bf4f74;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid #bf4f74;
  border-radius: 3px;
`;

このとき、コンテキストの情報を${(props) => props.theme.primaryColor}のように参照できる。

ただ、複雑になってくると記述が複雑になって可読性が下がる課題もある。

propsの参照

Styledコンポーネントでは、コンポーネントに渡されたpropsオブジェクトから必要な情報を取り出して、スタイリングに反映させることができる。

以下のコード例では、propsオブジェクトからisPrimaryの値を取り出し、動的にスタイルを定義している。

const Button = styled.button<{ isPrimary?: boolean }>`
  background: ${(props) => (props.isPrimary ? '#BF4F74' : 'white')};
  color: ${(props) => (props.isPrimary ? 'white' : '#BF4F74')};

  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid #bf4f74;
  border-radius: 3px;
`;
Note

${(props) => props.theme.primaryColor}のような部分をinterpolationsと呼ばれている。
https://styled-components.com/docs/advanced

書き方

基本的な書き方であれば下記のようになる。${(props) => props.xxx}のようにpropsを引数として受け取り参照する。

const Button = styled.button<{ isPrimary?: boolean }>`
  background: ${(props) => (props.isPrimary ? '#BF4F74' : 'white')};
  color: ${(props) => (props.isPrimary ? 'white' : '#BF4F74')};

  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid #bf4f74;
  border-radius: 3px;
`;

スプレッド構文でpropsを展開する

引数のpropsを展開しておくことで短めに書くことができる。

const Button = styled.button<{ isPrimary?: boolean }>`
  background: ${({ isPrimary }) => (isPrimary ? '#BF4F74' : 'white')};
  color: ${({ isPrimary }) => (isPrimary ? 'white' : '#BF4F74')};
  // ...
`;

ただ、この書き方はpropsの中身が増えると可読性が下がる。
例:${({ theme, isPrimary, isSecondary }) => ...}

styledのコールバックでpropsを受け取る

大元でpropsを受けることで各プロパティ毎の参照を減らすことができる。

const Button = styled.button<{ isPrimary?: boolean }>(
  (props) => `
    background: ${props.isPrimary ? '#BF4F74' : 'white'};
    color: ${props.isPrimary ? 'white' : '#BF4F74'};

    // ...
  `,
);
エディタによってはシンタックスハイライトが効かない

Emotionであればcss関数があり、それをハイライトの対象としているエディタ(プラグイン)もあるので、以下のようにcss関数に変更することでハイライトを有効にできるケースがある。

const Button = styled.button<{ isPrimary?: boolean }>(
  (props) => css`
    background: ${props.isPrimary ? '#BF4F74' : 'white'};
    color: ${props.isPrimary ? 'white' : '#BF4F74'};

    // ...
  `,
);

スプレッド構文の組み合わせでより短く書くこともできる。

const Button = styled.button<{ isPrimary?: boolean }>(
  ({ isPrimary }) => `
    background: ${isPrimary ? '#BF4F74' : 'white'};
    color: ${isPrimary ? 'white' : '#BF4F74'};

    // ...
  `,
);