1. シンプルな例
<Title>hello</Title>
-
title
を当てるとタイトルのスタイルになる - タイトルの色はテーマとして変更可能
SCSS
.title {
font-size: 36px;
color: $title-color;
}
CSS-in-JS
import styled from 'styled-components';
const Title = styled.h1`
font-size: 36px;
color: ${props => props.theme.titleColor};
`;
まだ辛くない
2. オプション的に見た目を変えたいとき(バリアント)
(
<Button variant="primary" />
<Button variant="secondary" />
)
-
primary
かsecondary
を指定すると、色が変わる -
primary
とsecondary
の色はテーマとして変更可能 -
font-size: 12px
は共通のスタイル
SCSS
.button {
font-size: 12px;
.primary {
color: $primary-fg-color;
background-color: $primary-bg-color;
}
.secondary {
color: $secondary-fg-color;
background-color: $secondary-bg-color;
}
}
CSS-in-JS (Template literal)
import styled from 'styled-components';
const Button = styled.button`
font-size: 12px;
${
(props) => props.variant === 'primary'
? css`
color: ${props.theme.primaryFgColor};
background-color: ${props.theme.primaryBgColor};
`
: css`
color: ${props.theme.secondaryFgColor};
background-color: ${props.theme.secondaryBgColor}
`;
}
`;
- 一気に複雑さが増す。
- テンプレートリテラルの中でテンプレートリテラルを使っていて気持ち悪い
-
css
の中か外かで、関数で変数を選択するかそのまま使うか違っていて頭を使う - そもそも
theme
に関してはネストした時点で2通りの書き方が存在してしまう。
CSS-in-JS (Object)
import styled from 'styled-components';
const Button = styled.button(
{
fontSize: '12px',
},
props => ({
return props.variant === 'primary'
? {
color: props.theme.primaryFgColor,
backgroundColor: props.theme.primaryBgColor
}
: {
color: props.theme.secondaryFgColor,
backgroundColor: props.theme.secondaryBgColor
};
),
);
- 上と比べるとテンプレートリテラルが無い分読みやすい
- stylelintが動かなくなる
CSS-in-JS (styled-system)
import styled from 'styled-components';
import { variant } from 'styled-system';
const Button = styled.button(
{
fontSize: '12px',
},
variant({
prop: 'variant',
variants: {
primary: {
color: 'colors.primaryFg',
backgroundColor: 'color.primaryBg',
},
secondary: {
color: 'colors.secondaryFg',
backgroundColor: 'colors.secondaryBg',
},
},
}),
);
-
variant === 'primary'
みたいなボイラープレートがなくなってだいぶ読みやすい -
styled.something()
の引数はprop → CSS
にもできるから、型は付けられる。 - stylelintが動かない
CSS-in-JS (xstyled)
import styled from 'styled-components';
import { varinat, css } from '@xstyled/system';
const Button = styled.button`
font-size: '12px',
${variant({
default: 'primary',
variants: {
primary: css`
color: primaryFg,
backgroundColor: primaryBg,
`,
secondary: css`
color: secondaryFg,
backgroundColor: secondaryBg,
`,
},
})},
);
- styled-systemのバリアントとだいたい同じ
- デフォルト値が付けられる
- css関数が使えるのでかろうじてstylelintが動く
3. 子要素をオーバーライドしたいとき
<Article>
<Button />
</Article>
-
.button
と.article
がある -
.article > .button
は、フォントサイズが2px分大きくなる
SCSS
.button {
font-size: 12px;
}
.article {
.button {
font-size: 14px;
}
}
CSS-in-JS
import styled from 'styled-components';
const Button = styled.button`
font-size: 12px;
`;
const Article = styled.article`
${Button} {
font-size: 12px;
}
`;
- Emotionはbabel pluginが必要になる
CSS-in-JS (Buttonが少しでもロジックを持っている場合)
import styled from 'styled-components';
const Wrapper = styled.button`
font-size: 12px;
`;
const Button = ({ children, ...rest }) => {
const submit = useSubmit();
return (
<Wrapper {...rest} onClick={submit}>
{children}
</Wrapper>
);
}
const Article = styled.article`
${Wrapper} {
font-size: 12px;
}
`;
- Component selectorが使えるのはstyled component限定なので、コンポーネントがstyledか否かを把握しないといけない。
- SFCの外から拡張したいときに、Wrapperの存在が漏れてしまうので、カプセル化できていない