리액트에는 여러 스타일링 방법이 있다.
- inline style
- stylesheet with className
- css module
- CSS-in-JS
CSS-in-JS 방법을 많이 사용하며 그 중에서도 대중적으로 사용하는 styled-components에 대해 알아보겠다.
npm i styled-components
먼저 styled-components를 import 한다.
import styled from "styled-components";
styled.button을 생성한다. styled.<태그> 해당 <태그>부분에 html 태그 이름을 넣음으로서 생성이 가능하다. 태그 뒤에는 백틱( ` )을 쓰며 그 안에 스타일을 정의해준다. 스타일은 Scss 정의가 가능하다.
const Btn = styled.button`
color: white;
background-color: tomato;
border: 0;
border-radius: 15px;
`;
vscode에서 사용중이라면 아래 extension을 설치해주면 편하다.
vscode-styled-components
React
컴포넌트처럼 작성한다.
function App() {
return (
<Btn>Log in</Btn>
);
}
HTML
랜덤한 클래스가 부여되어 스타일이 입혀진다.
<button class="sc-OKtSx hLMzlZ">Log in</button>
먼저 정의된 스타일 컴포넌트의 스타일을 상속받아 사용이 가능하다.
const Box = styled.div`
background-color: teal;
width: 100px;
height: 100px;
`;
const Circle = styled(Box)`
border-radius: 50px;
`;
<Box />
<Circle />
스타일 내부에서 props 사용이 가능하다.
const Box = styled.div`
background-color: ${props => props.bgColor};
`;
<Box bgColor="teal" />
<Box bgColor="tomato" >
const Box = styled.div`
background-color: ${props => (props.invalid ? 'teal' : 'tomato')}
`;
<Box invalid={isValid} />
const Input = styled.input.attrs({ required: true })`
background-color: tomato;
`;
<Input />
// in HTML
<input required="" class="sc-kuWgmH cqgciL">
컴포넌트에 as 속성을 사용하여 스타일은 유지하되 태그 타입만 변경이 가능하다.
const Btn = styled.button`
border: 2px solid tomato;
color: tomato;
`;
<Btn>Button</Btn>
<Btn as="a" href="/">Link with Btn style</Btn>
const Component = styled.div`
color: red;
`;
<Component as="button" onClick={() => alert('It works!')}>
Hello World!
</Component>
Scss 방식으로 selector 지정이 가능하다.
const Box = styled.div`
background-color: teal;
&.isvalid {
background-color: tomato;
}
`;
<Box className={isValid && "isvalid"} />
const Emoji = styled.span`
font-size: 36px;
`;
const Box = styled.div`
background-color: tomato;
${Emoji} {
&:hover {
font-size: 56px;
}
}
`;
<Box>
<Emoji>😀</Emoji>
</Box>
animation을 사용하기 위해선 'keyframes'를 불러와야 한다.
import styled, { keyframes } from "styled-components";
그리고 컴포넌트 생성과 비슷하게 작성해준다.
const rotateAnimate = keyframes`
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
`;
const Box = styled.div`
animation: ${rotateAnimate} 1s linear infinite;
`;
export하여 다른 곳에서 import하여 사용할 수도 있다.
styled-components는 테마 기능을 지원한다.
index.js에서 ThemeProvider를 import하여 사용 가능하다.
// index.js
import React from "react";
import ReactDOM from "react-dom/client";
import { ThemeProvider } from "styled-components";
import App from "./App";
const darkTheme = {
textColor: "whitesmoke",
backgroundColor: "#111",
};
const lightTheme = {
textColor: "#111",
backgroundColor: "whitesmoke",
};
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<ThemeProvider theme={lightTheme}>
<App />
</ThemeProvider>
</React.StrictMode>
);
// App.js
import styled from "styled-components";
const Title = styled.h1`
color: ${(props) => props.theme.textColor};
`;
const Wrapper = styled.div`
background-color: ${(props) => props.theme.backgroundColor};
`;
function App() {
return (
<Wrapper>
<Title>Hello</Title>
</Wrapper>
);
}
기본적인 설정 방법이며 다크 모드와 라이트 모드의 속성명이 동일해야 한다.