Styled Components

이찬영·2025년 1월 4일

CSS를 Javascirpt로 작성할 수 있는 장점 + 작업속도 향상을 위해 styled Components라는 것을 사용한다.

기본 사용법

npm install styled-components;

우선 파일은 .js로 만든다

import styled from 'styled-components';

const Button = styled.button`
	background-color : #123456;
	padding : 16px;
`;

export default Button;

즉, styled를 import 해주고, 컴포넌트 이름을 만든 뒤, styled.tagname(tagname부분에는 스타일을 적용할 HTML태그 이름을 쓰면 된다.)을 해주고, 백틱 + 리터럴 문법으로 CSS코드를 적어준다.
그리고, 다른 컴포넌트에서 쓰려면

<Button>Hello styled!</Button>

이런식으로 <button>태그 대신 내가 만든 스타일이 씌어진 button컴포넌트를 쓸 수 있게 된다.

Nesting 문법

Nesting 문법이란 styled components에서 지원하는 문법이다.
Nesting은 CSS규칙안에서 CSS규칙을 만드는것을 말하고, Nesting을 활용하는 두가지 방법에는 &선택자와 컴포넌트 선택자가 있다.

&선택자

import styled from 'styled-components';

const Button = styled.button`
	background-color : #123456;
	padding : 16px;

	&:hover {
		background-color : #654321;
	}
`;

export default Button;

Nesting에서 &은 부모 선택자를 의미한다. 위 코드에서는 버튼 컴포넌트의 클래스를 뜻하는 것이다.

컴포넌트 선택자

버튼안에 아이콘을 배치하는ㄴ 상황으로 예를 들어보면, 버튼 텍스트 왼쪽에 아이콘을 배치하고 그 사이에 마진을 4px를 주려고 하는 가정이다. 우선 styledComponents로 Icon과 styledButton 컴포넌트를 각각 만들고, StyledButton안에 Icon을 배치한다. 이때, StyledButton컴포넌트 안에서 Icon컴포넌트를 선택해서 별도로 margin-right : 4px라는 속성을 지정해보자.

import styled from 'styled-components';
import img from 'assets/img';

const Icon = styled.img`
	width : 16px;
	hegith : 16px;
`;

const StyledButton = styled.button`
	background-color : #123456;
	border : none;
	padding : 16px;

	&${Icon} {
		margin-right : 4px;
	}

	&:hover {
		background-color : #654321;
		
		&{Icon} {
			opacity : 0.2;
		}
	}
`;

function Button ({children}) {
	return (
    	<StyledButton>
      		<Icon src={img} alt="Icon-image" />
      		{children}
      	</StyledButton>
    )
}

이럴 경우, 컴포넌트를 선택자로 쓰고 싶을때 ${Icon}과 같이 컴포넌트 자체를 템플릿 리터럴 안에 넣어주면 된다.

자손 결합자로 쓴 &${Icon}과 &을 사용하는 경우에는 &을 생략할 수 있는데, 보통 간편하게 많이 쓰니까 자손 결합자로 Nesting할때는 생략하는것을 권장한다.

참고로 Nesting은 위 코드 처럼 여러겹으로 할수도 있다. Nesting된 규칙안에서 규칙을 만들 수 있다는것이다.

다이나믹 스타일링

import styled from 'styled-components';

const SIZES = {
	large : 24,
  	medium : 20,
  	small : 16,
};

const Button = styled.button`
	background-color : #000000;
	border-radius : ${({round}) => round ? `9999px` : `3px`};
	font-size : ${({size}) => SIZES[size] ?? SIZES['medium']}px;
`;

export default Button;
//App.js

function App() {
	return (
    	<Button round size="large">large Button</Button>
      	// Button컴포넌트에 round가 있고(9999px), size는 large니까 SIZES['large']
    )
}

이렇게 자바스크립트 코드를 삽입할 수 있다. JSX에서 prop이나 state에 따라 HTML태그를 다르게 보여주는것과 비슷하다.

이렇게 사용할 때 size Prop에 값이 없거나 잘못된 값이면 styled Component는 undefined값을 빈 문자열로 처리해주기 때문에 font-size : px와 같이 잘못된 CSS코드가 된다. 그래서 널 병합연산자(??)라던가 삼항 연산자를 통해 Prop이 없을때의 경우를 정해주는것이 올바르다.

핵심 :

  • 동적 스타일링 : Prop값을 활용해 스타일을 동적으로 설정
  • 기본값 설정 : Prop값이 없거나 잘못된 경우를 대비해 기본값을 지정한다.

