heyday2024 님의 블로그
[React 숙련 1주차(1)] Styled-Components 본문
지금까지 사용해봤던 css 스타일링을 적용 방법:
1. inline styling: 태그에 style 속성을 사용하여 직접 스타일 지정하는 방법.
JSX 문법을 사용하므로 {{ key: 'value' }} 형식을 사용해야 함. ({객체 형식} 필수!!!)
2. 순수 html처럼 className을 정해놓고 css 파일에 해당 요소 스타일 정의하기.
==> 하지만 위 두 방식은 조금 비효율적일 수도 있음!!!
Inline 스타일링의 단점:
- 가독성 저하: 스타일이 컴포넌트와 뒤섞여 코드가 복잡해지고, 특히 스타일 코드가 길어지면 구조가 흐려짐.
- 재사용성 부족: 같은 스타일을 다른 요소에 재사용하려면 중복 코드 발생.
- Pseudo-classes 및 Media Queries 제한: :hover, :active 같은 CSS pseudo-classes나 반응형 디자인을 위한 media queries를 적용하기 어려움.
CSS 파일을 별도로 만드는 방식의 단점:
- 반복적인 파일 생성 및 import: 컴포넌트마다 새로운 CSS 파일을 만들어야 하고, 이를 각각 import해야 하는 번거로움.
- 스타일 스코프 관리 어려움: 글로벌 CSS로 인해 다른 컴포넌트와의 스타일 충돌 가능성 증가.
- 동적 스타일링 제한: CSS 파일로는 JavaScript 변수나 props를 통한 동적 스타일링이 어려워, 상태에 따른 스타일 변경이 복잡해짐.
=====> 위 두 방식의 단점을 커버할 새로운 스타일링 방식: CSS in JS
CSS-in-JS방식이란, 단어 그대로 자바스크립트 코드로 CSS 코드를 작성하여 컴포넌트를 꾸미는 방식!
순수한 CSS코드를 자바스크립트를 이용해서 만들어내는 것!
이 방식은 다양한 조건문, 변수등을 이용해서 스타일링을 할 수 있게함!!!
즉, 이전 방식으로는 할 수 없었던 로직을 이용한 효율적인 스타일링을 할 수 있게함.
CSS-in-JS 장점을 다시 정리하자면,
CSS-in-JS 방식의 주요 장점:
- 스타일과 로직의 결합: 스타일과 컴포넌트 로직이 한 파일에 있어 유지보수성이 높고, 재사용이 용이함.
- 동적 스타일링: props와 상태에 따라 조건부로 스타일을 변경하거나 JavaScript 변수를 사용하여 동적 스타일링 가능.
- 자동 스코핑: CSS 클래스명이 자동으로 고유화되어 스타일 충돌이 방지됨.
- 코드 분할과 최적화: 사용하지 않는 스타일은 번들에 포함되지 않으므로 불필요한 코드가 줄어듦.
Styled-Components
CSS-in-JS 방식의 라이브러리 중 하나로, 리액트에서 컴포넌트를 꾸밀 수 있게 도와주는 패키지.
- 템플릿 리터럴 문법을 사용하여 CSS를 정의하고, JavaScript 변수를 스타일에 쉽게 삽입 가능.
(package: React에는 없는 기능이지만 우리가 추가로 가져와서 사용할 수 있는 third-party 프로그램 )
( 패키지들은 누군가에 의해 만들어진 것으로 npm에 모여 있음. 우리는 사용하고자 하는 패키지를 npm install 또는 yarn add를 통해서 설치하고 사용할 수 있음)
vsCode에서 사용하기 위해 아래 플러그인 설치하고,
yarn add styled-components
이 명령로, styled-components 패키지 설치함.
<Styled-Component(SC) 사용법>
꾸미고자 하는 컴포넌트를 SC의 방식대로 먼저 만들고, 그 안에 스타일 코드를 작성하는 방식으로 진행
// src/App.js
import React from "react";
// styled-components에서 styled 라는 키워드를 import 합니다.
import styled from "styled-components";
// styled키워드를 사용해서 styled-components 방식대로 컴포넌트를 만듭니다.
const StBox = styled.div`
// 그리고 이 안에 스타일 코드를 작성합니다. 스타일 코드는 우리가 알고 있는 css와 동일합니다.
width: 100px;
height: 100px;
border: 1px solid red;
margin: 20px;
`;
const App = () => {
// 그리고 우리가 만든 styled-components를 JSX에서 html 태그를 사용하듯이 사용합니다.
return <StBox>박스</StBox>;
};
export default App;
- 백틱(`) 사용해서 스타일 코드 작성해주면됨.
- styled. 뒤에는 html 태그가 옴.
<조건부 스타일링>
classname을 사용해서 구현하기는 조금 까다로운 조건부 스타일링을 styled-components를 이용하면 간편하게 할 수 있음. CSS-in-JS 방식 이용해서 바로 스타일 코드를 JS코드 작성하듯이 작성가능.
// src/App.js
import React from "react";
import styled from "styled-components";
// 1. styled-components를 만들었습니다.
const StBox = styled.div`
width: 100px;
height: 100px;
border: 1px solid ${(props) => props.borderColor}; // 4.부모 컴포넌트에서 보낸 props를 받아 사용합니다.
margin: 20px;
`;
const App = () => {
return (
<div>
{/* 2. 그리고 위에서 만든 styled-components를 사용했습니다. */}
{/* 3. 그리고 props를 통해 borderColor라는 값을 전달했습니다. */}
<StBox borderColor="red">빨간 박스</StBox>
<StBox borderColor="green">초록 박스</StBox>
<StBox borderColor="blue">파랑 박스</StBox>
</div>
);
};
export default App;
props는 부모 컴포넌트에서 자식 컴포넌트로 어떤 정보를 전달하고자 할 때 사용!
styled-components도 말 그대로 컴포넌트 이기 때문에 우리는 box들에게 props를 통해서 border color에 대한 정보를 전달해줄 수 있음!
위에 반복되는 부분을 map과 switch 문으로 refactoring하기
// src/App.js
import React from "react";
import styled from "styled-components";
const StContainer = styled.div`
display: flex;
`;
const StBox = styled.div`
width: 100px;
height: 100px;
border: 1px solid ${(props) => props.borderColor};
margin: 20px;
`;
// 박스의 색을 배열에 담습니다.
const boxList = ["red", "green", "blue"];
// 색을 넣으면, 이름을 반환해주는 함수를 만듭니다.
const getBoxName = (color) => {
switch (color) {
case "red":
return "빨간 박스";
case "green":
return "초록 박스";
case "blue":
return "파란 박스";
default:
return "검정 박스";
}
};
const App = () => {
return (
<StContainer>
{/* map을 이용해서 StBox를 반복하여 화면에 그립니다. */}
{boxList.map((box) => (
<StBox borderColor={box}>{getBoxName(box)}</StBox>
))}
</StContainer>
);
};
export default App;
Global Styles(전역 스타일링)
styled components는 컴포넌트 내에서만 활용할 수 있었지만, 가끔 요소들을 스타일링할 때, 겹치고 반복되는 스타일링이 있음.
공통적으로 들어가야할 이러한 스타일들을 적용하기 위해 전역적으로(globally) 스타일을 정의할 필요가 있음.
이때 전역 스타일링(Global Styles)을 이용함!!!
import styled from "styled-components";
function TestPage(props) {
return (
<Wrapper>
<Title>{props.title}</Title>
<Contents>{props.contents}</Contents>
</Wrapper>
);
}
const Title = styled.h1`
font-family: "Helvetica", "Arial", sans-serif;
line-height: 1.5;
font-size: 1.5rem;
margin: 0;
margin-bottom: 8px;
`;
const Contents = styled.p`
margin: 0;
font-family: "Helvetica", "Arial", sans-serif;
line-height: 1.5;
font-size: 1rem;
`;
const Wrapper = styled.div`
border: 1px solid black;
border-radius: 8px;
padding: 20px;
margin: 16px auto;
max-width: 400px;
`;
export default TestPage;
- 이 코드를 보면 font-family: "Helvetica", "Arial", sans-serif; line-height: 1.5 이 부분이 공통적인 스타일링 요소라고 볼 수 있음.
===> 해당 부분을 GlobalStyles.jsx 파일 이름으로 따로 빼주고,
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
body {
font-family: "Helvetica", "Arial", sans-serif;
line-height: 1.5;
}
`;
export default GlobalStyle;
이 전역 스타일링을 아래 처럼 import로 가져와서 적용시켜주면 됨.
import GlobalStyle from "./GlobalStyle";
import BlogPost from "./BlogPost";
function App() {
const title = '전역 스타일링 제목입니다.';
const contents = '전역 스타일링 내용입니다.';
return (
<>
<GlobalStyle />
<BlogPost title={title} contents={contents} />
</>
);
}
export default App;
크로스 브라우징이란?
웹사이트나 웹 애플리케이션이 다양한 브라우저(예: Chrome, Firefox, Safari, Edge 등)와 다양한 운영체제 환경(Windows, macOS, Linux, 모바일 OS 등)에서 일관된 사용자 경험을 제공하도록 만드는 작업을 뜻함.
브라우저마다 CSS와 JavaScript 기능을 해석하고 렌더링하는 방식이 약간씩 다르기 때문에, 특정 기능이나 스타일이 한 브라우저에서는 잘 작동하지만 다른 브라우저에서는 오류가 발생하거나 예상과 다르게 보일 수 있음.
대표적인 크로스 브라우징 이슈로는 각 브라우저마다 기본 스타일(default style)을 제공하는데, 이것은 내가 보여주고 싶은 스타일을 렌더링할때 브라우저마다 다 다르게 보일 수 있음으로, css reset이 필요함!!!!
,<초기화하는 방법>
1. 직접 이렇게 css 파일 링크하기
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./reset.css" />
</head>
<body>
<span>Default Style을 테스트 해 봅니다.</span>
<h1>이건 h1 태그에요</h1>
<p>이건 p 태그에요</p>
</body>
</html>
2. reset css cdn 검색해서 제공하는 코드 사용하기
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset-css@5.0.2/reset.min.css">
'프론트엔드 부트캠프' 카테고리의 다른 글
[React 숙련 1주차(3)] Memoization - (React.memo, useCallback, useMemo), Custom Hooks (0) | 2024.11.05 |
---|---|
[React 숙련 1주차(2)] 리액트 훅: useState, useEffect, useRef, useContext (4) | 2024.11.05 |
[React] 올림픽 메달 추적: 개인 프로젝트 정리(2) (0) | 2024.11.01 |
[React 개인과제] 올림픽 메달 트래커 만들어보기 (1) | 2024.10.31 |
[React 2주차 (4)] 컴포넌트 & 렌더링, DOM vs Virtual DOM (1) | 2024.10.30 |