
styled-components는 React에서 스타일을 작성하기 위한 CSS-in-JS 라이브러리이다. 스타일을 컴포넌트 형태로 정의하고 관리하며, JavaScript, TypeScript를 사용해 스타일을 동적으로 생성할 수 있다.
style.css
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
font-family: -apple-system;
}
위와 같은 CSS 파일을 만들고 난 뒤,
index.jsx
import { createRoot } from "react-dom/client";
import App from "./App";
import "./style.css";
createRoot(document.getElementById("root")).render(<App />);
위와 같이 js 파일에서 불러온다.
이렇게 CSS 파일을 불러오게 되면 JavaScript 파일 안에 있는 모든 내용이 만든 모든 페이지에 스타일이 적용된다.
JavaScript 파일에서 import를 통해 CSS를 불러오게 된다면 스타일 코드들이 어플리케이션 전체에 적용되므로 주의할 필요가 있다.
index.jsx
function App() {
<div style={{ color: "white", backgroundColor: "black" }}>hello world!</div>;
}
위와 같이 style 속성을 사용해 스타일을 지정한다.
인라인 스타일 속성을 사용하게 되면 JavaScript 형식의 코드를 적어야 하고, :hover, :active와 같은 속성을 사용할 수 없다는 단점이 있다.
App.module.css
.box {
background-color: black;
color: white;
}
index.jsx
import styles from "./App.module.css";
function App() {
<div className={styles.box}>hello world!</div>;
}
module.css파일에 일반적인 CSS 작성 방식으로 CSS를 작성하고, className들을 오브젝트의 속성인 것처럼 사용한다.
css모듈의 장점은 className을 랜덤으로 만들어주어서 클래스들이 서로 충돌되는것을 막아준다.
하지만 계속해서 className들을 복사/붙여넣기 해야 한다는 단점이 있다.
이러한 문제를 해결하기 위해 탄생한것이 바로 styled-components다!
먼저, styled-components를 설치하려면 아래와 같은 명령어를 실행하면 된다.
npm i styled-components
import styled from "styled-components";
const {컴포넌트명} = styled.{HTML태그}`
// css 코드
background-color: white;
width: 1000px;
height: 100px;
`;
이렇게 생성한 컴포넌트는 자동으로 class명을 만들어주고, 그 클래스 안에 스타일 코드를 담아준다.

