[React] Styled-Component

GyungHo Go·2020년 5월 24일
1
post-thumbnail

Styled-Component

컴포넌트 스타일링의 또다른 패러다임은 자바스크립트 파일 안에 스타일을 선언하는 방식이다. 이 방식을 'CSS-in-JS'라고 부른다. 이와 관련된 라이브러리들은 정말 많다.
CSS-in-JS 라이브러리중에 개발자들이 가장 선호하는 Styled-Component를 알아보자.

Sytled-Component를 대체할 수 있는 라이브러리는 현재 emotion이 대표적이다. 작동 방식은 Styled-Component와 상당히 비슷하다.

Styled-Component는 react 및 react-native 개발에 사용되는데, 이것의 특장점은 자바스크립트 파일 하나에 스타일까지 작성할 수 있기 때문에 .css 또는 .scss 확장자를 가진 스타일 파일을 따로 만들지 않아도 된다는 큰 이점이 있다. 즉, CSS 파일 없이 자바스크립트 파일 안에서 CSS작업을 할 수 있다는 말이다.

설치
$ npm install styled-component

Styled-Component 생성

컴포넌트 외부에서 스타일 컴포넌트를 생성해서 랜더링 해주면 된다.
스타일 컴포넌트 이름은 대문자로 시작한다.

import React from 'react';
import styled from 'styled-components';

function App(){
	return(
     <Contanier>
      <Text>스타일 컴포넌트!</Text>
     </Contanier>
   );
}

const Contanier = styled.div`
	background-color : #f6a58d;
`;

const Text = styled.div`
	font-size:44px;
	font-weight:600;
`;

export default App;

styled. 뒤에는 HTML tag를 입력해 주면 된다. 백틱(``)내부에서는 스타일을 지정해 준다.
여기서 사용한 문법은 Tagged 탬플릿 리터럴 이라고 부른다.

styled-component를 사용하여 스타일린된 엘리먼트를 만들 때는 컴포넌트 파일의 상단에서 styled를 불러오고, styled.태그명을 사용하여 구현한다.

import styled from 'styled-component';

const MyComponent = styled.div`
	font-size : 2rem;
 `;

이렇게 styled.div 뒤에 Tagged 탬플릿 리터럴 문법을 통해 스타일을 넣어주면, 해당 스타일이 적용된 div로 이러우진 리액트 컴포넌트가 생성된다. 그래서 나중에 <MyComponent>Hello</MyComponent>와 같은 형태로 사용할 수 있다.
div가 아닌 button이나 input에 스타일링을 하고 싶다면 styled.button 이나 styled.input 같은 형태로 뒤에 태그명을 넣어주면 된다.

사용해야 할 태그명이 유동적이거나 특정 컴포넌트 자체에 스타일링해 주고 싶다면 다음과 같은 형태로 구현 할 수 있다.

예시 코드

//태그 타입을 styled 함수의 인자로 전달
const MyInput = styled('input')`
	background : gray ;
`
//아예 컴포넌트 형식의 값을 넣어줌
const StyledLink = styled(Link)`
	color:blue;
`

props 전달

styled-component와 일반 className를 사용하는 CSS/sass를 비교했을 때, 가장 큰 장점은 props 값으로 전달 해 주는 값을 쉽게 스타일링에 적용할 수 있다는 것이다.
styled-component를 사용하면 스타일 쪽에서 컴포넌트에게 전달된 props값을 참조할 수 있다.

이전에 작성했던 Box 컴포넌트를 다시 보면

const Box = styled.div`
  /* props 로 넣어준 값을 직접 전달해줄 수 있습니다. */
  background: ${props => props.color || 'blue'};
  padding: 1rem;
  display: flex;
`;

이 코드를 보면 background값에 props를 조회해서 props.color의 값을 사용하게 했다. 그리고 color값이 주어지지 않았을 때는 blue를 기본 색상으로 설정하였다.
이렇게 만들어진 코드는 JSX에서 사용될 때 다음과 같이 color값을 props로 넣어 줄 수 있다.

