121
63

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 1 year has passed since last update.

ちーずのフロントエンド道場Advent Calendar 2021

Day 24

(自称) 日本一わかりやすいemotionのドキュメント

Last updated at Posted at 2021-12-24

※ あくまで自称です。笑
※ 今後もどんどん拡張していく予定です。
※ emotion/styled に関しては割愛する予定です。

:question: Emotionとは?

フレームワークにとらわれず使うことができるCSS in JSのフレームワーク。
(styled-componentsと比較されがちだが、emotionの方が後発であるためstyled-componentsができることは基本できます。)

:gear: 初期設定

利用したいEmotionのパッケージをインストールする

Emotion関連のパッケージ

  • @emotion/css
    • フレームワークにとらわれず、Emotionを使用するためのパッケージ。
  • @emotion/react
    • React用のEmotionパッケージ。
  • @emotion/styled
    • styled-component っぽい記法で書くことができるEmotionパッケージ。(筆者はstyled-componentから乗り換える人用のパッケージだと思っています)
  • @emotion/core
  • @emotion/babel-preset-css-prop
    • css propsを使用する場合、本来はすべてのファイルに/** @jsx jsx */を書く必要がある。
    • このJSX Pragmaの問題を解決するためのプラグインが@emotion/babel-preset-css-prop
  • @emotion/babel-plugin
    • Emotionのコンパイルを最適化するためのプラグイン。
    • version 8 以上は不要
  • @emotion/server
    • サーバー側レンダリングするAPI

:pencil2: 基本文法

基本的には2種類の書き方がある。
(厳密には3種類?@emotion/styledをインストールすればstyled-componentsの書き方もできます!!)

  • オブジェクトスタイル

    • :thumbsup_tone2: 厳密な型定義がされるため予測変換しやすい
    • :thumbsdown_tone2: CSSプロパティがキャメルケースになる
  • ストリングスタイル

    • :thumbsup_tone2: そのままのcssを文字列に展開するだけ
    • :thumbsdown_tone2: 型定義がないため、デフォだと予測変換がないしエラー検知しづらい
// オブジェクトスタイル
const objectStyle = css({
  maxWidth: '400px',
  margin: '0 auto',
  padding: '10px'
});

// ストリングスタイル
const stringStyle = css`
  max-width: 400px;
  margin: 0 auto;
  padding: 10px
`

// css propは css({}) もしくは css`` を代入するだけ
render(
  <div css={stringStyle}>
    {/* ... */}
  </div>
)

擬似要素やメディアクエリー

両方とも、scssの記述方法で入れ子にすればokそうです!!

ストリングスタイル

const styles = {
  main: css`
    padding: 12px;

    &:hover {
      opacity: 0.5;
    }
  `
}

オブジェクトスタイル

const styles = {
  main: css({
    padding: '12px'
    
    '&:hover': {
      opacity: 0.5,
    },
  })  
}

Propsで渡す

css propに記載されたスタイルが評価され、計算されたクラス名がclassNameに渡されます。
そのため、cssを親から受け取りたいComponentはpropsにcss(SerializedStyles型)ではなくclassName(string型)を受け取れるようにすればよいです。(もちろんcssとして受け取ることもできます。)

とても賢いが正直わかりづらい。

const Button = ({className, children}) => (
  <button className={className}>{children}</button>
)

const buttonWrapperStyle = css`
  background-color: #ddd;
`

// cssで渡しても、classNameに変換される
const ButtonWrapper =  () => (
  <Button css={buttonWrapperStyle}>ボタン</Button>
)

結合する

EmotionにおけるCSSの結合は、Specificityも解決します。

基本、配列で渡せば結合されます。

const marginBottom = css`
  margin-bottom: 16px
`

const style = css`
  padding: 16px;
`

render (
  <div css={[marginBottom, style]}>{/* */}</div> 
)

ストリングスタイル

そのまま変数代入展開することができる。

const marginBottom = css`
  margin-bottom: 16px
`

const style = css`
  ${marginBottom}
  padding: 16px;
`

オブジェクトスタイル

スプレッド演算子で展開することができる。

const marginBottom = css({
  marginBottom: '16px'
})

const style = css({
  ...marginBottom,
  padding: '16px'
})

入れ子

ストリングスタイル

子要素に対してスタイルを当てる
const listStyle = css`
  li {
    //...
  }
`

return (
  <ul css={listStyle}>
    <li css={item}>{/* */}</li>
  </ul>
);
親のタグを指定する

親のタグに囲まれているときのみスタイルを当てることもできる

const item = css`
  ul & {
    //...
  }
`

return (
  <>
    <ul>
      <li css={item}>{/* あたる */}</li>
    </ul>
    <div>
      <span css={item}>{/* あたらない */}</span>
    </div>
  </>
);

:computer: 設計

Media Query

※ マサカリ大歓迎です

type breakpointsType = {
  id: 'tablet' | 'pc';
  breakpoint: number;
}[];

const breakpoints: breakpointsType = [
  {
    id: 'tablet',
    breakpoint: 960,
  },
  {
    id: 'pc',
    breakpoint: 560,
  },
];

// min-widthのみしか設定できてないからもう少し工夫は必要かも?
export const MediaQuery = breakpoints.reduce((acc, { id, breakpoint }) => {
  return {
    ...acc,
    [id]: `@media (min-width: ${breakpoint}px)`,
  };
}, {});
// inline style
const style = css`
  background-color: '#fff';
  ${MediaQuery['pc']} {
    color: gray;
  }
`

// object style
const style = css({
  backgroundColor: '#fff',
  [MediaQuery['pc']]: {
    padding: 20,
  },
});
121
63
1

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
121
63

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?