안녕하세요! delay100입니다. 이번 포스팅에서는 컴포넌트 스타일링 중에 가장 자주 쓰이는 4가지에 대해 공부해봅시다.
대부분의 설명은 주석으로 달아놓았으니 코드에 대한 설명은 주석을 확인해주세요!
책 리액트를 다루는 기술, 개정판의 9장 내용을 다루고 있습니다.
이번 포스팅의 Github 링크
https://github.com/delay-100/study-react/tree/main/ch9/styling-react
1. CSS
소규모 프로젝트를 개발할 때 새로운 스타일링 시스템을 적용하는 것이 불필요할 수 도 있습니다. 그 때는 프로젝트에 이미 적용되어 있는 기본 css 시스템을 사용하는 것만으로도 충분합니다.
css를 작성할 때 가장 중요한 점은 css 클래스를 중복되지 않게 만드는 것입니다.
중복 방지를 위해서는?
- 특별한 규칙을 두어 짓기
- CSS Selector 활용하기
1-1. 특별한 규칙
이름을 짓는 규칙에도 여러 종류가 있습니다. 여기서는 2가지만 소개합니다.
1. 컴포넌트 이름-클래스
클래스 이름에 컴포넌트 이름을 포함시킴으로써 다른 컴포넌트에서 실수로 중복되는 클래스를 만들어 사용하는 것을 방지할 수 있는 작성법
ex) App-header
- 컴포넌트 이름-클래스 예시 - src/App.css 中 아랫 부분
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
- 컴포넌트 이름-클래스 예시 - src/App.js
import logo from "./logo.svg";
import "./App.css";
function App() {
return (
<div className="App">
<header className="App-header">
<header>
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
2. BEM 네이밍
이름을 지을 때 일종의 규칙을 준수하여 해당 클래스가 어디에서 어떤 용도로 사용되는지 명확하게 작성하는 방식
ex) .card_title-primary
1-2. CSS Selector
CSS Selector을 사용하면 CSS 클래스가 특정 클래스 내부에 있는 경우에만 스타일을 적용할 수 있습니다.
컴포넌트의 최상위 html 요소에는 컴포넌트의 이름으로 클래스 이름을 짓고(.App), 그 내부에서는 소문자를 입력하거나(.logo), header 같은 태그를 사용하여 클래스 이름이 불필요한 경우에는 아예 생략도 가능합니다.
- CSS Selector 예시 - src/App.css 中 윗 부분
.App {
text-align: center;
}
/* App 안에 들어 있는 .logo */
.App .logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
/* App 안에 들어 있는 header
header 클래스가 아닌 header 태그 자체에
스타일을 적용하기 때문에 .이 생략되었습니다. */
.App header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
/* App 안에 들어 있는 link태그 */
.App link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
- CSS Selector 예시 - src/App.js
import logo from "./logo.svg";
import "./App.css";
function App() {
return (
<div className="App">
<header>
<img src={logo} className="logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
2. Sass
Sass란?
- Syntactically Awesome Style Sheets(문법적으로 매우 멋진 스타일시트)
- CSS 전처리기로 복잡한 작업을 쉽게 할 수 있도록 해줌
- 스타일 코드의 재활용성을 높여줌
- 코드의 가독성을 높여서 유지 보수를 더욱 쉽게 해줌
+ create-react-app 구버전에서는 Sass를 사용하려면 추가 작업이 필요했는데, v2 버전부터는 별도의 추가 설정 없이 바로 사용이 가능합니다.
Sass에서는 .scss확장자와 .sass 확장자를 지원합니다. (sass가 처음 나왔을 때는 .sass 확장자만 지원했지만 나중에 .scss 확장자도 지원하게 되었습니다.)
앞으로는 scss를 위주로 사용해보겠습니다.
scss 확장자는 중괄호({})와 세미콜론(;)을 사용합니다. 아래의 예시 코드를 보면 sass와 scss의 차이점을 볼 수 있습니다.
- sass 확장자 예시
$font-stack: Helvetica, sans-serif
$primary-color: #333
body
font: 100% $font-stack
color: $primary-color
- scss 확장자 예시
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}
2-1. Sass 사용하기
Sass를 사용하려면 Sass라는 라이브러리를 설치해줘야 합니다. 이 라이브러리는 Sass를 CSS로 변환해줍니다.
Sass 설치 명령어
yarn add sass
- sass 사용 예시 - src/SassComponent.scss
// 변수 사용하기
$red: #fa5252;
$orange: #fd7e14;
$yellow: #fcc419;
$green: #40c057;
$blue: #339af0;
$indigo: #5c7cfa;
$violet: #7950f2;
// 믹스인 만들기(재사용되는 스타일 블록을 함수처럼 사용할 수 있음)
@mixin square($size) {
$calculated: 32px * $size;
width: $calculated;
height: $calculated;
}
.SassComponent {
display: flex;
.box { // 일반 CSS 에서는 .SassComponent .box와 마찬가지
background: red;
cursor: pointer;
transition: all 0.3s ease-in;
&.red {
// .red 클래스가 .box와 함께 사용되었을 때
background: $red;
@include square(1);
}
&.orange {
background: $orange;
@include square(2);
}
&.yellow {
background: $yellow;
@include square(3);
}
&.green {
background: $green;
@include square(4);
}
&.blue {
background: $blue;
@include square(5);
}
&.indigo {
background: $indigo;
@include square(6);
}
&.violet {
background: $violet;
@include square(7);
}
&:hover {
// .box에 마우스를 올렸을 때
background: black;
}
}
}
- sass 사용 예시 - src/SassComponent.js
import "./SassComponent.scss";
const SassComponent = () => {
return (
<div className="SassComponent">
<div className="box red" />
<div className="box orange" />
<div className="box yellow" />
<div className="box green" />
<div className="box blue" />
<div className="box indigo" />
<div className="box violet" />
</div>
);
};
export default SassComponent;
- sass 사용 예시 - src/App.js
import { Component } from "react";
import SassComponent from "./SassComponent";
class App extends Component {
render() {
return (
<div>
<SassComponent />
</div>
);
}
}
export default App;
2-2. Scss 파일 분리하기
앞서 작성했던(2-1 sass 사용 예시) 예시의 Sass 변수 및 믹스인(@mixin)을 다른 파일로 따로 분리하여 작성한 뒤, 필요한 곳에 불러와 사용해봅시다.
scss 파일을 불러올 때는 @import 구문을 사용합니다.
- scss 파일 관리(분리) 예시 - src/styles/utils.scss
// 변수 사용하기
$red: #fa5252;
$orange: #fd7e14;
$yellow: #fcc419;
$green: #40c057;
$blue: #339af0;
$indigo: #5c7cfa;
$violet: #7950f2;
// 믹스인 만들기(재사용되는 스타일 블록을 함수처럼 사용할 수 있음)
@mixin square($size) {
$calculated: 32px * $size;
width: $calculated;
height: $calculated;
}
- scss 파일 관리(분리) 예시 - src/SassComponent.scss
@import './styles/utils'; // scss 파일 불러오기
.SassComponent {
display: flex;
.box { // 일반 CSS 에서는 .SassComponent .box와 마찬가지
background: red;
cursor: pointer;
transition: all 0.3s ease-in;
&.red {
// .red 클래스가 .box와 함께 사용되었을 때
background: $red;
@include square(1);
}
&.orange {
background: $orange;
@include square(2);
}
&.yellow {
background: $yellow;
@include square(3);
}
&.green {
background: $green;
@include square(4);
}
&.blue {
background: $blue;
@include square(5);
}
&.indigo {
background: $indigo;
@include square(6);
}
&.violet {
background: $violet;
@include square(7);
}
&:hover {
// .box에 마우스를 올렸을 때
background: black;
}
}
}
실행 결과는 2-1 sass 사용 예시 실행 결과와 동일합니다.
2-3. Sass 파일 자동으로 불러오기
위에서 반복적으로 쓰이는 scss 파일(utils.scss)을 모든 파일마다 @import 해주어야 했는데, 이를 자동으로 불러오게 설정할 수 있습니다.
이를 위해서는 yarn eject 명령어를 써서 create-react-app으로 만든 프로젝트의 세부 설정을 보면 됩니다.
이 때, yarn eject을 사용하기 위해서는 먼저 git에 지금까지 한 프로젝트를 commit 해야 합니다. Git에 커밋되지 않은 변화가 있다면 진행되지 않습니다.
yarm eject 실행 명령어
yarn eject
실행이 완료되었다면, config/webpack.config.js 파일을 열어봅시다.
위 코드들을 아래의 코드로 바꿉니다. 여기서 /styles는 자신의 sass 파일의 경로에 따라 바꿔주어야 합니다.
- sass 설정 변경1 - config/webpack.config.js
{
test: sassRegex,
exclude: sassModuleRegex,
use: getStyleLoaders({
importLoaders: 3,
sourceMap: isEnvProduction
? shouldUseSourceMap
: isEnvDevelopment,
modules: {
mode: "icss",
},
}).concat({
loader: require.resolve("sass-loader"),
options: {
sassOptions: {
includePaths: [paths.appSrc + "/styles"],
},
},
}),
여기까지 하셨으면, 자동으로 sass 파일이 불러와지지는 않지만 아래와 같이 @import 문의 경로를 간단하게 사용할 수 있습니다.
@import 'utils.scss';
이제 모든 scss 파일에서 sass 파일(utils.scss)을 자동으로 불러오는 설정을 추가해보겠습니다.
위에서 수정했던 부분에서, .concat 부분을 아래의 코드로 바꾸면 됩니다. additionalData 필드를 설정이 추가되었습니다.
- sass 설정 변경2 - config/webpack.config.js
.concat({
loader: require.resolve("sass-loader"),
options: {
sassOptions: {
includePaths: [paths.appSrc + "/styles"],
},
additionalData: "@import 'utils';",
},
}),
2-4. node_modules에서 라이브러리 불러오기
yarn을 통해 설치한 라이브러리는 기본적으로 아래의 코드를 통해 불러올 수 있습니다.
@import '../../../node_modules/library/styles';
이 때, node_modules 의 경로는 물결 문자(~)로 경로를 보다 쉽게 적을 수 있습니다.
@import '~library/styles';
우리의 scss파일에도 실제로 적용해봅시다.
유용한 node_modules의 sass 라이브러리
1. open-color: 편리한 색상 팔레트
2. include-media: 반응형 디자인을 쉽게 만들어 줌
설치
yarn add open-color include-media
위의 2가지의 라이브러리를 예시로 들어보겠습니다.
설치가 완료되면 node_modules 파일에서 방금 설치한 라이브러리의 이름을 찾아 scss 파일의 경로를 찾아줍니다.
그 후 scss 파일에서 import를 해주면 됩니다.
- node_modules에서 라이브러리 불러오기 예시 - src/styles/utils.scss
@import '~include-media/dist/include-media'; // Sass 라이브러리를 불러올 때는 node_modules 안의 scss 파일을 불러와야 합니다.
@import '~open-color/open-color';
// 변수 사용하기
$red: #fa5252;
$orange: #fd7e14;
$yellow: #fcc419;
$green: #40c057;
$blue: #339af0;
$indigo: #5c7cfa;
$violet: #7950f2;
// 믹스인 만들기(재사용되는 스타일 블록을 함수처럼 사용할 수 있음)
@mixin square($size) {
$calculated: 32px * $size;
width: $calculated;
height: $calculated;
}
- node_modules에서 라이브러리 불러오기 예시 - src/SassComponent.scss
.SassComponent {
display: flex;
background-color: $oc-gray-2; // SassComponent의 배경색을 open-colors 팔레트 라이브러리에서 불러온 후 설정
@include media('<768px') { // 화면 가로 크기가 768px 미만이 되면 배경색을 어둡게 바꿔줌
background: $oc-gray-9;
}
.box { // 일반 CSS 에서는 .SassComponent .box와 마찬가지
background: red;
cursor: pointer;
transition: all 0.3s ease-in;
&.red {
// .red 클래스가 .box와 함께 사용되었을 때
background: $red;
@include square(1);
}
&.orange {
background: $orange;
@include square(2);
}
&.yellow {
background: $yellow;
@include square(3);
}
&.green {
background: $green;
@include square(4);
}
&.blue {
background: $blue;
@include square(5);
}
&.indigo {
background: $indigo;
@include square(6);
}
&.violet {
background: $violet;
@include square(7);
}
&:hover {
// .box에 마우스를 올렸을 때
background: black;
}
}
}
3. CSS Module
CSS Module?
- CSS를 불러와서 사용할 때 클래스 이름을 고유한 값으로 자동으로 만들어서 컴포넌트 스타일 클래스 이름이 중첩되는 현상을 방지해 주는 기술
- 형태: [파일 이름]_[클래스 이름]_[해시 값]
- v2 버전 이상부터는 따로 설정할 필요 없이 .module.css 확장자로 파일을 저장하면 CSS Module이 적용됨
- 만든 클래스(class)는 스타일을 직접 불러온 컴포넌트 내부에서만 작동함
3-1. CSS Module 사용하기
- CSS Module 사용 예시 - src/CSSModule.module.css
/* 자동으로 고유해질 것이므로 흔히 사용되는 단어를 클래스 이름으로 마음대로 사용 가능 */
.wrapper {
background: black;
padding: 1rem;
color: white;
font-size: 2rem;
}
/* 글로벌 CSS를 작성하고 싶다면 - global: 특정 클래스가 웹 페이지에서 전역적으로 사용되는 경우 사용 */
:global .something {
font-weight: 800;
color: aqua;
}
- CSS Module 사용 예시 - src/CSSModule.js
import styles from "./CSSModule.module.css";
const CSSModule = () => {
console.log(styles);
/* 출력결과 - wrapper: "CSSModule_wrapper__MKjbW
CSS Module이 적용된 스타일 파일을 불러오면 객체를 하나 전달받게 되는데 CSS Module에서 사용한 클래스 이름과 해당 이름을 고유화한 키-값이 형태로 들어있음
파일이름: CSSModule, 클래스: wrapper, 해시값:MKjbW */
return (
<div className={styles.wrapper}>
안녕하세요, 저는 <span className="something">CSS Module!</span>
</div>
);
};
export default CSSModule;
- CSS Module 사용 예시 - src/App.js
import { Component } from "react";
import CSSModule from "./CSSModule";
class App extends Component {
render() {
return (
<div>
<CSSModule />
</div>
);
}
}
export default App;
- CSS Module 사용 예시2(클래스 여러개) - src/CSSModule.module.css
/* 자동으로 고유해질 것이므로 흔히 사용되는 단어를 클래스 이름으로 마음대로 사용 가능 */
.wrapper {
background: black;
padding: 1rem;
color: white;
font-size: 2rem;
}
.inverted {
color: black;
background: white;
border: 1px solid black;
}
/* 글로벌 CSS를 작성하고 싶다면 - global: 특정 클래스가 웹 페이지에서 전역적으로 사용되는 경우 사용 */
:global .something {
font-weight: 800;
color: aqua;
}
- CSS Module 사용 예시2(클래스 여러개) - src/CSSModule.js
import styles from "./CSSModule.module.css";
const CSSModule = () => {
console.log(styles); // 출력결과 - wrapper: "CSSModule_wrapper__MKjbW / {wrapper: 'CSSModule_wrapper__MKjbW', inverted: 'CSSModule_inverted__YwyLv'}
// CSS Module이 적용된 스타일 파일을 불러오면 객체를 전달받게 되는데 CSS Module에서 사용한 클래스 이름과 해당 이름을 고유화한 키-값이 형태로 들어있음
// 파일이름: CSSModule, 클래스: wrapper, 해시값:MKjbW
return (
<div className={`${styles.wrapper} ${styles.inverted}`}>
{/* className={[styles.wrapper, styles.inverted].join(' ')} 와 동일*/}
안녕하세요, 저는 <span className="something">CSS Module!</span>
</div>
);
};
export default CSSModule;
- CSS Module 사용 예시2(클래스 여러개) - src/App.js
import { Component } from "react";
import CSSModule from "./CSSModule";
class App extends Component {
render() {
return (
<div>
<CSSModule />
</div>
);
}
}
export default App;
3-2. classnames로 간편화
classnames란?
- css 클래스를 조건부로 설정할 때 매우 유용한 라이브러리
- CSS Module 사용 시 이 라이브러리를 사용하면 여러 클래스를 적용할 때 매우 편리함
classnames 설치 명령어
yarn add classnames
- classnames 간단 사용법
import classNames from 'classnames';
classNames('one', 'two'); // = 'one two'
classNames('one', { two: true }); // = 'one two'
classNames('one', { two: false}); // = 'one'
classNames('one', ['two', 'three']); // = 'one two three'
const myClass = 'hello';
classNames('one', myClass, { myCondition: true}); // = 'one hello myCondition'
CSS Module을 사용할 때 클래스를 여러 개 설정하거나, 또는 조건부로 클래스를 설정할 때 classnames의 bind를 사용하면 훨씬 편리하게 작성이 가능해집니다.
- classnames로 bind 사용 예시 - src/CSSModule.js
import classNames from "classnames/bind";
import styles from "./CSSModule.module.css";
const cx = classNames.bind(styles); // classnames에 내장되어 있는 bind 함수를 사용하면 클래스를 넣어 줄 때마다 styles.[클래스 이름] 형태를 사용할 필요가 없습니다.
// 사전에 미리 styles에서 받아 온 후 사용하게끔 설정해두고, cx('클래스 이름', '클래스 이름2') 형태로 사용할 수 있습니다.
const CSSModule = () => {
return (
<div className={cx("wrapper", "inverted")}>
안녕하세요, 저는 <span className="something">CSS Module!</span>
</div>
);
};
export default CSSModule;
나머지 코드는 아래와 동일하며 실행결과도 3-1. CSS Module 사용 예시2(클래스 여러개) 와 같습니다.
- CSS Module 사용 예시2(클래스 여러개) - src/CSSModule.module.css
- CSS Module 사용 예시2(클래스 여러개) - src/App.js
- classnames로 bind 사용 예시 & Sass(scss)와 함께 사용하기- src/CSSModule.module.scss
/* 자동으로 고유해질 것이므로 흔히 사용되는 단어를 클래스 이름으로 마음대로 사용 가능 */
.wrapper {
background: black;
padding: 1rem;
color: white;
font-size: 2rem;
&.inverted {
// inverted가 .wrapper와 함께 사용되었을 때만 적용
color: black;
background: white;
border: 1px solid black;
}
}
/* 글로벌 CSS를 작성하고 싶다면 - global: 특정 클래스가 웹 페이지에서 전역적으로 사용되는 경우 사용 */
:global {
.something {
font-weight: 800;
color: aqua;
}
}
- classnames로 bind 사용 예시 & Sass(scss)와 함께 사용하기 - src/CSSModule.js
import classNames from "classnames/bind";
import styles from "./CSSModule.module.scss";
const cx = classNames.bind(styles); // classnames에 내장되어 있는 bind 함수를 사용하면 클래스를 넣어 줄 때마다 styles.[클래스 이름] 형태를 사용할 필요가 없습니다.
// 사전에 미리 styles에서 받아 온 후 사용하게끔 설정해두고, cx('클래스 이름', '클래스 이름2') 형태로 사용할 수 있습니다.
const CSSModule = () => {
return (
<div className={cx("wrapper", "inverted")}>
안녕하세요, 저는 <span className="something">CSS Module!</span>
</div>
);
};
export default CSSModule;
나머지 코드는 아래와 동일하며 실행결과도 3-1. CSS Module 사용 예시2(클래스 여러개) 와 같습니다.
- CSS Module 사용 예시2(클래스 여러개) - src/App.js
3-3. css파일에서 CSS Module 사용하기
/* CSS Module이 아닌 일반 .css, .scss 파일에서도 :local을 사용하여 CSS Module을 사용할 수 있음 */
:local .wrapper {
}
4. styled-components
컴포넌트 스타일링의 방식 중 하나로 자바스크립트 파일 안에 스타일을 선언하는 방식이 있습니다.(CSS-IN-JS)
CSS-IN-JS 라이브러리는 많은 종류가 있는데, 그 중에 개발자의 선호도가 가장 높은 styled-components에 대해 알아보겠습니다. 그 외 emotion 등이 있습니다.
styled-components를 사용하면 자바스크립트 파일 하나에 스타일까지 작성이 가능합니다. 따라서 .css 또는 scss 확장자를 가진 스타일 파일을 따로 만들지 않아도 되는 장점이 있습니다.
styled-components와 일반 classNames를 사용하는 CSS/Sass를 비교했을 때, styled-components의 가장 큰 장점은 props 값으로 전달해주는 값을 쉽게 스타일에 적용할 수 있다는 점입니다.
styled-components 설치 명령어
yarn add styled-components
+vscode 스타일 확장 프로그램
4-1. Tagged 템플릿 리터럴
4. styled-components 사용 예시 코드를 보면 스타일 작성 시 `(백틱)을 사용해 만든 문자열에 스타일 정보를 넣어주었습니다. 이러한 문법을 Tagged 템플릿 리터럴이라 부릅니다.
그래서 이게 뭐냐? 이해하자면,,
앞선 3-1. CSS Module 사용하기에서 아래와 같은 결과가 있었습니다.
반면, Tagged 템플릿 리터럴은 아래와 같습니다.
function tagged(...args) {
console.log(args);
}
tagged`hello ${{ foo: "bar" }} ${() => "world"}!`;
즉, 템플릿 안에 자바스크립트 객체나 함수를 전달할 때 온전히 추출할 수 있다는 장점이 있습니다.
styled-components는 이러한 속성을 사용해 styled-components로 만든 컴포넌트의 props를 스타일 쪽에서 쉽게 조회할 수 있도록 해줍니다.
4-2. 예시
- styled-components 사용 예시 - src/StyledComponent.js
import styled, { css } from "styled-components";
// 단순 변수의 형태가 아니라 여러 줄의 스타일 구문을 조건부로 설정해야 하는 경우에는 css를 불러와야 합니다
// 반응형 디자인 함수화 하기 => styled-components 매뉴얼에서 제공하는 유틸 함수를 따라 사용
const sizes = {
desktop: 1024,
tablet: 768,
};
// 위에 있는 size 객체에 따라 자동으로 media 쿼리 함수를 만들어 줍니다.
// 참고: https://www.styled-components.com/docs/advanced#media-templates
const media = Object.keys(sizes).reduce((acc, label) => {
acc[label] = (...args) => css`
@media (max-width: ${sizes[label] / 16}em) {
${css(...args)};
}
`;
return acc;
}, {});
const Box = styled.div`
/* props로 넣어 준 값을 직접 전달해 줄 수 있습니다. */
background: ${(props) => props.color || "blue"};
padding: 1rem;
display: flex;
${media.desktop`width:768px`}
${media.tablet`width: 100%`};
/* 반응형 디자인 */
/* 기본적으로는 가로 크기 1024px에 가운데 정렬을 하고
가로 크기가 작아짐에 따라 크기를 줄이고
768px 미만이 되면 꽉 채웁니다 */
/* width: 1024px;
margin: 0 auto;
@media (max-width: 1024px) {
width: 768px;
}
@media (max-width: 768px) {
width: 100%;
} */
`;
const Button = styled.button`
// 스타일 작성 시 백틱을 사용해 만든 문자열에 스타일 정보를 넣어줌 => Tagged 템플릿 리터럴 문법임
// styled.태그명 으로 구현함. styled.button 뒤에 Tagged 템플릿 리터럴 문법을 통해 스타일을 넣으면, 해당 스타일이 적용된 button으로 이루어진 리액트 컴포넌트가 생성됨.
// 나중에 <Button>Hello</Button>으로 사용 가능
background: white;
color: black;
border-radius: 4px;
padding: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
font-size: 1rem;
font-weight: 600;
/* & 문자를 사용하여 Sass처럼 자기 자신 선택 가능*/
&:hover {
background: rgba(255, 255, 255, 0.9);
}
/* 다음 코드는 inverted 값이 true일 때 특정 스타일을 부여해 줍니다. */
${(props) =>
props.inverted &&
css`
/* 스타일 코드 여러 줄을 props에 따라 넣어 주어야 할 때는 CSS를 styled-components에서 불러와야 합니다
여기서 css+백틱이 아닌 그냥 백틱으로 바로 문자열을 넣어도 동작하기는 합니다.
css를 지우게 되면, VS Code 확장 프로그램에서 syntax 하이라이팅이 제대로 이루어지지 않는다는 단점이 있습니다.
더욱 치명적인 단점은 Tagged 템플릿 리터럴이 아니기 때문에 함수를 받아 사용하지 못해 해당 부분에서는 props 값을 사용하지 못합니다.
만약 조건부 스타일링을 할때 props를 참조하지 않는다면 굳이 CSS를 불러올 필요는 없습니다. */
background: none;
border: 2px solid white;
color: white;
&:hover {
background: white;
color: black;
}
`};
& + button {
margin-left: 1rem;
}
`;
// 사용해야 할 태그명이 유동적이거나 특정 컴포넌트 자체에 스타일링 해주고 싶은 경우
// // 태그의 타입을 styled 함수의 인자로 전달
// const MyInput = styled("input")`
// background: gray;
// `;
// // 특정 컴포넌트에 스타일링을 해주고 싶은 경우에는(컴포넌트를 styled의 파라미터에 넣는 경우)
// // 해당 컴포넌트에 className props를 최상위 DOM의 className 값으로 설정하는 작업이 내부적으로 되어있어야 함
// const Sample = ({ className }) => {
// return <div className={className}>Sample</div>;
// };
// // 아예 컴포넌트 형식의 값을 넣어 줌
// const StyledLink = styled(Link)`
// color: blue;
// `;
const StyledComponent = () => (
<Box color="black">
<Button>안녕하세요</Button>
<Button inverted={true}>테두리만</Button>
</Box>
);
export default StyledComponent;
- styled-components 사용 예시 - src/App.js
import { Component } from "react";
import StyledComponent from "./StyledComponent";
class App extends Component {
render() {
return (
<div>
<StyledComponent />
</div>
);
}
}
export default App;
읽어주셔서 감사합니다. 잘못된 정보는 댓글로 알려주세요!
'Study > React' 카테고리의 다른 글
11. 컴포넌트 성능 최적화 (0) | 2022.07.20 |
---|---|
10. 간단한 투두리스트(TodoList) 만들기 (0) | 2022.07.19 |
8. Hooks (0) | 2022.07.16 |
7. Lifecycle method(라이프사이클 메서드) (0) | 2022.07.14 |
6. map (0) | 2022.07.13 |