상속

  1. styled()함수로 스타일 상속하기
  • styled()함수를 사용하면 다른 styled component의 스타일을 그대로 상속할 수 있다.
  • 기존 컴포넌트에 추가적인 스타일을 입힐 때 유용하다.

예시 :

const SubmitButton = styled(Button)`
	background-color : #de117d;
	
	&:hover {
		background-color : #f5070f;
	}
`;
  1. JSX로 만든 컴포넌트에 스타일 적용
  • JSX로 만든 컴포넌트는 className프로퍼티를 전달해야만 스타일 적용이 가능하다.
  • 이유 : styledComponents는 className으로 스타일을 적용하기 때문임

예시 :

function TermsOfService({className}) {
	return (
    	<div className={className}>/*내용*/</div>
    )
}


// styled component

const TermsOfServiceStyle = styled(TermsOfService)`
	background-color : #ededed;
	border-radius : 8px;
	padding : 16px;
`;
  1. 정리
  • styled component : 바로 styled()함수로 상속이 가능하다.
  • JSX컴포넌트 : className프롭을 내려주어야만 styled함수로 스타일 적용이 가능하다.

중복 CSS코드 사용

  1. 반복되는 CSS코드 문제
  • 동일한 스타일을 여러 컴포넌트에 적용할 때 같은 코드를 반복 작성하면 유지보수에 어려움이 생긴다.

예시 :

const Button = styled.button`
	font-size = ${({size}) => SIZES[size] ?? SIZES['medium']}px;


const Input = styled.input`
	font-size : ${({size}) => SIZES[size] ?? SIZES['medium']}px;
`;
`;

이와 같이 중복된 코드가 생긴다면 유지보수에 귀찮아진다.

  1. CSS함수 사용
  • 이 처럼 반복되는 스타일을 CSS태그함수로 정의하고 재사용
  • Props를 사용하는 경우 반드시 css함수를 사용해야 한다.

예시 :

const SIZES = {
	large : 24,
  	medium : 20,
  	small : 16,
};

// 재사용 가능한 스타일 정의
const fontSize : css`
	font-size : ${({size}) => SIZES[size] ?? SIZES['medium']}px;
`;
// 컴포넌트에서 이를 재사용
const Button = styled.button`
	${fontSize}
`;

const Input = styled.input`
	${fontSize}
`;
  1. 단순한 문자열 스타일
  • Props를 사용하지 않는 경우 단순한 템플릿 리터럴로 작성이 가능하다.
  • 하지만 css함수를 습관화하는것이 좋다.

글로벌 스타일

최상위 컴포넌트에 선언한다.

const GlobalStyled = createGlobalStyle`
	* {
		box-sizing : border-box;
		margin : 0;
		padding : 0;
	}

	body {
		font-family : sans-serif;
	}
`;

const App() {
	return (
    	...
      	<GlobalStyled />
      	...
    )
}

애니메이션

키프레임

  1. 애니메이션의 기준점
  • 키프레임은 애니메이션에서 중요한 상태(기준 지점)을 정의한다.
  • 예를 들어, 공이 위로 튀었다가 내려오는 애니메이션을 만들때 :
  • 시작지점(0%) : 공이 바닥에 있음
  • 중간 지점(50%) : 공이 최대 높이로 올라감
  • 끝 지점(100%) : 공이 다시 바닥으로 돌아옴
  1. CSS에서 키프레임 정의
  • CSS에서는 @keyframes를 사용해 키프레임을 정의하고, 이를 animation 속성에서 사용한다.
@keyframes bounce {
	0% {
    	transform : translateY(0%);	
    }
    50% {
    	transform : translateY(-100%);
    }
    100% {
    	transform : translateY(0%);
    }
}

.ball {
	animation : bounce 1s infinite;
}

이렇게 사용하는데, styled-components에선
1. keyframes라는 함수를 사용해 키프레임 애니메이션을 정의한다.
2. 이 함수는 javascript객체 형태로 키프레임 정보를 반환하며, styled-components내부에서 애니메이션으로 사용할 수 있다.

예 :

import styled, {keyframes} from 'styled-components';

// 1. keyframes함수로 애니메이션 정의
const bounce = keyframes`
	0% {
		transform : translateY(0%);
	}
	50% {
		transform : translateY(-100%);
	}
	100% {
		transform : translateY(0%);
	}
`;