<Box color = "black">....</Box>

전달받은 props를 사용할 때에는 props를 매개변수로 하는 화살표함수를 사용해야 한다.

import React from 'react';
import styled from 'styled-components';

function App(){
	return(
     <Contanier>
      <Text>스타일 컴포넌트!</Text>
     </Contanier>
   );
}

const Contanier = styled.div`
	background-color : ${props => props.bgColor};
`;

const Text = styled.div`
	font-size:44px;
	font-weight:600;
`;

export default App;

${} 형식으로 자바스크립트를 사용할 수 있다.

state의 변화에 따라 서로 다른 스타일을 나타낼 때에는 다음과 같이 사용한다.

import React from 'react';
import styled from 'styled-components';

class App extends React.Component{
  state ={
    theme:"dark"
  };
	render(){
	 return(
    	 <Contanier>
    	  <Text>스타일 컴포넌트!</Text>
    	 </Contanier>
     );
  }
}

const Contanier = styled.div`
	background-color : ${props => (props.theme === "dark"? "black" : "white")};
`;

const Text = styled.div`
	font-size:44px;
	font-weight:600;
	color: ${props => (props.theme === "dark" ? "whtie" : "black")};
`;

export default App;

일반 CSS 클래스를 사용하여 조건부 스타일링을 해야 할 때는 className을 사용하여 조건부 스타일링을 해 왔다. styled-components에서는 조건부 스타일링을 간단하게 props로도 처리할 수 있다.

import React from 'react';
import styled, { css } from 'styled-components';
/*  단순 변수의 형태가 아니라 여러 줄의 스타일 구문을 조건부로 설정해야 하는 경우는
css를 불러와야 한다.*/

const Button = styled.button`
  background: white;
  color: black;
  border-radius: 4px;
  padding: 0.5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  font-size: 1rem;
  font-weight: 600;

  /* & 문자를 사용하여 Sass 처럼 자기 자신 선택 가능 */
  &:hover {
    background: rgba(255, 255, 255, 0.9);
  }

  /* 다음 코드는 inverted 값이 true 일 때 특정 스타일을 부여해줍니다. */
  ${props =>
    props.inverted &&
    css`
      background: none;
      border: 2px solid white;
      color: white;
      &:hover {
        background: white;
        color: black;
      }
    `};
  & + button {
    margin-left: 1rem;
  }
`;

이렇게 만든 컴포넌트는 다음과 같이 props를 사용하여 서로 다른 스타일을 적용할 수 있다.

<Button> 안녕하세요</button>
<Button inverted ={true}>테두리만 </button>

스타일 코드 여러줄을 props에 따라 넣어주어야 할 때는 CSS를 styled-components에서 불러 와야 한다. CSS를 사용하지 않고 다음과 같이 바로 문자열을 넣어도 작동하기는 한다.

${props => 
	props.inverted && 
  ` background :none; 
	border:2px solid white; 
	color:white;

	$:hover {
	 background:white;
	 color:black;
  }
`};

하지만 이럴 경우 Tagged 탬플릿 리터럴이 아니기 때문에 함수를 받아 사용하지 못해 해당 부분에서는 props 값을 사용하지 못한다는 치명적인 단점이 있다. 만약 조건부 스타일링을 할 때 넗는 여러 줄의 코드에서 props를 참조하지 않는다면 굳이 CSS를 불러와서 사용하지 않아도 상관없다. 하지만 props를 참조한다면, 반드시 CSS로 감싸주어서 Tagged 탬플릿 리터럴을 사용해 주어야 한다.

참조
https://codingbroker.tistory.com/17?category=799514
https://codingbroker.tistory.com/29
[서적] 리액트를 다루는 기술

profile
기록하는 습관

1개의 댓글

comment-user-thumbnail
2021년 4월 27일

감사합니다

답글 달기