Styled Components 정리!

Cullen·2022년 1월 20일
0

Styled Components

현대 웹 앱이 컴포넌트를 기반으로 성숙해가면서 CSS 스타일링 방법론 또한 컴포넌트를 기반으로 재구성되고 있습니다. 이러한 고민 속에서 등장한 패러다임이 CSS-in-JS이고, 다시 그 중 가장 인기 있는 라이브러리가 바로 Styled-Components입니다.

SASS만으로도 행복했는데... Why?

언제나 잊지 말아야 할 건 기술은 문제를 해결하기 위해 등장했다는 사실입니다.

단, 마주한 문제를 더욱 멋지게 풀어낼 수 있는 방법이 존재한다면 열린 마음으로 도입을 고려해봐야 합니다.

SASS는 기존 Pure CSS의 많은 부분을 개선했습니다. 그러나 여전히 해결되지 않는 고질적인 문제점 또한 존재합니다.

  • CSS 클래스 명에 대한 고민은 여전합니다.
    • ex. BEM (.block__element--modifier, button button--state-success)
  • 정해진 가이드가 없으면 구조가 복잡해집니다.
  • 방대한 스타일 정보로 인한 스크롤 지옥도 여전합니다.
  • 여전히 CSS 클래스로 조건부 스타일링을 하고 있습니다.
  • CSS 클래스로 조건부 스타일링을 하더라도 동적인 변화를 표현하기에 한계가 있습니다.
    • ex. 1초에 px 값을 1씩 증가 → Inline 스타일에 의존

그러면 인라인 스타일은 안될까요?

const textStyles = {
  color: white,
  backgroundColor: black
}

<p style={textStyles}>inline style!</p>

// 렌더 결과
<p style="color: white; backgrond-color: black;">inline style!</p>
  • CSS 명시도(우선 순위)의 문제가 있습니다.
  • 엄밀하게 CSS가 아닙니다. (ex. background-color, backgroundColor)
  • 문서의 구조를 명시하는 html 파일의 부피가 증가하고 CSS 파일과의 역할 분리가 모호해집니다. (CSS ⇒ 웹 문서의 스타일링 정보)
  • Pseudo selector를 사용할 수 없습니다. (ex. :hover, :after)
  • media query, key frame 또한 사용할 수 없습니다.

Styled-Components

HomeBrew를 이용해 아래 Styled-Components 설치하기

npm install --save styled-components

왜 Styled Components를 고려해야 할까?

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

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

import styled from 'styled-components'

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

// html 태그 이름 뒤 Tagged Templete 문법을 활용해 CSS 속성을 정의하고 있습니다
// 앞서 학습했던 Templete 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 (가장 기본적이고 많이 쓰이는 항목)

return (
  <div>
    <Button>Normal</Button>
    <Button 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;
`;

Nesting도 가능합니다!

return (
  <>
    <Thing>Hello world!</Thing>
    <Thing>How ya doing?</Thing>
    <Thing className="something">
			<span className="contents">The sun is shining...<span>
		</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;
  }
`

SCSS에서 사용하는 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);
`;
profile
#프론트엔드 개발자

0개의 댓글