こちらはStyled-componentsの使い方、ユースケースを集めた端的なページです。
なにかの問題解決、参考になりましたらスターを押してくださいませ。励みになります。
随時更新中
更新情報
- 2020/1/4
- 絵を更新
- 2020/1/3
- backgroundでsvgを読み込む
- .activeをクラスに追加した際のスタイル
- attrsのpropsの渡し方を
4.1.1
で修正された内容に変更
- styled-componentsを使う為の前提
- styled-componentsの最小の指定
- ``は何??
- defaultPropsとして指定する
- 呼び出し時指定する
- styled-componentsの拡張の仕方
- styleは一緒でタグだけ変えたい場合
- styleは一緒でタグだけ変えた後拡張したい
- componentからのpropsをstyledへのpropsに渡せる。連結させる。
- styled-componentsとTypeScript
- レイアウトの組み方の一例(how to layout with styled-components)
- styled-componentsにおける擬似要素の指定方法
- mixinやattrsなどaタグのhref設定
- background指定する
- isOpen(boolean)の時だけスタイルを追加する(.active)
- styled-ComponentされたComponentをデバッグ時にDisplayNameとして表示させる設定
- iconをstyled-components化する(background-image: url())
- mediaQuery対応
- お役立ちライブラリ
//importする
import styled from 'styled-components'
const Button = styled.button`
color: red;
`
//render
<Button>ボタン</Button>
styled-componentで使われているTaggedTemplateLiterals
styled.button``
とstyled.button()
は同じ
違いは引数を渡すと値になるかだけ
const logArgs = (...args) => console.log(...args)
これはただの引数を渡したら渡された引数を出力する関数だ
単純に
logArgs('a', 'b');
//-> a b
じゃあtagged template literalで呼んでみよう
logArgs``
//-> [""]
続きWIP
const Button = styled.button`
color: red;
backgroun: ${(theme) => thme.main}
`
Button.defaultProps = {
theme: {
main: "#0088ee"
}
}
const Button = styled.button`
color: ${({theme}) => theme.main};
border: 2px solid ${({theme})=> theme.main};
`
//render
<Button theme={{main: red}}></Button>
const Button = styled.button`
color: red;
`
const ButtonExtend = Button.extend`
border-color: green
`
const Button = styled.button`
color: red;
`
const StyledLink = Button.withComponent('a')
//render
<Button>ボタン</Button>
<StyledLink>リンク</StyledLink>
const Button = styled.button`
color: red;
`
const StyledLink = Button.withComponent('a')
const StyledLinkEx = StyledLink.extend`
color: red
`
- 呼び出し時に渡したpropsを元に動的に変更する
- staticなprops記述もできる
const Button = styled.button.attrs(props => ({
type:'password',//staticなprops
margin: props.size || '1em',//sizeとして受け取りmappingしている
padding:props.size || '1em'//sizeとして受け取りmappingしている
//共通部分はこの下に書く
}))`
font-size: 1em;
border-radius: 3px;
margin: ${props => props.margin};//上で定義したmarginを受け取る
padding: ${props => props.padding};//上で定義したpaddingを受け取る
`
//render
<Button>ボタン</Button>
<Button size="2em">ボタン</Button>
//最終的にViewされるHTML
<button type="password" margin="1em" padding="1em" class="sc-htpNat fTzOaU">ボタン</button>
<button type="password" margin="2em" padding="2em" class="sc-htpNat fTzOaU">ボタン</button>
template literal内でのprops値によってstyleを変える際に出るcompileエラーを避ける
styled-components/styled-components#630 (comment)
Paddingというコンポーネントは全てのコンポーネントのpaddingに責務を持つ →Styleに依存しないミニマムなコンポーネントができる
例えば
export const Padding = styled.div`
padding-top: ${(props) => props.top}px;
padding-right: ${(props) => props.right}px;
padding-bottom: ${(props) => props.bottom}px;
padding-left: ${(props) => props.left}px;
`
Padding.defaultProps = {
top: 0,
right: 0,
bottom: 0,
left: 0
}
をutlisとして作り、
呼び出し側では
<Padding top={30} right={20} bottom={20} left={20}>
<Some />
</Padding>
<Padding top={10} right={10}>
<Some />
</Padding>
リアルに使っているユーティリティstyledコンポーネント
export const Padding = styled.div`
padding-top: ${(props) => console.log("padding", props) || props.top}px;
padding-right: ${(props) => props.right}px;
padding-bottom: ${(props) => props.bottom}px;
padding-left: ${(props) => props.left}px;
`
Padding.defaultProps = {
top: 0,
right: 0,
bottom: 0,
left: 0
}
export const Margin = styled.div`
margin-top: ${(props) => props.top};
margin-right: ${(props) => props.right};
margin-bottom: ${(props) => props.bottom};
margin-left: ${(props) => props.left};
`
Margin.defaultProps = {
top: "0px",
right: "0px",
bottom: "0px",
left: "0px"
}
export const Text = styled.span`
display: ${props => props.disp};
text-align: ${props => props.ta};
font-size: ${props => props.fs};
color: ${props => props.color};
font-weight: ${props => props.fw};
line-height: ${props => props.lh};
`
Text.defaultProps = {
"display": "inline",
"text-align": "left",
"font-size": "12px",
"color": "#4B5467",
"font-weight": "normal",
"line-height": "1px"
}
export const Border = styled.div`
border-top: ${(props) => props.top} solid ${(props) => props.color};
border-right: ${(props) => props.right} solid ${(props) => props.color};
border-bottom: ${(props) => props.bottom} solid ${(props) => props.color};
border-left: ${(props) => props.left} solid ${(props) => props.color};
`
Border.defaultProps = {
top: "0px",
right: "0px",
bottom: "0px",
left: "0px",
color: "#c9d2db"
}
export const Strong = styled.span`
font-size: ${props => props.fs};
color: ${props => props.color};
font-weight: 600;
`
Strong.defaultProps = {
"font-size": "14px",
"font-color": "#262626"
}
こうすることでSomeはpaddingに依存しない原子なComponentとしてどこにでも置ける
import styled from 'styled-components';
export const Paaan = styled.div`
text-align: center;
&::before,
&::after {
position: absolute;
top: 0;
some...
}
&::before {
transform: skewX(25deg);
left: 0;
}
&::after {
transform: skewX(-25deg);
right: 0;
}
`
import styled, {css} from 'styled-components'
//ボタンの種類(border-colorと背景色)を定義
const colors = {
secondary: {borderColor: '#8db909', bg: '#6c8d0a'}
}
//共通で使うプロパティ-値をmixinとして定義
const ButtonStyle = css`
display: inline-block;
width: 100%;
padding: 0;
`
export const ButtonLink = styled.a.attrs({
href: props => props.href//aタグなのでhrefをそのまま設定,
target: props => (props.target === '_new' ? props.target : '_self')
})`
${ButtonStyle}//共通で使うプロパティをmixinを呼んでいる
background-color: ${(props) => colors[props.type]["borderColor"]};//ここで種類によって分けている
color: #fff;
border-color: ${(props) => colors[props.type]["bg"]};
`
///use
<ButtonLink
type="secondary"
href={`https://some.jp`}
target={'_new'}
>
ボタン
</ButtonLink>
import profile from 'assets/img/profile.svg'
.
.
.
const ProfileButton = styled.button`
width: 100%;
padding: 14px 0;
color: #9b9b9b;
&:before{
content: url(${profile}); // here
margin-right: 9px
}
`
or
<Content img={ImagePath} />
.
.
.
const Content = styled.div`
background-image: url(${props => props.img});
`;
<ProfileButton isOpen={props.isOpen} onClick={props.handleClickProfile}>
.
.
.
const ProfileButton = styled.button`
width: 100%;
padding: 14px 0;
color: #9b9b9b;
&:before{
content: url(${profile});
margin-right: 9px
}
${({ isOpen }) => isOpen && `
border-bottom: solid 2px #de552b;
font-weight: bold;
color: #000;
background: #fff9ee;
`}
`
or
<Tab
onClick={props.handleClickMatch(detail.matchDate)}
className={detail.matchDate === props.matchTabId ? 'active' : ''}
>
.
.
.
const Tab = styled.div`
color: #9b9b9b;
width: 100%;
padding: 15px 0;
&.active {
border-bottom: solid 2px #de552b;
color: #000000;
}
`
下記該当箇所をbabel設定に多くはpackage.jsonやbabel設定ファイル
"babel": {
"presets": [
"react-app"
],
///////////ここ//////////////
"plugins": [
["babel-plugin-styled-components", {
"displayName": true
}]
]
///////////ここまで//////////////
},
backgroundImageはfile自体をimportして設定する
//utils/styledComponent.js
import male from '../../assets/icon/male.png';//importする
import female from '../../assets/icon/female.png';//importする
.
.
.
export const IconEmployee = styled.span`
width: 68px;
height: 68px;
border-radius: 100px;
flex: 0 0 68px;
background-color: #fff;
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
background-image: url(${({isMale}) => isMale ? male : female});
`
//someComponent.js
<IconEmployee isMail={gender === 1} />
// style-utils.jsというutilsを作る
import { css } from 'styled-components';
export const media = {
handheld: (...args) => css`
@media (min-width: 1279px) {//ここにデバイス幅を指定
${css(...args)};
}
`,
handheld320: (...args) => css`
@media (max-width: 374px) {//375px未満
${css(...args)};
}
`
};
///////////////////
////読み込み側では
import styled from 'styled-components';
import { media } from '../Utils/style-utils';
export const Paaan = styled.div`
text-align: center;
${media.handheld` //ここで使う
width: 270px;
`}
font-weight: 700;
position: relative;
margin: 0 auto;
.
.
.
some