TIL 60 | Styled Components

hyounglee·2020년 10월 2일
1

React

목록 보기
19/33
post-thumbnail

Styled-Components

Why Styled Components?

css-in-js는 2018년 이후 폭발적으로 성장하고 있다. 그 중 Styled-Components는 npm 다운로드 수 기준으로 현재 가장 인기있는 css-in-js 라이브러리이다.

설치

npm install --save styled-components

공식 문서
https://styled-components.com/

Getting Started

// styled-components 라이브러리에서 import 해온 styled라는 객체를 이용합니다
// 아래와 같이 h1 태그를 만들어 Title이라는 스타일드 컴포넌트를 만들 수 있습니다

import styled from 'styled-components'

render(
  <Wrapper>
    <Title>
      Hello World!
    </Title>
  </Wrapper>
);

// html 태그 이름 뒤 Tagged Templete 문법을 활용해 CSS 속성을 정의하고 있습니다
// 앞서 학습했던 Templete Literals 문법(``)의 확장이라고 생각해도 좋습니다 ([링크](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Template_literals))

const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

Adapting based on props

render(
  <div>
    <Button>Normal</Button>
    <Button primary width="100">Primary</Button>
  </div>
);

// 만약 Button 컴포넌트에 전달된 props(width)가 200 미만(조건)이면
// 삼항연산자 true : "palevioletred"
// 삼항연산자 false : "white"

const Button = styled.button`
  background: ${props => props.width < 200 ? "palevioletred" : "white"};
  color: ${props => props.primary ? "white" : "palevioletred"};
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

Extending Styles

render(
  <div>
    <Button>Normal Button</Button>
    <TomatoAnchorButton>Tomato Button</TomatoAnchorButton>
  </div>
);

// The Button from the last section without the interpolations
const Button = styled.button`
  color: palevioletred;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

// A new component based on Button, but with some override styles
// Button의 속성을 상속 받아 새로운 anchor 태그를 생성
const TomatoAnchorButton = styled(Button.withComponent("a"))`
  color: tomato;
  border-color: tomato;
`;

Nesting & Global Style

가장 크게 체감할 수 있는 Pure CSS와 SASS의 차이라면 nesting 기능 유무에 있다. Styled Components 역시 해당 기능을 제공한다. 적절히 사용한다면 모든 컴포넌트를 스타일드 컴포넌트화 시키지 않더라도 충분히 스타일링할 수 있다.

render(
  <>
    <Thing>Hello world!</Thing>
    <Thing>How ya doing?</Thing>
    <Thing className="something">The sun is shining...</Thing>
    <div>Pretty nice day today.</div>
    <Thing>Don't you think?</Thing>
    <div className="something-else">
      <Thing>Splendid.</Thing>
    </div>
  </>
)

const Thing = styled.div`
  color: blue;

  &:hover {
    color: red;
  }

  #id {
		div {
	    background: orange;
		}
  }

  .something-else & {
    border: 1px solid;
  }
`
render(
  <>
    <GlobalStyle />
    <Thing>
      I'm blue, da ba dee da ba daa
    </Thing>
  </>
)

const Thing = styled.div`
  && {
    color: blue;
  }
`

const GlobalStyle = createGlobalStyle`
  ${Thing} {
    color: red;
  }
`

Mixin

import { css } from "styled-components"

const Navigation = styled.nav`
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  ${Sticky}
`;

const Sticky = css`
  position: fixed !important;
  background-color: white;
  border-bottom: 1px solid rgba(0, 0, 0, 0.11);
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.11);
  transition: all 0.6s ease-in-out;
  color: black;
`;

//

const RingVariant = (radius, stroke = "10") => css`
  position: absolute;
  border-radius: 50%;
  height: ${radius * 2}px;
  width: ${radius * 2}px;
  border: ${stroke}px solid rgba(0, 0, 0, 0.5);
`;

Attaching addition props

render(
  <div>
    <Input placeholder="A small text input" />
    <br />
    <Input placeholder="A bigger text input" size="2em" />
  </div>
);

const Input = styled.input.attrs(props => ({
  // we can define static props
  type: "password",

  // or we can define dynamic ones
  size: props.size || "1em",
}))`
  color: palevioletred;
  font-size: 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;

  /* here we use the dynamically computed prop */
  margin: ${props => props.size};
  padding: ${props => props.size};
`;

Animations

// Create the keyframes
const rotate = keyframes`
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
`;

// Here we create a component that will rotate everything we pass in over two seconds
const Rotate = styled.div`
  display: inline-block;
  animation: ${rotate} 2s linear infinite;
  padding: 2rem 1rem;
  font-size: 1.2rem;
`;
render(
  <Rotate>&lt; 💅🏾 &gt;</Rotate>
);

Etc.

Styled-reset

npm install --save styled-components styled-reset
import * as React from 'react'
import { createGlobalStyle } from 'styled-components'
import reset from 'styled-reset'

const GlobalStyle = createGlobalStyle`
  ${reset}
  /* other styles */
`

const App = () => (
  <React.Fragment>
    <GlobalStyle />
    <div>Hi, I'm an app!</div>
  </React.Fragment>
}

export default App
profile
(~˘▾˘)~♫❝ 쉽게만 살아가면 재미없어 빙고 .ᐟ ❞•*¨*•.¸¸♪

0개의 댓글