※ あくまで自称です。笑
※ 今後もどんどん拡張していく予定です。
※ emotion/styled に関しては割愛する予定です。
Emotionとは?
フレームワークにとらわれず使うことができるCSS in JSのフレームワーク。
(styled-components
と比較されがちだが、emotionの方が後発であるためstyled-components
ができることは基本できます。)
初期設定
利用したいEmotionのパッケージをインストールする
Emotion関連のパッケージ
-
@emotion/css
- フレームワークにとらわれず、Emotionを使用するためのパッケージ。
-
@emotion/react
- React用のEmotionパッケージ。
-
@emotion/styled
-
styled-component っぽい記法で書くことができるEmotionパッケージ。(筆者は
styled-component
から乗り換える人用のパッケージだと思っています)
-
styled-component っぽい記法で書くことができるEmotionパッケージ。(筆者は
- @emotion/core
-
@emotion/core
はEmotion 11で@emotion/react
に改名したため、忘れ去ってください。 - 参考:https://emotion.sh/docs/emotion-11#package-renaming
-
-
@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
基本文法
基本的には2種類の書き方がある。
(厳密には3種類?@emotion/styled
をインストールすればstyled-components
の書き方もできます!!)
-
オブジェクトスタイル
- 厳密な型定義がされるため予測変換しやすい
- CSSプロパティがキャメルケースになる
-
ストリングスタイル
- そのままのcssを文字列に展開するだけ
-
型定義がないため、デフォだと予測変換がないしエラー検知しづらい
- vscodeであれば、vscode-styled-componentsを入れると予測変換が使える
// オブジェクトスタイル
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>
</>
);
設計
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,
},
});