// 2. styled-components에 애니메이션 적용
const ball = styled.div`
	width : 50px;
	height : 50px;
	background-color : red;
	border-radius : 50%;
	animation : ${bounce} 1s infinite;
`;

// 3. React 컴포넌트에서 사용
function App() {
	return <Ball />
}

keyframs함수가 반환하는 값은 단순한 CSS문자열이 아닌, JS객체로 반환되며, CSS규칙과 관련된 여러 정보를 포함한다.

핵심 :
1. Styled-Components에서 반드시 keyframes함수를 사용

  • css의 @keyframes와 다르게 js객체로 반환되므로, styled-components안에서만 사용가능하다.
  • 다른 스타일링 라이브러리에선 사용할 수 없다.

2. Template Literal 형태로 삽입

  • ${}를 사용해 keyframes로 만든 애니메이션을 CSS속성에 연결해야 한다.

테마와 Provider

테마란?

  • 테마는 UI에서 사용하는 색상, 글자크기, 글자 색상 등 스타일 관련 설정을 하나의 객체로 모아둔 것이다.
  • 라이트 모드 / 다크 모드, 사용자 맞춤 색상 등 다양한 스타일 옵션을 구현할 때 사용한다.

styled-components에서는 ThemeProvider를 사용해 쉽게 테마를 설정하고 활용할 수 있다.

애니메이션

키프레임
1. 애니메이션의 기준점

  • 키프레임은 애니메이션에서 중요한 상태(기준 지점)를 정의한다.
  • 예를 들어, 공이 위로 튀었다가 내려오는 애니메이션을 만들때 :
    -- 시작 지점(0%) : 공이 바닥에 있음
    -- 중간 지점(50%) : 공이 최대 높이로 올라감
    -- 끝 지점 (100%) : 공이 다시 바닥으로 돌아옴
  1. CSS에서 키프레임 정의
  • CSS에서는 @keyframes를 사용해 키프레임을 정의하고, 이를 animation 속성에서 사용한다.

#css
@keyframs bounce {
0% {
transform : translateY(0%);
}
50% {
transform : translateY(-100%);
}
100% {
transform : translateY(0%);
}
}

.ball {
animation : bounce 1s infinite;
}

styled-Components에서 키프레임 사용하기
1. Styled-Components에서는 keyframes라는 함수를 사용해 키프레임 애니메이션을 정의한다.

  1. 이 함수는 javascript객체 형태로 키프레임 정보를 반환하며, styled-components내부에서 애니메이션으로 사용할 수 있다.

예:
import styled, {keyframes} from 'styled-components';

//1. keyframes함수로 애니메이션 정의
const bounce = keyframes 0% { transform : translateY(0%); } 50% { transform : translateY(-100%); } 100% { transform : translateY(0%); };

// 2. styled-components에 애니메이션 적용
const ball = styled.div width : 50px; height : 50px; background-color : red; border-radius : 50%; animation : ${bounce} 1s infinite;;

// 3. React 컴포넌트에서 사용
function App() {
return
}

Keyframes함수의 반환값
keyframes 함수가 반환하는 값은 단순한 CSS문자열이 아니다. JS객체로 반환되며, CSS규칙과 관련된 여러 정보를 포함한다.

핵심요약
1. Styled-Components에서 반드시 keyframes를 사용

  • css의 @keyframes와 다르게 js객체로 반환되므로, styled-components안에서만 사용가능하다.
  • 다른 스타일링 라이브러리에선 사용할 수 없다.
  1. Template Literal 형태로 삽입
  • ${}를 사용해 keyframes로 만든 애니메이션을 CSS속성에 연결해야 한다.

테마와 ThemeProvider
테마란?

  • 테마는 UI에서 사용하는 색상, 글자크기, 글자 색상 등 스타일 관련 설정을 하나의 객체로 모아둔것이다.
  • 라이트 모드/다크 모드, 사용자 맞춤 색상 등 다양한 스타일 옵션을 구현할 때 사용된다.

styled Components에서는 ThemeProvider를 사용해 쉽게 테마를 설정하고 활용할 수 있다.
애니메이션

키프레임
1. 애니메이션의 기준점

  • 키프레임은 애니메이션에서 중요한 상태(기준 지점)를 정의한다.
  • 예를 들어, 공이 위로 튀었다가 내려오는 애니메이션을 만들때 :
    -- 시작 지점(0%) : 공이 바닥에 있음
    -- 중간 지점(50%) : 공이 최대 높이로 올라감
    -- 끝 지점 (100%) : 공이 다시 바닥으로 돌아옴
  1. CSS에서 키프레임 정의
  • CSS에서는 @keyframes를 사용해 키프레임을 정의하고, 이를 animation 속성에서 사용한다.

