리액트에서 컴포넌트를 스타일링 하는 가장 기본적인 방법:
css 파일을 만들어서 컴포넌트에서 import 해서 사용하는 것
- Sass
- CSS Module
- styled-components
1. Sass
- 시작
- node-sass 라이브러리 설치(Sass->CSS변환)
cd styling-with-sass $ yarn add node-sass
Button 컴포넌트 만들기
- & : 부모 선택자 참조
$blue: #228be6; // 주석 선언
background: $blue; // 주석 사용
&:hover { //:hover 상태(사용자가 요소 위에 마우스를 올렸을 때)
background: lighten($blue, 10%); // 색상 10% 밝게 }
&:active { //:active상태 (사용자가 요소를 클릭할 때)
background: darken($blue, 10%); // 색상 10% 어둡게 }
- background: darken($blue, 10%); --> CSS에는 없는 문법 ( darken(), lighten() )
- 이 코드의 의미는 $blue 색상을 기준으로 10% 더 어둡게(darken) 만든 색상을 background 속성에 적용하라는 것입니다. 즉, 요소가 클릭되었을 때 배경 색상이 어두워짐
버튼 사이즈 설정
- className 에 CSS 클래스 이름을 동적으로 넣어주고 싶으면 이렇게 설정을 해주어야 함
- className={`Button ${size}`} 또는 className={['Button', size].join(' ')}
- 조건부로 CSS 클래스를 넣어주고 싶을때 이렇게 문자열을 직접 조합해주는 것 보다 classnames 라는 라이브러리를 사용하는 것이 훨씬 편함
$ yarn add classnames // 설치
- 조건부 스타일링 이란???
- 특정 조건에 따라 스타일을 다르게 적용하는 것을 의미
- 다양한 상황에서 UI 요소의 스타일을 동적으로 변경해야 할 때 유용
- classNames 를 사용하면 조건부 스타일링을 할 때 함수의 인자에 문자열, 배열, 객체 등을 전달하여 손쉽게 문자열을 조합 할 수 있음
-
function Button({ children, size }) { return <button className={classNames('Button', size)}>{children}</button>; } //props 로 받은 props 값이 button 태그의 className 으로 전달
-
.Button { &.large { //&는 부모 선택자인 .Button을 가리킴 } } // 사이즈 설정 = .Button.large 와 같은 거임!!!
- >' .Button 클래스를 가진 요소에 large 클래스가 함께 적용되었을 때만 특정 스타일을 적용하겠다 ' 라는 뜻!!
-
.Button & + & { margin-left: 1rem; } //.Button + .Button 를 의미, 만약 함께 있다면 우측에 있는 버튼에 여백 설정
버튼 색상 관리 ( 반복되는 코드 : mixin 기능 사용해서 단순화! )
&.pink {
background: $pink;
&:hover {
background: lighten($pink, 10%);
}
&:active {
background: darken($pink, 10%);
}
이런 코드가 props 값만 바뀌고 다 반복되는 상황이면
아래 코드처럼 변환 가
@mixin button-color($color) {
background: $color;
&:hover {
background: lighten($color, 10%);
}
&:active {
background: darken($color, 10%);
}
&.pink {
@include button-color($pink);
}
outline 옵션
요소의 경계 외부에 그려지는 선을 정의하는 속성
시각적 요소이며 처음 정의할 때(구현방식)은 아래와 같이 정의,
outline 값을 props 로 받아와서 객체 안에 집어 넣은 다음에 classNames() 에 포함시킴
-> outline 값이 true 일 때에만 button 에 outline CSS 클래스가 적용
//설정
function Button({ children, size, color, outline }) {
return (
<button className={classNames('Button', size, color, { outline })}>
{children}
</button>
);
}
//불러올 때
<div className="buttons">
<Button size="large" color="blue" outline>
BUTTON
</Button>
<Button color="gray" outline>
BUTTON
</Button>
<Button size="small" color="pink" outline>
BUTTON
</Button>
</div>
fulllWidth 옵션
요소가 부모 컨테이너의 전체 너비를 차지하도록 설정하는 데 사용
outline옵션과 설정하는 방법은 같다.
&.fullWidth {
width: 100%; // .fullWidth 클래스가 적용된 요소의 너비를 100%로 설정하여, 부모 요소의 전체 너비를 차지하도록 합니다.
justify-content: center; // flexbox 컨테이너에서 요소의 자식들을 가로축(수평)에서 중앙에 배치하도록 설정합니다.
& + & {
margin-left: 0; // .fullWidth 클래스가 연속적으로 배치된 경우, 다음 요소의 왼쪽 여백을 0으로 설정합니다.
margin-top: 1rem; // 연속적인 .fullWidth 요소들 사이에 1rem의 위쪽 여백(간격)을 추가합니다.
}
}
다른 컴포넌트 또는 HTML 태그에 전달하는 상황
spread 와 rest 이용
JavaScript에서 주로 함수의 인자, 배열, 객체에서 사용되며, 여러 개의 값을 하나의 배열이나 객체로 모아주는 역할을 하며,이를 통해 코드의 가독성과 유연성을 높일 수 있다.
spread:객체 혹은 배열을 펼칠 수 있음. (복사 개념으로,,)
...[객체/배열이름]
rest는 ...뒤에 변수이름 아님!!(( ...value와 ...rest가 있음))
const purpleCuteSlime = {
name: '슬라임',
attribute: 'cute',
color: 'purple'
};
const { color, ...rest } = purpleCuteSlime;
console.log(color); // purple
console.log(rest); // {name: '슬라임', attribute:'cute'}}
function Button({ children, size, color, outline, fullWidth, ...rest }) {
return (
<button
className={classNames('Button', size, color, { outline, fullWidth })}
{...rest}
>
{children}
</button>
);
}
...rest를 사용해서 우리가 지정한 props 를 제외한 값들을 rest 라는 객체에 모아주고, <button> 태그에 {...rest} 를 해주면, rest 안에 있는 객체안에 있는 값들을 모두 <button> 태그에 설정
rest에 어느 props가 올지모르지만 앞에 지정한 props외 모두가 올 수 있음 ( 앞에 지정한 props의 여집합)
함수 파라미터에서의 rest
함수의 파라미터가 몇개가 될 지 모르는 상황에서 rest 파라미터를 사용하면 매우 유용
2. CSS Module
이 기술의 장점
CSS 클래스가 중첩되는 것을 완벽히 방지 가능, 명확한 의존관계가 잘 보임!
리액트 컴포넌트 파일에서 해당 CSS 파일을 불러올 때 CSS 파일에 선언한 클래스 이름들이 모두 고유해짐
실수로 CSS 클래스 이름이 다른 관계 없는 곳에서 사용한 CSS 클래스 이름과 중복되는 일에 대하여 걱정 할 필요가 없음
ex)
function Component() {
return (
<div className={styles.container}>
<h1 className={styles.title}>Hello, CSS Modules!</h1>
</div>
);
}
3. styled-components
import React from 'react';
import styled from 'styled-components';
const Circle = styled.div`
width: 5rem;
height: 5rem;
background: black;
border-radius: 50%;
`;
function App() {
return <Circle />;
}
export default App;
Template Literal( 템플릿 리터럴(`))
const object = { a: 1 };
const text = `${object}`; // 이 코드에서 object.toString()이 자동으로 호출됨
console.log(text); // "[object Object]" 출력
const red = '빨간색';
const blue = '파란색';
function favoriteColors(texts, ...values) {
console.log(texts);
console.log(values);
}
favoriteColors`제가 좋아하는 색은 ${red}과 ${blue}입니다.`
- texts 배열: 템플릿 리터럴의 정적인 문자열 부분들이 배열로 들어간다.
- values 배열: 템플릿 리터럴에서 ${} 안에 삽입된 값들이 배열로 들어간다.
console.log(texts); // ["내가 좋아하는 색은 ", "와 ", "입니다."]
console.log(values); // ["빨간색", "파란색"]
'WINK-(Web & App) > React.js 스터디' 카테고리의 다른 글
[2024 여름방학 React.js 스터디] 백채린 #6주차 (0) | 2024.08.16 |
---|---|
[2024 여름방학 React.js 스터디] 정채은 #5주차 (0) | 2024.08.09 |
[2024 여름방학 React.js 스터디] 김태일 #5주차 "리액트 컴포넌트 스타일링" (0) | 2024.08.09 |
[2024 여름방학 React.js 스터디] 김민서 #5주차 (0) | 2024.08.09 |
[2024 여름방학 React.js 스터디] 이종윤 #5주차 (1) | 2024.08.08 |