안녕하세요. 박기린 입니다.
이번엔 ReactJS의 스타일링 모듈인 styled-components에 대해 알아보겠습니다.
공식 사이트 : https://styled-components.com/
styled-components가 필요한 이유
React 프로젝트의 컴포넌트들을 css 파일을 이용해서 스타일링하는 경우, 비록 컴포넌트 파일(js/ts)에서 css 파일을 import해서 사용한다고 해도, 그 css 파일의 스타일을 해당 컴포넌트에만 국한되지 않고 전역으로 적용시킵니다.
.form-control {
margin: 0.5rem 0;
}
.form-control label {
font-weight: bold;
display: block;
margin-bottom: 0.5rem;
}
예를 들어, 위와 같은 css 파일이 있다고 가정하자. 우연찮게 전혀 상관없는 컴포넌트에서 'form-control' 클래스를 가지고 있다면, 위의 css 파일에 적용된 '.form-control' 스타일이 같이 적용된다.
비록 selector을 중복되는 이름이 없도록 좀 더 신경써서 만들면 되긴 하지만, 큰 프로젝트는 여러 명의 개발자들이 붙들고 있고, 각자 다른 컴포넌트를 만들다가 이름이 겹칠 수 있다. 이를 방지하기 위해, 컴포넌트 단위로만 스타일을 줄 수 있는 방법으로 'styled-components'를 사용한다.
styled-components를 적용하기
기존 css 파일을 이용한 방식
// 기존 Button.js
import React from 'react';
import './Button.css';
const Button = props => {
return (
<button type={props.type} className="button" onClick={props.onClick}>
{props.children}
</button>
);
};
export default Button;
// 기존 Button.css
.button {
font: inherit;
padding: 0.5rem 1.5rem;
border: 1px solid #8b005d;
color: white;
background: #8b005d;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
cursor: pointer;
}
.button:focus {
outline: none;
}
.button:hover,
.button:active {
background: #ac0e77;
border-color: #ac0e77;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
}
styled-components를 사용한 방식
//변화된 Button.js
import styled from "styled-components";
const Button = styled.button`
font: inherit;
padding: 0.5rem 1.5rem;
border: 1px solid #8b005d;
color: white;
background: #8b005d;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
cursor: pointer;
&:focus {
outline: none;
}
&:hover,
&:active {
background: #ac0e77;
border-color: #ac0e77;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
}
`;
const Button = styled.button`
styled 객체를 styled-components로부터 import 한 후, 뒤에 html tag의 이름을 넣고, 백틱(``)을 넣어서 사용합니다.
Tagged Template Literal
styled-componets가 사용하는 백틱(``)을 Tagged Template Literal이라고 부릅니다. 자바스크립트의 기본 기능으로, 어떤 자바스크립트 프로젝트에서도 사용이 가능하며, 이전에 자바스크립트 강의노트에서 설명을 드린 적이 있습니다. (https://arnopark.tistory.com/475)
button은 styled 객체의 메소드입니다. 일반적인 메소드들은 (괄호)를 뒤에 붙이지만, styled 객체의 html 태그 메소드들은 백틱(``)을 붙여서 사용합니다. 이 `백틱`사이에 전달하는 스타일링 값들이 button 메소드로 전달됩니다. 그리고 이 값을 받은 button 메소드가 새로운 Button 컴포넌트를 반환합니다.
(styled-componets는 모든 html element를 메소드로 지원합니다.)
Pseudo-class
&:focus {
outline: none;
}
&:hover,
&:active {
background: #ac0e77;
border-color: #ac0e77;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
}
`;
styled-componets에서 css의 가상 선택자(pseudo - class / selector)는 '&' 기호를 사용합니다.
styled-components의 build 출력방식
styled-componets를 적용한 후, build한 html파일을 살펴보면 위처럼 암호같이 생긴 class가 생성된다. 컴포넌트 단위로 css Class를 지정해줘야 하기 때문에, styled-componets가 자동으로 복잡한 class를 생성해서 넣어준다.
styled-components의 동적 스타일링
const FormControl = styled.div`
margin: 0.5rem 0;
& label {
font-weight: bold;
display: block;
margin-bottom: 0.5rem;
color: ${(props) => (props.invalid ? "red" : "black")};
}
& input {
display: block;
width: 100%;
border: 1px solid ${(props) => (props.invalid ? "red" : "#ccc")};
background-color: ${(props) => (props.invalid ? "#ffd7d7" : "transparent")};
font: inherit;
line-height: 1.5rem;
padding: 0 0.25rem;
}
& input:focus {
outline: none;
background: #fad0ec;
border-color: #8b005d;
}
`;
color: ${(props) => (props.invalid ? "red" : "black")};
styled-components도 동적 스타일링을 완벽히 지원합니다.
styled 객체로 생성된 컴포넌트도 리액트 컴포넌트이므로 props를 전달받을 수 있습니다.
${(props) => (props.prop이름 ? "스타일링1" : "스타일링2")};
`template literal`에 ${string interpolation}을 사용한 후, 그 안에 props가 인수로 전달되는 함수를 넣어주면 됩니다. 이 함수는 css 스타일이 적힌 String을 return해야만 합니다.
Media Query
const Button = styled.button`
width: 100%;
font: inherit;
padding: 0.5rem 1.5rem;
border: 1px solid #8b005d;
color: white;
background: #8b005d;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
cursor: pointer;
@media (min-width: 768px) {
width: auto;
}
{...}
`
styled-componets에서도 미디어 쿼리(@media)를 이용해서 기기의 화면 크기에 따라 다르게 보이도록 설정할 수 있습니다
미디어쿼리에 지정된 width보다 좁은 경우(너비가 768px 미만)면 버튼의 width가 100%,
미디어쿼리에 지정된 width보다 넓은 경우면 버튼의 width가 auto로 동작합니다.
'JS > React 강의' 카테고리의 다른 글
[React] 13. useEffect() 사용법 총정리 (0) | 2023.07.20 |
---|---|
[React] 12. CSS 모듈 사용하기 (0) | 2023.03.28 |
[React] 10. useRef(), ref에 대해 알아보기 (0) | 2023.03.06 |
[React] 9. 리스트 데이터 출력하기 (0) | 2023.03.03 |
[React] 8. <form /> 태그 다루기 (0) | 2023.02.23 |