Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
styled-componentsの使い方(パッとわかりやすく、色々なパターンを説明することを目指しています)

styled-componentsの使い方(パッとわかりやすく、色々なパターンを説明することを目指す記事)

styled-compoents

本家ドキュメント

こちらはStyled-componentsの使い方、ユースケースを集めた端的なページです。
なにかの問題解決、参考になりましたらスターを押してくださいませ。励みになります。
随時更新中

更新情報

  • 2020/1/4
    • 絵を更新
  • 2020/1/3
    • backgroundでsvgを読み込む
    • .activeをクラスに追加した際のスタイル
    • attrsのpropsの渡し方を4.1.1で修正された内容に変更

index

  • 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対応
  • お役立ちライブラリ

styled-componentsを使う為の前提

//importする
import styled from 'styled-components'

styled-componentsの最小の指定

styled

cosnt 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

defaultPropsとして指定する

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

styled-componentsの拡張の仕方

cosnt Button = styled.button`
  color: red;
`
const ButtonExtend = Button.extend`
  border-color: green
`

styleは一緒でタグだけ変えたい

cosnt Button = styled.button`
  color: red;
`
const StyledLink = Button.withComponent('a')

//render
<Button>ボタン</Button>
<StyledLink>リンク</StyledLink>

styleは一緒でタグだけ変えた後拡張したい

withComponent

cosnt Button = styled.button`
  color: red;
`
const StyledLink = Button.withComponent('a')
const StyledLinkEx = StyledLink.extend`
  color: red
`

componentからのpropsをstyledへのpropsに渡せる。連結させる。

attrs

  • 呼び出し時に渡した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>

styled-componentsとTypeScript

template literal内でのprops値によってstyleを変える際に出るcompileエラーを避ける

https://github.com/styled-components/styled-components/issues/630#issuecomment-315475109

レイアウトの組み方の一例(how to layout with styled-components)

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としてどこにでも置ける

styled-componentsにおける擬似要素の指定方法

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;
  }
`

mixinやattrsなどaタグのhref設定

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>

background指定する

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});
`;

isOpen(boolean)の時だけスタイルを追加する(.active)

<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;
  }
`

Styled-ComponentされたComponentをデバッグ時にDisplayNameとして表示させる設定

下記該当箇所をbabel設定に多くはpackage.jsonやbabel設定ファイル

  "babel": {
    "presets": [
      "react-app"
    ],
    ///////////ここ//////////////
   "plugins": [
      ["babel-plugin-styled-components", {
        "displayName": true
      }]
    ]
    ///////////ここまで//////////////
  },

iconをstyled-components化する(background-image: url())

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} />

mediaQuery

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

お役立ちライブラリ

mixinを呼び出してくれるpolishedのドキュメント

@setogawamasao

This comment has been minimized.

Copy link

@setogawamasao setogawamasao commented May 21, 2020

cosnt はわざとでしょうか

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.