Styled Components 공식문서 정리

박재영·2020년 10월 19일

— Basic —

Getting Started

styles 지정과 React component를 생성을 동시에 함

// Title component 생성 : 스타일이 적용된 <h1> 렌더링
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

// Wrapper component 생성 : 스타일이 적용된 <section> 렌더링
const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

// 다른 React component처럼 사용
render(
  <Wrapper>
    <Title>
      Hello World!
    </Title>
  </Wrapper>
);

render method 밖에서 styled component 정의 : 렌더링할 때마다 생성⇒캐싱X

const Wrapper = ({ message }) => {
  // 경고: 매우 매우 좋지 않고 느리다. 절대 이렇게 하지마라!!
  const StyledWrapper = styled.div`
    /* ... */
  `

  return <StyledWrapper>{message}</StyledWrapper>
}

Adapting based on props

props를 기반으로 styles를 지정할 수 있음

const Button = styled.button`
  /* Button에 넘겨준 props를 가지고 styled 적용 */
  background: ${props => props.primary ? "palevioletred" : "white"};
  color: ${props => props.primary ? "white" : "palevioletred"};

  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

render(
  <div>
    <Button>Normal</Button>
    <Button primary>Primary</Button>
  </div>
);

Extending Styles

styled( ) 생성자를 사용하여 다른 styled component의 styles를 상속, 확장

const Button = styled.button`
  color: palevioletred;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

// Button 컴포넌트의 모든 style 속성을 물려받음 
// 같은 속성이면 오버라이드
const TomatoButton = styled(Button)`
  color: tomato;
  border-color: tomato;
`;

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

as styles는 유지, 다른 HTML tag나 다른 custom component로 렌더링

const Button = styled.button`
  display: inline-block;
  color: palevioletred;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
  display: block;
`;

const ReversedButton = props => <Button {...props} children={props.children.split('').reverse()} />

render(
  <div>
    <Button>Normal Button</Button>
    <Button as={ReversedButton}>Custom Button with Normal Button styles</Button>
  </div>
);

Pseudoelements, pseudoselectors, and nesting

scss 와 같은 syntax 제공. & 는 styled 정의하고 있는 컴포넌트 가리킴

const Wrapper = styled.section`
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 4em;
  background: papayawhip;

  /* & 없으면 자식 컴포넌트 가리킴 */
  .owner {
    color: palevioletred;
  }
`;

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

const Button = styled.button`
  background: ${(props) => (props.primary ? "white" : "palevioletred")};
  color: ${(props) => (props.primary ? "palevioletred" : "white")};
  font-size: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
	
  /* & 는 Button을 가리킴 */
  &:hover {
    color: white;
    background: palevioletred;
  }

  &:hover + h1 {
    color: white;
  }
`;

export default function App() {
  return (
    <Wrapper>
      <Button primary>Primary</Button>
      <Title>This is Title</Title>
      <span className="owner">@dodose</span>
    </Wrapper>
  );
}

Animations

keyframes 헬퍼를 사용하여 고유한 인스턴스를 생성

// keyframes 생성하기
const rotate = keyframes`
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
`;

// keyframes 적용 
const Rotate = styled.div`
  display: inline-block;
  animation: ${rotate} 2s linear infinite;
  padding: 2rem 1rem;
  font-size: 1.2rem;
`;

render(
  <Rotate>&lt; 💅🏾 &gt;</Rotate>
);

css 헬퍼 사용도 가능

const rotate = keyframes`
 from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
`;

const animation = css`
  animation: ${rotate} 2s linear infinite;
`

const Rotate = styled.div`
	${animation};
`;

— Advanced —

Theming

<ThemeProvider> : 모든 컴포넌트에서 공유하는 styles 지정

const Button = styled.button`
  color: ${props => props.theme.fg};
  border: 2px solid ${props => props.theme.fg};
  background: ${props => props.theme.bg};

  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border-radius: 3px;
`;

// 공유할 styles 지정 
const theme = {
  fg: "palevioletred",
  bg: "white"
};

render(
  // ThemeProvider 안에 있는 어떤 컴포넌트들도 theme에 정의한 styles에 접근 가능
  <ThemeProvider theme={theme}>
    <div>
      <Button>Default Theme</Button>
    </div>
  </ThemeProvider>
);

Referring to other components

$ 를 사용하여 다른 컴포넌트를 참조할 수 있다

const Link = styled.a`
  display: flex;
  align-items: center;
  padding: 5px 10px;
  background: papayawhip;
  color: palevioletred;
`;

const Icon = styled.svg`
  flex: none;
  transition: fill 0.25s;
  width: 48px;
  height: 48px;

	// Link 태그를 호버했을 때 Icon의 style 적용 
  ${Link}:hover & {
    fill: rebeccapurple;
  }
`;

const Label = styled.span`
  display: flex;
  align-items: center;
  line-height: 1.2;

  &::before {
    content: '◀';
    margin: 0 10px;
  }
`;

render(
  <Link href="#">
    <Icon viewBox="0 0 20 20">
      <path d="M10 15h8c1 0 2-1 2-2V3c0-1-1-2-2-2H2C1 1 0 2 0 3v10c0 1 1 2 2 2h4v4l4-4zM5 7h2v2H5V7zm4 0h2v2H9V7zm4 0h2v2h-2V7z"/>
    </Icon>
    <Label>Hovering my parent changes my style!</Label>
  </Link>
);

1개의 댓글

comment-user-thumbnail
2021년 8월 31일

styled-components에서 제공하는 것들을 한 눈에 공부할 수 있는 좋은 글이네요 :)

답글 달기