아래의 인라인 스타일을 통해 작성한 코드를
function App() {
return (
<div style={{ display: "flex" }}>
<div style={{ backgroundColor: "white", width: "100px", height: "100px" }}></div>
<div style={{ backgroundColor: "black", width: "100px", height: "100px" }}>
<span style={{ color: "white" }}>hello world!</span>
</div>
</div>
);
}
export default App;
styled-components를 사용하면 아래와 같이 작성할 수 있다
import styled from "styled-components";
const Container = styled.div`
display: flex;
`;
const WhiteBox = styled.div`
background-color: white;
width: 100px;
height: 100px;
`;
const BlackBox = styled.div`
background-color: black;
width: 100px;
height: 100px;
`;
const Text = styled.span`
color: white;
`;
function App() {
return (
<Container>
<WhiteBox />
<BlackBox>
<Text>hello world!</Text>
</BlackBox>
</Container>
);
}
export default App;
하지만 WhiteBox, BlackBox는 background-color만 다르고 width, height값은 같다는 문제가 있다.
이 문제를 해결하기 위해 styled-components에서는 프로퍼티(props)를 통해 컴포넌트에 데이터를 전달할 수 있다.
아래 코드와 같이 components에 자신이 지정한 props의 이름을 components를 선언할 때 ${(props) => props.{propsName};
이렇게 작성하면 {속성이름}="속성값"의 속성값이 components에 전달된다.
const Box = styled.div`
background-color: ${(props) => props.bgColor};
width: 100px;
height: 100px;
`;
function App() {
return (
<>
<Box bgColor="white" />
<Box bgColor="black" />
</>
);
}
export default App;
위 코드의 첫 번째 Box 컴포넌트는 bgColor="white"를 넘겨줬으니 background-color: ${(props) => props.bgColor};가 값을 받아 코드가 실행될 때에는 background-color: white;로 바뀌게 된다.
하지만 이렇게 React에게 표준 HTML 속성이 아닌 props를 전달하게 되면 경고가 발생한다.
이를 prop 이름에 $ prefix를 붙이면 해결된다. 자세한 설명은 이 글에서
prefix를 통해 아래와 같이 경고를 해결할 수 있다
const Box = styled.div`
background-color: ${(props) => props.$bgColor};
width: 100px;
height: 100px;
`;
function App() {
return <Box $bgColor='white' />;
}
export default App;
또한 위 코드의 Box의 스타일과 대부분의 스타일이 중복되는 다른 컴포넌트를 원한다면 스타일을 상속하는 새 컴포넌트도 생성할 수 있다.
const Box = styled.div`
background-color: ${(props) => props.$bgColor};
width: 100px;
height: 100px;
`;
const Circle = styled(Box)`
border-radius: 50px;
`;
위와 같이 작성하게 된다면 Box가 가지는 모든 스타일에 border-radius: 50px;이 추가된 컴포넌트가 만들어진다.
Circle은 Box의 bgColor props도 가져오기 때문에 색상도 지정할 수 있다.
function App() {
return (
<>
<Box $bgColor='white' />
<Circle $bgColor='black' />
</>
);
}
styled-components에서는 태그의 속성값도 변경할 수 있다.
const Input = styled.input.attrs({ required: true, minLength: 5 })`
background-color: black;
color: white;
`;
function App() {
return (
<>
<Input />
<Input />
<Input />
<Input />
<Input />
<Input />
</>
);
}
attrs를 통해 변경된 속성을 확인할 수 있다.
여기에 더해 컴포넌트의 스타일은 유지하면서 HTML태그만 변경할 수도 있다.
const Btn = styled.button`
color: white;
background-color: black;
border: 0;
border-radius: 15px;
`;
function App() {
return (
<>
<Btn>Log in</Btn>
<Btn as='a' href='/logout'>
Log out
</Btn>
</>
);
}
컴포넌트에 as="태그이름"이라는 prop를 추가하면 components의 HTML태그만 변경할 수 있다.
위 코드에서는 button태그로 지정된 Btn 컴포넌트를 as="a"를 통해 anchor로 변경하였다.
as prop을 통해 태그를 변경한 컴포넌트도 변경한 컴포넌트의 속성을 설정할 수 있다. 위 코드에서는 태그를 anchor로 변경하였으니 href 속성을 사용할 수 있다.
styled-components에서는 Pseudo Selectors(가상 선택자)를 사용할 수 있다.
const Box = styled.div`
width: 200px;
height: 200px;
span {
font-size: 36px;
&:hover {
font-size: 48px;
}
}
`;
function App() {
return (
<Box>
<span>😭</span>
</Box>
);
}
위와 같이 Box 안의 span을 target 해 font-size와 같은 스타일을 지정할 수 있다.
또한 & 연산자를 통해 &:hover, &:active와 같은 속성도 사용할 수 있다.
const Box = styled.div`
width: 200px;
height: 200px;
span {
font-size: 36px;
&:hover {
font-size: 48px;
}
}
span:hover {
font-size: 48px;
}
`;
여기서 &:hover와 span:hover은 동일하게 동작한다.
하지만 여기서 Box 컴포넌트 안의 span 태그를 다른 태그로 변경하면 가상 선택자로 지정한 스타일은 태그 이름에 의존하고 있기 때문에 동작하지 않는다.
const Emoji = styled.span`
font-size: 36px;
`;
const Box = styled.div`
width: 200px;
height: 200px;
${Emoji}:hover {
font-size: 98px;
}
`;
function App() {
return (
<Box>
<Emoji as='a'>😭</Emoji>
</Box>
);
}
위와 같이 코드를 작성하면 as를 사용해 Emoji의 태그를 변경하여도 정상적으로 동작하는 것을 확인할 수 있다.
styled-components를 사용하는 중 모든 컴포넌트에 공통으로 적용되어야 하는 스타일이 필요한 경우가 있다.
이러한 경우 createGlobalStyle을 사용해 전역 스타일을 관리할 수 있다.
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
`;
ReactDOM.createRoot(document.getElementById("root")).render(
<ThemeProvider theme={darkTheme}>
<GlobalStyle />
<App />
</ThemeProvider>
);
createGlobalStyle로 생성한 GlobalStyle은 일반 컴포넌트처럼 사용할 수 있다.
App 컴포넌트와 함께 렌더링하면 앱 전체에 스타일이 적용된다.
styled-components는 ThemeProvider Warpper 컴포넌트를 통해 전체 앱 테마를 사용할 수 있다.
index.js
import ReactDOM from "react-dom/client";
import App from "./App";
import { ThemeProvider } from "styled-components";
const darkTheme = {
textColor: "white",
backgroundColor: "black",
};
const lightTheme = {
textColor: "black",
backgroundColor: "white",
};
ReactDOM.createRoot(document.getElementById("root")).render(
<ThemeProvider theme={darkTheme}>
<App />
</ThemeProvider>
);
ThemeProvider 컴포넌트는 자신의 아래에 있는 모든 요소에 테마를 사용할 수 있게 해준다.
<ThemeProvider theme={테마이름}> 형식으로 사용하면 된다.
지정한 테마 컬러를 사용하려면
const Title = styled.h1`
color: ${(props) => props.theme.textColor};
backgroundColor: ${(props) => props.theme.bgColor};
`;
위와 같이 사용하면 테마에 따라 다르게 색상이 적용된다.
styled-components의 기본 문법부터 추가 기능까지, 그리고 실제 프로젝트에서 어떻게 활용할 수 있는지 살펴보았습니다.
styled-components는 한마디로 "CSS의 컴포넌트화"입니다.
제 글이 styled-components를 전반적으로 이해하고 실무에 적용하는 데 도움이 됐으면 합니다.
우와! 정말 유익해요