1
1

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.

Emotionのコーディングルール考えてみた

Last updated at Posted at 2021-09-20

はじめに

社内のプロジェクトでCSSinJSライブラ入りとしてemotionを導入したのでコーディングルールを考えてみました。

プロジェクトで使用する技術

package version
next v11.1.2
typescript v4.4.3
@emotion/react v11.4.1

css関数を使ってスタイルを定義する

emotionではstyle-componentと同様にスタイルを含むコンポーネントを作成するstyled関数と、コンポーネントと独立してスタイルを定義できるcss関数が用意されています。

css関数を使うことで従来のマークアップのようにHTMLとCSSを分別することができるので、css関数を使うことにします。
emotionを導入した理由もcss関数が使えることが大きいです。

import { css, styled } from '@emtion/react';

// styledを使った書き方
const StyleButton = styled.button`
  width: 100px;
`;
const Button = ({ children }) => {
  return <StyledButton>{ children }</styledButton>
}

// cssを使った書き方
const buttonStyle = css`
  width: 100px;
`;
const Button = ({ children }) => {
  return <button css={buttonCss}>{children}</button>
}

cssの記述はファイルの下段に定義する

一つのjsxファイルでコンポーネントのロジック、HTML、CSSを記述するので、それぞれの記述が混在すると可読性が落ちてしまいます。

VueのSFCの記述のように一番下にスタイルを記述することでどこに何が記載されているか予測しやくなります。

参考:レシピサービスのフロントエンドに CSS in JS を採用した話

css関数で作ったスタイルの変数名にプレフィックスとして「css」を付ける

変数のプレフィックスを統一することで、一目でスタイルを表す変数であると認識しやすくなります。
プレフィックスにはstylecssなどいくつか候補あると思いますが、文字数が短くcssプロパティともイメージづけしやすいcssをプレフィックスとしてつけると良いと考えます。
また、エディタの補完機能が働き、cssと入力した時点で作成したスタイルの一覧が入力候補として表示されるようになります。
image.png

実装例
const Button = ({children}) => {
  return <button css={cssButton}>{ children }</button>
}

const cssButton = css`
  background: #ddd;
  border-radius: 30px;
`;

Highlightの設定

その他にVSCodeの拡張機能「Highlight」を使って、cssから始まる文字の色を変更することで、変数がcss関数で作られたスタイルを意味するのかそれ以外なのか区別しやすくできます。

拡張機能をインストールして、VSCodeの設定ファイルに以下の設定を追加する。
colorは自由に変更してください。

settings.json
    "highlight.regexes": {
        "(css[a-zA-Z0-9_]+)": {
            "filterFileRegex": ".*(jsx|tsx)$",
            "decorations": [
                {
                    "color": "OldLace",
                }
            ]
        },
    }

image.png

親コンポーネントからcssを渡したいときは、子コンポーネント側はclassNameで受け取り、cssプロパティの後ろにclassNameを設定する

emotionを使用すると、cssプロパティで渡したスタイルは内部でclassNameというpropsに変換されて子コンポーネントに渡されます。(参考記事:Emotionを使いこなす
そのため、親から子へスタイルを渡した場合は、子コンポーネントはcssプロパティとclassNameプロパティの両方を扱う必要があります。

この二つを同時に指定した場合、classNameプロパティで渡したスタイルの優先度が高くなるのですが、どちらのプロパティを先に記述した方が可読性が高いか考えるときにcssプロパティ内でのマージ方法を参考にします。

cssプロパティ上でスタイルをマージする方法として、配列でcss={[style1, style2]}と記述する方法があります。
この場合、配列の後ろに格納したstyle2の優先順位が高くなります。

このルールに基づき、cssプロパティより優先度が高いclassNameプロパティを後ろに書くことで優先順位をイメージしやすくなります。

記述例
const Parent = () => {
  return <div>
    <Child css={cssParentToChild} />
  </div>
}

const Child: React.FC<{ className?: string}> = ({ className }) => {
  return <div css={[cssChild1, cssChild2]} className={className}>child</div>
}
const cssParentToChild = css`
  top: 3px;
`;
const cssChild1 = css`
  top: 1px;
`;
const cssChild2 = css`
  top: 2px;
`;

このように指定すると、以下のようにスタイルが定義されます。スクリーンショット 2021-09-20 16.56.12.png

おわり

今回のプロジェクトは走り出したばっかりなので今後ルールは増えてくると思いますが、最初に決めておくルールはこれぐらいかなと思います。
またルールが増えたり変更することがあれば都度、追記していきたいと思います。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?