#css
@keyframs bounce {
0% {
transform : translateY(0%);
}
50% {
transform : translateY(-100%);
}
100% {
transform : translateY(0%);
}
}

.ball {
animation : bounce 1s infinite;
}

styled-Components에서 키프레임 사용하기
1. Styled-Components에서는 keyframes라는 함수를 사용해 키프레임 애니메이션을 정의한다.

  1. 이 함수는 javascript객체 형태로 키프레임 정보를 반환하며, styled-components내부에서 애니메이션으로 사용할 수 있다.

예:
import styled, {keyframes} from 'styled-components';

//1. keyframes함수로 애니메이션 정의
const bounce = keyframes 0% { transform : translateY(0%); } 50% { transform : translateY(-100%); } 100% { transform : translateY(0%); };

// 2. styled-components에 애니메이션 적용
const ball = styled.div width : 50px; height : 50px; background-color : red; border-radius : 50%; animation : ${bounce} 1s infinite;;

// 3. React 컴포넌트에서 사용
function App() {
return
}

Keyframes함수의 반환값
keyframes 함수가 반환하는 값은 단순한 CSS문자열이 아니다. JS객체로 반환되며, CSS규칙과 관련된 여러 정보를 포함한다.

핵심요약
1. Styled-Components에서 반드시 keyframes를 사용

  • css의 @keyframes와 다르게 js객체로 반환되므로, styled-components안에서만 사용가능하다.
  • 다른 스타일링 라이브러리에선 사용할 수 없다.
  1. Template Literal 형태로 삽입
  • ${}를 사용해 keyframes로 만든 애니메이션을 CSS속성에 연결해야 한다.

테마와 ThemeProvider
테마란?

  • 테마는 UI에서 사용하는 색상, 글자크기, 글자 색상 등 스타일 관련 설정을 하나의 객체로 모아둔것이다.
  • 라이트 모드/다크 모드, 사용자 맞춤 색상 등 다양한 스타일 옵션을 구현할 때 사용된다.

styled Components에서는 ThemeProvider를 사용해 쉽게 테마를 설정하고 활용할 수 있다.
애니메이션

키프레임
1. 애니메이션의 기준점

  • 키프레임은 애니메이션에서 중요한 상태(기준 지점)를 정의한다.
  • 예를 들어, 공이 위로 튀었다가 내려오는 애니메이션을 만들때 :
    -- 시작 지점(0%) : 공이 바닥에 있음
    -- 중간 지점(50%) : 공이 최대 높이로 올라감
    -- 끝 지점 (100%) : 공이 다시 바닥으로 돌아옴
  1. CSS에서 키프레임 정의
  • CSS에서는 @keyframes를 사용해 키프레임을 정의하고, 이를 animation 속성에서 사용한다.

#css
@keyframs bounce {
0% {
transform : translateY(0%);
}
50% {
transform : translateY(-100%);
}
100% {
transform : translateY(0%);
}
}

.ball {
animation : bounce 1s infinite;
}

styled-Components에서 키프레임 사용하기
1. Styled-Components에서는 keyframes라는 함수를 사용해 키프레임 애니메이션을 정의한다.

  1. 이 함수는 javascript객체 형태로 키프레임 정보를 반환하며, styled-components내부에서 애니메이션으로 사용할 수 있다.

예:
import styled, {keyframes} from 'styled-components';

//1. keyframes함수로 애니메이션 정의
const bounce = keyframes 0% { transform : translateY(0%); } 50% { transform : translateY(-100%); } 100% { transform : translateY(0%); };

// 2. styled-components에 애니메이션 적용
const ball = styled.div width : 50px; height : 50px; background-color : red; border-radius : 50%; animation : ${bounce} 1s infinite;;

// 3. React 컴포넌트에서 사용
function App() {
return
}

Keyframes함수의 반환값
keyframes 함수가 반환하는 값은 단순한 CSS문자열이 아니다. JS객체로 반환되며, CSS규칙과 관련된 여러 정보를 포함한다.

핵심요약
1. Styled-Components에서 반드시 keyframes를 사용

  • css의 @keyframes와 다르게 js객체로 반환되므로, styled-components안에서만 사용가능하다.
  • 다른 스타일링 라이브러리에선 사용할 수 없다.
  1. Template Literal 형태로 삽입
  • ${}를 사용해 keyframes로 만든 애니메이션을 CSS속성에 연결해야 한다.

