1. 인라인 스타일
App.jsx
function App() {
return <button style={{ backgroundColor: 'green' }} />
}
export default App
2. CSS
- 컴포넌트를 스타일링하는 가장 기본적인 방식
- CSS 클래스를 중복되지 않게 만들어야함
- CSS 클래스가 중복되는 것을 방지하기 위해 1) 이름을 지을 때 특별한 규칙을 사용하거나 2) CSS selector를 활용한다
CSS 클래스 이름 짓는 2가지 방법
- 컴포넌트이름-클래스형태
- i.e.) App-header
- BEM 네이밍: Block__Element-Modifier
- class="컴포넌트이름__역할—세부특징"
- i.e.) card__title-primary
컴포넌트 스타일로 css를 사용할시 단점
상위 컴포넌트에서 불러온 css 코드가 하위 컴포넌트에까지 영향을 미치기 때문에 컴포넌트마다 다른 스타일을 개별적으로 적용하기가 힘들어진다. 각 컴포넌트별로 스타일을 관리해주기 위해서 아래에서 소개할 SCSS, CSS Module, Styled-Components를 사용한다.
App.jsx
import Button from './components/Button'
function App() {
return (
<>
<Button size="large" color="tomato" />
<Button size="medium" color="orange" />
<Button size="small" color="skyblue" />
</>
)
}
export default App
Button.jsx
import React from 'react'
import '../styles/Button.css'
function Button({ size, color }) {
return (
<button className={`button ${size} ${color}`}>
버튼
</button>
)
}
export default Button
Button.css
.button {
outline: none;
border: none;
display: flex;
align-items: center;
justify-content: center;
background-color: green;
border-radius: 10px;
color: white;
margin: 10px;
width: 60px;
height: 30px;
font-size: 16px;
}
.large {
width: 140px;
height: 70px;
font-size: 24px;
}
.medium {
width: 120px;
height: 60px;
font-size: 20px;
}
.small {
width: 100px;
height: 50px;
font-size: 16px;
}
.tomato {
background-color: tomato;
}
.orange {
background-color: orange;
}
.skyblue {
background-color: skyblue;
}
3. SCSS
- yarn add sass로 sass라이브러리를 설치해야함
- 라이브러리는 Sass를 CSS로 변환시켜줌
- CSS의 전처리기 중 하나
- CSS를 더 쉽게 작성할 수 있게 해줌
- 스타일 코드의 재활용성을 높여줌
- 코드의 가독성을 높여 유지 보수를 더 쉽게 해줌
- 두가지 확장자 .scss와 .sass를 지원한다
utils 함수 분리하기
@import './styles/utils.scss';
Scss 변수, 믹스인은 utils.scss로 따로 분리하여 작성한 뒤 필요한 곳에서 불러와 사용할 수 있다
sass-loader 설정 커스터마이징하기
@import '../../../styles/utils';
문제
프로젝트 디렉토리를 많이 만들어 구조가 깊어졌다면 해당 파일에 접근할때 상위 폴더로 한참 거슬러 올라가야 한다는 단점이 생긴다.
해결
웹팩에서 Sass를 처리하는 sass-loader의 설정을 커스터마이징하여 해결
sass-loader에 접근하는 방법
create-react-app으로 만든 프로젝트는 프로젝트 구조의 복잡도를 낮추기 위해 웹팩 관련된 세부 설정이 숨겨져 있다
1) yarn eject 명령어로 create-react-app으로 만든 프로젝트의 세부설정을 밖으로 꺼내준다.
2) yarn eject를 하기전에 커밋을 먼저 해주어야 한다 git commit -m "Commit before yarn eject"
3) config > webpack.config.js 파일을 수정한다.
App.jsx
import Button from './components/Button'
function App() {
return (
<>
<Button size="large" color="tomato" />
<Button size="medium" color="orange" />
<Button size="small" color="skyblue" />
</>
)
}
export default App
Button.jsx
import React from 'react'
import '../styles/Button.scss'
function Button({ size, color }) {
return (
<button className={`button ${size} ${color}`}>
버튼
</button>
)
}
export default Button
Button.scss
$main-color: green;
.button {
outline: none;
border: none;
display: flex;
align-items: center;
justify-content: center;
background-color: $main-color;
border-radius: 10px;
color: white;
margin: 10px;
&.large {
width: 140px;
height: 70px;
font-size: 24px;
}
&.medium {
width: 120px;
height: 60px;
font-size: 20px;
}
&.small {
width: 100px;
height: 50px;
font-size: 16px;
}
&.tomato {
background-color: tomato;
}
&.orange {
background-color: orange;
}
&.skyblue {
background-color: skyblue;
}
}
4. CSS Module
- 자동으로 클래스 이름을 고유한 값으로 만들어서 컴포넌트 스타일 클래스 이름이 중첩되는 현상을 방지해주는 기술
- 형식: [파일 이름]_[클래스 이름]_[해시값]
CSS Module을 사용하기 위해 필요한 패키지
CSS Module을 사용하기 위해 css-loader 패키지가 필요하다. 다만 CRA로 리액트 프로젝트를 만들면 기본적으로 설치가 되어있으므로 바로 사용이 가능하다.
CSS Module 사용하기
import style from './파일이름.module.css';
console.log(style)
// {button: 'Button_button__A76z0', large: 'Button_large__sDlIm'}
- 파일이름.module.css 확장자로 파일을 저장하면 자동으로 CSS Module이 적용된다
- CSS Module이 적용된 스타일 파일을 불러오면 객체를 하나 전달받는다
- CSS Module에서 사용한 클래스 이름과 해당 이름을 고유화한 값이 키-값 형태로 들어 있다
- { className: '[파일 이름]_[클래스 이름]_[해시값]' }
CSS Module로 만든 클래스 이름 사용하기
클래스가 하나일때
className={style.클래스이름}
클래스가 두개 이상일때
1. 템플릿 리터럴 사용
className={`${style.클래스이름} ${style.클래스이름}`}
2. 배열의 메서드 join 사용
className={[styles.클래스이름, styles.클래스이름].join(' ')}
CSS Module의 장점
CSS Module을 사용하면 컴포넌트마다 다른 고유값이 class 이름에 부여되므로 컴포넌트마다 공유하지 않는 독자적인 스타일 코드를 가질 수 있게 된다.
App.jsx
import Button from './components/Button'
function App() {
return (
<>
<Button size="large" color="tomato" />
<Button size="medium" color="orange" />
<Button size="small" color="skyblue" />
</>
)
}
export default App
Button.jsx
className으로 연결할 속성이 하나일때는 중괄호 { }안에 바로 넣어준다
import style from '../styles/Button.module.css'
function Button({ size, color }) {
return (
<button className={ style.button }>
버튼
</button>
)
}
export default Button
className으로 전달해줄 값이 두개 이상인 경우 템플릿 리터럴 형태로 사용
import React from 'react'
import style from '../styles/Button.module.css'
function Button({ size, color }) {
const cssSize = size
const cssColor = color
return (
<button className={ `${style.button} ${style[cssSize]} ${style[cssColor]}` }>
버튼
</button>
)
}
export default Button
className으로 전달해줄 값이 두개 이상인 경우 배열의 메서드 join 사용
import React from 'react'
import style from '../styles/Button.module.css'
function Button({ size, color }) {
const cssSize = size
const cssColor = color
return (
<button
className={[style.button, style[cssSize], style[cssColor]].join(' ')}
>
버튼
</button>
)
}
export default Button
Button.module.css
.button {
outline: none;
border: none;
display: flex;
align-items: center;
justify-content: center;
background-color: green;
border-radius: 10px;
color: white;
margin: 10px;
width: 60px;
height: 30px;
font-size: 16px;
}
.large {
width: 140px;
height: 70px;
font-size: 24px;
}
.medium {
width: 120px;
height: 60px;
font-size: 20px;
}
.small {
width: 100px;
height: 50px;
font-size: 16px;
}
.tomato {
background-color: tomato;
}
.orange {
background-color: orange;
}
.skyblue {
background-color: skyblue;
}
5. Styled-Components
스타일을 CSS나 SCSS처럼 외부 파일로 만드는것이 아닌 자바스크립트 파일에 내장시키는 방식
자바스크립트 파일 안에 스타일을 선언하는 CSS-in-JS 방식
스타일을 작성함과 동시에 해당 스타일이 적용된 컴포넌트를 만들 수 있게 해줌
자체적으로 클래스를 만들고 그 안에 설정한 스타일링이 들어간다
styled-components 라이브러리 설치
yarn add styled-components
vscode-styled-components 설치
styled-components 신텍스 하이라이팅 해주는 extension
styled components의 장점
- 자바스크립트 파일 하나에 스타일까지 작성할 수 있기 때문에 스타일 파일을 따로 만들지 않아도 된다
- props 값으로 전달해주는 값을 쉽게 스타일에 적용할 수 있다
styled components 사용방법
1. 폴더 구조 만들어주기
components 폴더 안에 사용할 컴포넌트명으로 폴더를 만들어주고 그 안에 index.jsx 파일에는 컴포넌트를 생성하고 style.js파일에는 스타일을 적용한다.
2. App.jsx 파일에 Button 컴포넌트 import 해주기
import Button from './components/Button'
// Button 폴더 안에 있는 index.jsx를 찾아 자동으로 import 해주게 된다
// index 파일은 import할때 생략할 수 있다
function App() {
return (
<>
<Button />
</>
)
}
export default App
3. index.js에 버튼으로 사용할 컴포넌트 만들기
import React from 'react'
const Button = () => {
return <button>버튼</button>
}
export default Button
4. style.js에 SCSS 코드 넣기
import styled from 'styled-components'
export const ButtonStyle = styled.button`
/* SCSS 코드 */
`
5. index.js에 style.js에서 만든 SCSS 코드 import해오기
방법1
style.js
import styled from 'styled-components'
export const ButtonStyle = styled.button`
/* SCSS 코드 */
`
index.js
import React from 'react'
import { ButtonStyle } from './style.js'
const Button = () => {
return <ButtonStyle>버튼</ButtonStyle>
}
export default Button
방법2
style.js
import styled from 'styled-components'
export const Button = styled.button`
/* SCSS 코드 */
`
index.js
스타일 컴포넌트를 S.Button처럼 작성함으로서 Button과 같은 실제 컴포넌트와 차이를 줄 수 있다.
import React from 'react'
import * as S from './style.js'
const Button = () => {
return <S.Button}>버튼</S.Button>
}
export default Button
styled-components를 사용해서 props 값 넘겨주기
1. 기본 구조
index.jsx
import React from 'react'
import * as S from './style.js'
const Button = () => {
return (
<>
<S.Button color="tomato">버튼</S.Button>
<S.Button color="orange">버튼</S.Button>
<S.Button color="skyblue">버튼</S.Button>
</>
)
}
export default Button
style.js
import styled from 'styled-components'
export const Button = styled.button`
outline: none;
border: none;
display: flex;
align-items: center;
justify-content: center;
background-color: ${(props) => props.color};
border-radius: 10px;
color: white;
margin: 10px;
`
2. 구조분해할당하면서 props 전달
import styled from 'styled-components'
export const Button = styled.button`
outline: none;
border: none;
display: flex;
align-items: center;
justify-content: center;
background-color: ${({color}) => color};
border-radius: 10px;
color: white;
margin: 10px;
`
3. props값이 없을때 default 값 지정
import styled from 'styled-components'
export const Button = styled.button`
outline: none;
border: none;
display: flex;
align-items: center;
justify-content: center;
background-color: ${({ color }) => color || 'green'};
border-radius: 10px;
color: white;
margin: 10px;
`
4. props와 함께 삼항연산자 사용하기
import React from 'react'
import * as S from './style.js'
const Button = () => {
return (
<>
<S.Button color="tomato" isClicked={true}>
버튼
</S.Button>
</>
)
}
export default Button
import styled from 'styled-components'
export const Button = styled.button`
outline: none;
border: none;
display: flex;
align-items: center;
justify-content: center;
background-color: ${({ isClicked }) => isClicked ? 'green' : 'gray'};
border-radius: 10px;
color: white;
margin: 10px;
`
theme에 색상변수 저장해서 사용해주기
theme.js
theme.js 파일에 자주 사용하는 색상 코드 등록해주기
const colors = {
primary: '#007bff',
success: '#28a745',
danger: '#dc3545',
}
const theme = {
colors,
}
export default theme
App.jsx
theme.js에 등록한 스타일코드를 전역적으로 사용할 수 있도록 ThemeProivder로 전체 컴포넌트 감싸주기
import { ThemeProvider } from 'styled-components'
import theme from './styles/theme'
import Button from './components/Button'
function App() {
return (
<ThemeProvider theme={theme}>
<Button size="large" color="tomato" />
<Button size="medium" color="orange" />
<Button size="small" color="skyblue" />
</ThemeProvider>
)
}
export default App
style.js
theme으로 등록한 색상변수 style.js에서 props 값으로 받아서 사용하기
import styled from 'styled-components'
export const Button = styled.button`
outline: none;
border: none;
display: flex;
align-items: center;
justify-content: center;
background-color: ${({ theme }) => theme.colors.primary};
border-radius: 10px;
color: white;
margin: 10px;
`
theme에 자주 사용하는 스타일코드 객체화해서 사용하기
theme.js
theme.js 파일에 자주 사용하는 스타일코드 객체화해서 등록해주기
const colors = {
primary: '#007bff',
success: '#28a745',
danger: '#dc3545',
}
const common = {
flexCenter: `
display: flex;
align-items: center;
justify-content: center;
`,
}
const theme = {
colors,
common,
}
export default theme
style.js
import styled from 'styled-components'
export const Button = styled.button`
${({ theme }) => theme.common.flexCenter}
outline: none;
border: none;
background-color: ${({ theme }) => theme.colors.primary};
border-radius: 10px;
color: white;
margin: 10px;
`
keyframes 사용해서 애니메이션 효과주기
style.js
import styled, { keyframes } from 'styled-components'
const fadeIn = keyframes`
from {
opacity: 0
}
to {
opacity: 1
}
`
export const Button = styled.button`
${({ theme }) => theme.common.flexCenter}
outline: none;
border: none;
background-color: ${({ theme }) => theme.colors.primary};
border-radius: 10px;
color: white;
margin: 10px;
animation-name: ${fadeIn};
animation-duration: 1s;
animation-timing-function: ease-out;
`
globalstyle 사용해서 폰트 추가하기
globalStyle.js
import { createGlobalStyle } from 'styled-components'
import BlackHanSans from '../assets/fonts/BlackHanSans-Regular.ttf'
export default createGlobalStyle`
@font-face {
font-family: "BlackHanSans";
src: url(${BlackHanSans}) format('truetype');
}
`
format() 안에 들어가는 부분은 폰트 파일의 확장자에 따라서 변경해주어야한다:
- otf 파일 → opentype
- ttf 파일 → truetype
- woff 파일 → woff
App.js
globalstyle을 import한후 ThemeProvider 밑에 등록해주어 모든 컴포넌트에서 globalstyle에 접근할 수 있도록 해준다.
import GlobalStyle from './styles/globalStyle'
import { ThemeProvider } from 'styled-components'
import theme from './styles/theme'
import Button from './components/Button'
function App() {
return (
<ThemeProvider theme={theme}>
<GlobalStyle />
<Button size="large" color="tomato" />
<Button size="medium" color="orange" />
<Button size="small" color="skyblue" />
</ThemeProvider>
)
}
export default App
style.js
import styled, { keyframes } from 'styled-components'
const fadeIn = keyframes`
from {
opacity: 0
}
to {
opacity: 1
}
`
export const Button = styled.button`
${({ theme }) => theme.common.flexCenter}
outline: none;
border: none;
background-color: ${({ theme }) => theme.colors.primary};
border-radius: 10px;
color: white;
margin: 10px;
animation-name: ${fadeIn};
animation-duration: 1s;
animation-timing-function: ease-out;
font-family: 'BlackHanSans';
`
'React' 카테고리의 다른 글
[리액트] useContext 정리 (0) | 2022.08.22 |
---|---|
[리액트] useReducer 사용법 (0) | 2022.08.21 |
[리액트] props를 className으로 지정하기 (0) | 2022.08.12 |
[리액트] 리액트 프로젝트에서 기본적인 ESLint, Prettier, setting.json 설정해주기 (0) | 2022.08.11 |
[리액트] useRef의 두가지 기능 정리 (0) | 2022.08.10 |
댓글