본문 바로가기
JavaScript/React

[ReactJS] styled-components

by 혀나Lee 2018. 9. 3.

react 에서 CSS 를 사용하는 방법에는 몇가지가 있다.

  • inline - style 속성 사용 (참고: https://reactjs.org/docs/dom-elements.html#style)

    • CSS classes are generally better for performance than inline styles. (CSS class 를 사용하는 것이 일반적으로 inline styles 를 사용하는 것보다 성능이 좋다.)

var divStyle = {
  color: 'white',
  backgroudImage: 'url(' + imgUrl + ')',
  WebkitTranstion: 'all', // note the capital 'W' here
  msTransition: 'all' // 'ms' is the only lowercase vendor prefix
};
 
ReactDOM.render(<div style={divStyle}>Hello World!</div>, mountNode);
  • CSS 파일 사용 (참고: https://velopert.com/1555)

    • 의존 모듈(css-loader, style-loader) 설치 및 webpack.config.js 에 loaders 추가 필요

.container {
    position: fixed;
    width: 100%;
    height: 100%;
    background-color: black;
}
 
.hello {
    color: white;
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 3rem;
}
import React from 'react';
import styles from './App.css';
 
export default class App extends React.Component {
    componentWillMount() {
        document.body.style.margin = 0;
        document.body.style.padding = 0;
    }
 
    render() {
        return (
            <div className={styles.container}>
                <div className={styles.testing}>
                    hello
                </div>
            </div>
        );
    }
}
  • styled-components (참고: https://www.styled-components.com/)

    • CSS 파일을 사용할 경우, CSS 와 컴포넌트 파일이 떨어져있다보니 관리가 불편한 점이 있다. styled-components 는 컴포넌트를 생성할 때 스타일을 줄 수 있기때문에 CSS 파일을 따로 관리하지 않아도 된다는 장점이 있다.

const Button = styled.a`
  display: inline-block;
  border-radius: 3px;
  padding: 0.5rem 0;
  margin: 0.5rem 1rem;
  width: 11rem;
  background: transparent;
  color: white;
  border: 2px solid white;
 
  ${props => props.primary && css`
    background: white;
    color: palevioletred;
  `}
 `

styled-components

설치

npm install --save styled-components

styled-components babel plugin 을 사용하는 것을 매우 추천한다. (필수 아님) 읽기 쉬운 클래스 이름, 서버 측 렌더링 호환성, 더 작은 번들 등과 같은 많은 이점을 제공한다.

npm install --save --dev babel-plugin-styled-components

.babelrc 에 “styled-components” 플러그인을 추가한다.

{
  "presets": ["env", "react"],
  "plugins": ["styled-components"]
}

시작하기

styled-components 는 태그가 있는 템플릿 리터럴을 사용하여 컴포넌트의 스타일을 지정한다.

기존에 컴포넌트를 <h1> 태그를 사용하고 class 를 통해 스타일을 줬다면 styled-components 는 styled.h1 을 사용하고 `` 안에 CSS 를 작성하면 된다.

CSS 코드와의 비교

  • CSS 사용 코드

import styles from './styles.css';
 
class Counter extends Component {
  state = {/* .. */}
  increment = () => {/* ... */}
  decrement = () => {/* ... */}
  render() {
    return (
      <div className={styles.counter}>
        <p className={styles.paragraph}>{this.state.count}</p>
        <button className={styles.button} onClick={this.increment}>+</button>
        <button className={styles.button} onClick={this.decrement}>-</button>
      </div>
    )
  }
}
  • styled-components 사용 코드

import styled from 'styled-components';
 
const StyledCounter = styled.div`/* ... */`;
const Paragraph = styled.p`/* ... */`;
const Button = styled.button`/* ... */`;
 
class Counter extends Component {
  state = {/* ... */}
  increment = () => {/* ... */}
  decrement = () => {/* ... */}
  render() {
    return (
      <StyledCounter>
        <Paragraph>{this.state.count}</Paragraph>
        <Button onClick={this.increment}>+</Button>
        <Button onClick={this.decrement}>-</Button>
      </StyledCounter>
    )
  
}

주의사항

render method 안에 styled component 를 만들지 말라.

// good

const StyledWrapper = styled.div`/* ... */`;
 
const Wrapper = ({ message }) => {
  return <StyledWrapper>{message}</StyledWrapper>
};

// bad

const Wrapper = ({ message }) => {
  // WARNING: THIS IS VERY VERY BAD AND SLOW, DO NOT DO THIS!!!
  const StyledWrapper = styled.div`/* ... */`;
   
  return <StyledWrapper>{message}</StyledWrapper>
};

컴포넌트의 render 함수 안에 styled-component 는 공식 사이트에서도 반대하는 아주 나쁜 코드방식이다. 이렇게 작성할 경우 Wrapper 컴포넌트가 렌더링이 될 때마다 StyledWrapper 를 생성하기 때문이다. (원래 render 함수에서 함수 생성 및 함수 바인딩도 하는 코드 방식도 안좋다.)

props 사용

const Button = styled.button`
  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 parimary>Primary<Button>
  </div>
);

외부 라이브러리 사용시 방법

// react-router-dom 의 Link 일 경우.
const Link = ({ className, children }) => {
  <a className={className}>
    {children}
  </a>
};
 
const StyledList = styled(Link)`
  color: palevioletred;
  font-weight: bold;
`;
 
render(
  <div>
    <Link>Unstyled, boring Link</Link>
    <br />
    <StyledLink>Styled, exiting Link</StyledLink>
  </div>
);

스타일 상속

const Button = styled.button`
  color: palevioletred;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;
 
const TomatoButton = styled(Button)`
  color: tomato;
  border-color: tomato;
`;
 
render(
  <div>
    <Button>Noraml Button</Button>
    <TomatoButton>Tomato Button</TomatoButton>
  </div>
);

attribute

const Input = styled.input.attrs({
  type: 'password',
  margin: props => props.size || '1em',
  padding: props => props.size || '1em'
})`
  color: palevioletred;
  font-size: 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
  margin: ${props => props.marin};
  pading: ${props => props.padding};
`;
  
 render (
   <div>
     <Input placeholder="A small text input" size="1em" />
     <br />
     <Input placeholder="A bigger text input" size="2em" />
   </div>
 );

Animations

const rotate360 = keyframes`
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
};
 
const Rotate = styled.div`
  display: inline-block;
  animation: ${rotate360} 2s linear infinite;
  padding: 2rem 1rem;
  font-size: 1.2rem;
`;
 
render(
  <Rotate>test</Rotate>
)


더 자세한 내용은 공식 사이트를 참고하시기 바랍니다. https://www.styled-components.com/docs/advanced

'JavaScript > React' 카테고리의 다른 글

[React] Stateless Component  (0) 2018.11.30
[ReactJS] React private route 로그인 권한  (0) 2018.10.16
React 로 TDD 쵸큼 맛보기  (0) 2018.07.20
[ReactJS] scroll to top  (0) 2017.07.31
[React] 속도 향상  (0) 2017.07.25

댓글