테마와 ThemeProvider
테마란?

  • 테마는 UI에서 사용하는 색상, 글자크기, 글자 색상 등 스타일 관련 설정을 하나의 객체로 모아둔것이다.
  • 라이트 모드/다크 모드, 사용자 맞춤 색상 등 다양한 스타일 옵션을 구현할 때 사용된다.

styled Components에서는 ThemeProvider를 사용해 쉽게 테마를 설정하고 활용할 수 있다.

1. 기본 테마 설정
ThemeProvider를 사용해 테마 값 설정하기

  • ThemeProvider는 React Context기반으로 동작하며, 테마 객체를 하위 컴포넌트로 전달한다.
  • 테마 객체는 Styled Components내부에서 theme프로퍼티로 접근할 수 있다.

예시 : 단일 테마 사용

import {ThemeProvider} from 'styled-components';
import Button from './Button';

function App() {
	const theme = {
    	primaryColor : '#1da1f2'; // 테마의 주요 색상 설정
    }
    
    return (
    	<ThemeProvider theme={theme}>
      		<Button>확인</Button>
      	</ThemeProvider>
    )
}

// Button컴포넌트
const Button = styled.button`
	background-color : ${({theme}) => theme.primaryColor};
	color : white;
	border : none;
	cursor : pointer;
`;
  • theme.primaryColor : ThemeProvider에서 내려준 값을 참조하여 버튼 배경색으로 설정한다.
  1. 테마 변경하기
    useState를 사용한 동적 테마변경
function App() {
	const [theme, setTheme] = useState({
    	primaryColor : '#1da1f2', // 초기 테마 색상
    });
  
  	const handleColorChange = (e) => {
    	setTheme({
        	...theme,
          	primaryColor : e.target.value, // 사용자가 선택한 색상으로 업데이트
        });
    }
    
    return (
    	<ThemeProvider theme={theme}>
      		<select value={theme.primaryColor} onChange={handleColorChange}>
              <option value="#1da1f2">blue</option>
			  <option value="#ffa800">yellow</option>
			  <option value="#f5005c">red</option>
			</select>
			<br />
            <br />
            <Button>확인</Button>
      	</ThemeProvider>
    )
}
  1. 일반 컴포넌트에서 테마 값 참조
  • styled component의 테마 값은 react의 useContext를 통해 일반 컴포넌트에서도 참조할 수 있다.
  • ThemeContext : styled Components에서 제공하는 context객체이다.
import {useContext} from 'react';
import {ThemeContext} from 'styled-components';

function SettingPage() {
	const theme = useContext(ThemeContext);
  
  	return (
    	<div>
      		<h2>현재 테마 색상</h2>
      		<p>Primary Color : {theme.primaryColor}</p>
      	</div>
    )
}
  • useContext(ThemeContext) : 현재 ThemeProvider에서 내려준 테마 객체를 반환한다.
  • 일반 컴포넌트에서도 테마 값을 자유롭게 사용할 수 있다.

정리
1. ThemeProvider :

  • 테마 객체를 하위 컴포넌트에 전달하는 React Context Provider
  1. theme프로퍼티
  • styled components내부에서 theme로 테마객체를 참조
  1. 동적 테마 변경
  • useState를 사용해 테마 객체를 업데이트 가능
  1. 일반 컴포넌트에서 사용
  • useContext(ThemeContext)로 테마 값 접근

styled-Components 팁

  1. 버튼 모양의 링크가 필요할 때
    문제 :
    어떤 버튼을 클릭하면 특정 기능을 수행(예 : Submit) 다른 버튼은 새로운 페이지로 이동 (예 : Create Account)하지만 버튼처럼 보이고 싶음
  • 이 경우 <button>과 <a>태그 모두 스타일이 동일해야 한다면

해결 : as Prop사용

  • styled-components의 as Prop을 사용하면 기존 스타일을 유지한 채 태그만 변경할 수 있다.

예제 :

import styled from 'styled-components';

const Button = styled.button`
	background-color : #123456;
	cursor : pointer;
`;

// button태그 대신 a태그로 사용하기
function App() {
	return (
    	<>
      		<Button>Submit</Button>
      		<Button as="a" href="path">Go to Link</Button>
      	</>
    )
}

결과 :
1. Submit 버튼은 기본 버튼 기능을 수행
2. Go to Link는 a태그처럼 동작하지만 모양은 버튼 모양이 됨

0개의 댓글