๐ Sass
Sass (Syntactically Awesome Style Sheets)
- CSS pre-processor ๋ก์, ๋ณต์กํ ์์ ์ ์ฝ๊ฒ ํ ์ ์๊ฒ ํจ
- ์ฝ๋์ ์ฌํ์ฉ์ฑ์ ๋์
- ์ฝ๋์ ๊ฐ๋ ์ฑ์ ๋์ฌ์ฃผ์ด ์ ์ง๋ณด์๋ฅผ ์ฝ๊ฒํจ
- ๋๊ฐ์ง์ ํ์ฅ์ ์ง์(.scss/ .sass)
๐ 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;
}
์ฐจ์ด์
- ๋ฌธ๋ฒ
- { }; ์ ์ ๋ฌด scss์์๋ {};๋ฅผ ์ฌ์ฉํจ
- ํ์ฅ์
- ๋ณดํต scss๊ฐ ๋ ๋ง์ด ์ฌ์ฉ๋จ
- ํ์ฅ์
css๋์ ์กฐ๊ธ ๋ค๋ฅธ ๋ฌธ๋ฒ
- $blue: #228be6
- lighten() darken() ๊ฐ์๊ฑด ์์๋๋ฐ ์กฐ๊ธ ๋ค๋ฅด๋ค์
๐ ๋ฒํผ ์ฌ์ด์ฆ ์กฐ์ ํ๊ธฐ
- className์ CSS ํด๋์ค ์ด๋ฆ์ ๋์ ์ผ๋ก ๋ฃ์ด์ฃผ๊ณ ์ถ์๋ (className={['Button', size].join(' ')} ๋๋
- className={'Button ${size}'}
ํ์ง๋ง ์ด๋ ๊ฒ ๋ณด๋ค classNames ๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋๊ฒ? ๋ ํธํ๋ค!
classNames - ์กฐ๊ฑด๋ถ ์คํ์ผ๋ง์ ํ ๋ ํจ์์ ์ธ์์ ๋ฌธ์์ด, ๋ฐฐ์ด, ๊ฐ์ฒด ๋ฑ์ ์ ๋ฌํ์ฌ ์์ฝ๊ฒ ๋ฌธ์์ด์ ์กฐํฉ ํ ์ ์์
classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'
classNames(['foo', 'bar']); // => 'foo bar'
// ๋์์ ์ฌ๋ฌ๊ฐ์ ํ์
์ผ๋ก ๋ฐ์์ฌ ์ ๋ ์์ต๋๋ค.
classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); // => 'foo bar baz quux'
// false, null, 0, undefined ๋ ๋ฌด์๋ฉ๋๋ค.
classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'
scss ์ดํด๋ณด๊ธฐ
.Button {
&.large {
}
} //์ด๊ฑฐ๋
.Button.large {
} //์ด๊ฑฐ๋ ๊ฐ๋ค~
๊ฒฐ๊ตญ, Button ๊ณผ large CSS ํด๋์ค๊ฐ ํจ๊ป ์ ์ฉ๋์ด ์์ผ๋ฉด ์ฐ๋ฆฌ๊ฐ ์ํ๋ ์คํ์ผ์ ์ ์ฉํ๊ฒ ๋ค๋ ๊ฒ์ ์๋ฏธ.
๋์ ์ฒ์๋ด ๋๋ค ์ด๋ฐ๊ฑด ใ ใ
& + & = .Button + .Button์ด๋ผ๊ณ ํ๋ค์... ๊ทธ๋์ ์ฌ๋ฐฑ์ ์ค๊ฑฐ๋ ๊ฐ์์ ์ ๋ ๊ฒ ๋ฐ๋๋ค์
๐ ๋ฒํผ ์์ ์ค์ ํ๊ธฐ
๐ outline ์ต์ ๋ง๋ค๊ธฐ
๐ ์ ์ฒด ๋๋น ์ฐจ์งํ๋ ์ต์
๊ทผ๋ฐ ์ด๊ฒ ์์ ๋ฐ๋ผํ๋ค๊ฐ ๋ฐ๊ฒฌํ๊ฑด๋ฐ defaultProps๋ก color: blue๋ฅผ ํด๋จ๋จ ๋ง์ด์ฃ
๊ทผ๋ฐ default๊ฐ ํ๋์์ด ์๋๋ผ ์ ๋ ๊ฒ ์ฐํ ํ์์ผ๋ก ๋จ๋๋ผ๊ณ ์
์.. ์์ธ์ ์ฐพ์๋ณด๋๊น
โdefaultProps x ํจ์์์ ๋ฐ๋ก ์ ์
์ด๊ฑฐ ์ ์ ํ๋ ์คํฐ๋์์๋ ํ๋๊ฑด๋ฐ ์ฌ๊ธฐ์๋ ์ด๊ฑฐ ๋๋ฌธ!!
๐ ...rest props ์ ๋ฌํ๊ธฐ
์ด์ ๋ฒํผ ์ปดํฌ๋ํธ์ onClick์ ์ค์ ํ๋ ค๋ฉด??
spread์ rest์ฌ์ฉํ๊ธฐ
- props์ ์ง์ ํ์ง ์์ ๊ฐ๋ค์ rest๋ผ๋ ๊ฐ์ฒด์ ๋ชจ์์ค
- buttonํ๊ทธ์ {...rest}๋ฅผ ํด์ฃผ๋ฉด rest ๊ฐ์ฒด์์ ์๋ ๊ฐ๋ค์ ๋ชจ๋ buttonํ๊ทธ์ ์ค์ ํด์ค
๐ CSS Module
- CSS ํด๋์ค๊ฐ ์ค์ฒฉ๋๋ ๊ฒ์ ์๋ฒฝํ ๋ฐฉ์งํ ์ ์๋ ๊ธฐ์
- CRA๋ก ๋ง๋ ํ๋ก์ ํธ์์ CSS Module๋ฅผ ์ฌ์ฉ ํ ๋์๋ CSS ํ์ผ์ ํ์ฅ์๋ฅผ .module.css๋ก ์ค์
- ๋ฆฌ์กํธ ์ปดํฌ๋ํธ ํ์ผ์์ ํด๋น CSS ํ์ผ์ ๋ถ๋ฌ์ฌ ๋ CSS ํ์ผ์ ์ ์ธํ ํด๋์ค ์ด๋ฆ๋ค์ด ๋ชจ๋ ๊ณ ์ ํด์ง
- className ์ ์ค์ ํ ๋์๋ styles.Box ์ด๋ ๊ฒ import๋ก ๋ถ๋ฌ์จ styles ๊ฐ์ฒด ์์ ์๋ ๊ฐ์ ์ฐธ์กฐํด์ผ ํจ
.Box {
background: black;
color: white;
padding: 2rem;
}
//js
import React from "react";
import styles from "./Box.module.css";
function Box() {
return <div className={styles.Box}>{styles.Box}</div>;
}
export default Box;
์ผ๋ฐ CSS์ ์ฐจ์ด์
์ผ๋ฐ CSS
/* styles.css */
.button {
background-color: blue;
color: white;
}
// App.jsx
import './styles.css';
function App() {
return <button className="button">Click me</button>;
}
- ๋ค๋ฅธ ํ์ผ์์๋ ๊ฐ์ ์ด๋ฆ์ ํด๋์ค๊ฐ ์์ผ๋ฉด ์คํ์ผ ์ถฉ๋์ด ๋ฐ์
CSS Module
/* Button.module.css */
.button {
background-color: blue;
color: white;
}
// App.jsx
import styles from './Button.module.css';
function App() {
return <button className={styles.button}>Click me</button>;
}
์ด๋ ๊ฒ ํ๋ฉด ๊ณ ์ ์ ํด์๊ฐ์ ํฌํจํ ์ด๋ฆ์ผ๋ก ๋ฐ๋๋๋ค !! => ์ค๋ณต ์์ผ์ด๋จ
์ด์ ์์ ๋ก ๊ณต๋ถ๋ฅผ ํด๋ณผ๊ฑด๋ฐ ~
์ด๋ ๊ฒ ๋๋๋ฐ ์ฒดํฌ๋ฐ์ค๋ "์ฒดํฌ๋จ/์๋จ" ํ ์คํธ๋ฅผ ๋๋ฅด๋ฉด check์ํ๊ฐ ๋ณํจ => ํด๋น ๊ณต๊ฐ์ labelํ๊ทธ๋ก ๊ฐ์ธ์
์ด์จ๋ ์ด ์์ ๋ก ๊ณต๋ถ๋ฅผ ํด๋ณด์!!!
styles.icon ์ด๋ ๊ฒ ๊ฐ์ฒด์์ ์๋ ๊ฐ์ ์กฐํํด์ผํ๋๋ฐ ์ด๋ฆ์ -๊ฐ ๋ค์ด๊ฐ ์๋ค๋ฉด? :
- styles['my-class'] ์ด๋ ๊ฒ ์ฌ์ฉ!
- ์ฌ๋ฌ๊ฐ๊ฐ ์๋ค๋ฉด? ${styles.one} ${styles.two}
- ์กฐ๊ฑด๋ถ ์คํ์ผ๋ง : ${styles.one} ${condition ? styles.two : ''}
- ์ฌ๋ฌ๊ฐ์ CSS ํด๋์ค๋ฅผ ์ฌ์ฉํด์ผ ํ ๋
- ์กฐ๊ฑด๋ถ ์คํ์ผ๋ง์ ํด์ผ ํ ๋
cx('one', 'two')
cx('my-component', {
condition: true
})
cx('my-component', ['another', 'classnames'])
๐ ๊ธฐํ ์ถ๊ฐ ๋ด์ฉ
- CSS Module์ Sass์์๋ ์ฌ์ฉ ๊ฐ๋ฅ
- ํ์ฅ์๋ฅผ .module.scss๋ก
- CSS Module์ ์ฌ์ฉํ๊ณ ์๋ ํ์ผ์์ ํด๋์ค ์ด๋ฆ ๊ณ ์ ํ x ์ ์ญ์ ํด๋์ค ์ด๋ฆ์ ์ฌ์ฉํ๊ณ ์ถ์๋
:global .my-global-name {
}
//Sass
:global {
.my-global-name {
}
}
- CSS Module ์ ์ฌ์ฉํ์ง ์๋ ๊ณณ์์ ํน์ ํด๋์ค์์๋ง ๊ณ ์ ์ด๋ฆ์ ๋ง๋ค์ด์ ์ฌ์ฉํ๊ณ ์ถ์๋
:local .make-this-local {
}
//Sass
:local {
.make-this-local {
}
}
๐ styled- components : CSS in JS
Tagged Template Literal
- Template Literal
- `์ผ๋ก ๊ฐ์ธ์ผ ํจ
- ${} ์์ ๋ณ์, ์ฐ์ฐ์, ํจ์ ํธ์ถ ๋ฑ ๋ค์ํ ํํ์ ๋ฃ์ ์ ์์
const name = "์๋";
const age = 22;
// ๊ธฐ์กด ๋ฐฉ์
console.log("์๋
ํ์ธ์, ์ ์ด๋ฆ์ " + name + "์ด๊ณ , ๋์ด๋ " + age + "์ด์
๋๋ค.");
// Template Literal
console.log(`์๋
ํ์ธ์, ์ ์ด๋ฆ์ ${name}์ด๊ณ , ๋์ด๋ ${age}์ด์
๋๋ค.`);
- Tagged Template Literal
- Template Literal ์์ ํจ์ ์ด๋ฆ์ ๋ถ์
- ๊ทธ ํจ์๊ฐ ๋ฌธ์์ด๊ณผ ํํ์์ ๋ถ๋ฆฌํด์ ์ง์ ์ฒ๋ฆฌ ๊ฐ๋ฅ
- tagFunction`๋ฌธ์์ด ${ํํ์1} ๋ ๋ค๋ฅธ ๋ฌธ์์ด ${ํํ์2}`
function emphasize(strings, ...values) {
// strings: ๋ฌธ์์ด ๋ฐฐ์ด
// values: ${}๋ก ๋ค์ด์จ ๊ฐ๋ค
return strings.reduce((result, str, i) => {
return result + str + (values[i] ? `**${values[i]}**` : "");
}, "");
}
const name = "์๋";
const age = 22;
const result = emphasize`์๋
ํ์ธ์, ${name}! ๋น์ ์ ${age}์ด์
๋๋ค.`;
console.log(result);
// ์ถ๋ ฅ: ์๋
ํ์ธ์, **์๋**! ๋น์ ์ **22**์ด์
๋๋ค.
++ ์ด๋ฐ ๋ฌธ๋ฒ์ ์ฌ์ฉํ๊ธฐ๋ ํจ
const StyledDiv = styled`
background: ${props => props.color};
`;
์ด์ ์์ ๋ฅผ ๋ณด๋ฉด์ ํด๋ณด๊ฒ ์ต๋๋ค
์ ์์งํ ์ฒ์ ๋ณด๋๊ฑฐ๋ผ ์ข ์ด๋ ค์์;;
๊ทผ๋ฐ ์ด๋ ๊ฒ ์ฌ๋ฌ ์ค์ CSS ์ฝ๋๋ฅผ ์กฐ๊ฑด๋ถ๋ก ๋ณด์ฌ์ฃผ๊ณ ์ถ๋ค๋ฉด css๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๋๋ฐ...
๊ทธ๋์ผ ๊ทธ ์คํ์ผ ๋ด๋ถ์์๋ ๋ค๋ฅธ props๋ฅผ ์กฐํ ํ ์ ์๋ค๋๋ฐ... ํํ ์ด๋ ต๋ค
๐ Button ๋ง๋ค๊ธฐ
์ฌ๊ธฐ ๋ถํด styled-components ๋จ์ข ์ด์๋ก Emotion์ผ๋ก ํ ๊ฒ์ ๋ฌธ๋ฒ์ ๊ฐ์ผ๋๊น..
๐ polished์ ์คํ์ผ ๊ด๋ จ ์ ํธ ํจ์ ์ฌ์ฉํ๊ธฐ
Sass๋ฅผ ์ฌ์ฉ ํ ๋ lighten() ์ด๋ darken() ๊ฐ์ ํจ์๋ฅผ ์ฌ์ฉํ๋๋ฐ CSS in JS์์๋ polished๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋จ
:hover๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ง์ฐ์ค ์ปค์๋ฅผ ๊ฐ์ ธ๊ฐ๋ฉด ํ๋ฉด์ด ํ๋ ค์ง๊ณ ํด๋ฆญํ๋ฉด ์ด๋์์ง๊ฒ ๋จ
ThemeProvider : emotion/styled-components ๋ก ๋ง๋๋ ์ปดํฌ๋ํธ์์ ์กฐํ/์ฌ์ฉ ๊ฐ๋ฅํ๊ฒ ์ค์
- color๋ฅผ ์ง์ ํ์ง๋ง๊ณ ๋ฐ์์ ์ฌ์ฉํ๋๋ก
- defaultprops๊ฐ ์ ์๋์ ์์ ๋ ์กฐ๊ธ ๋ค๋ฅด๊ฒ ??์ฐ์ฐ์๋ฅผ ์ฌ์ฉ => ๊ธฐ๋ณธ๊ฐ ์ง์ ๋จ
- +๊ทผ๋ฐ ์ฌ๊ธฐ์ ๊ทธ & + & ๊ฐ ์๋จน๋๋ฐ ์์ธ์ง๋ ๋ชจ๋ฅด๊ฒ ๋ค์ :not๊ฑฐ๋ ์ธ๋ผ์ธ ์คํ์ผ๋ก ํด๊ฒฐ์ ๊ฐ๋ฅํฉ๋๋ค
const colorStyles = css`
${({ theme, color }) => {
const selected = theme.palette[color];
return css`
background: ${selected};
&:hover {
background: ${lighten(0.1, selected)};
}
&:active {
background: ${darken(0.1, selected)};
}
`;
}}
`;
์๋๋ ์ด๋ ๊ฒ ์์๊ด๋ จ ์ฝ๋๋ฅผ ๋ถ๋ฆฌํด์ ์ฌ์ฉ ํ ์
const colorStyles = css`
${({ theme, color }) => {
const selected = theme.palette[color];
return css`
background: ${selected};
&:hover {
background: ${lighten(0.1, selected)};
}
&:active {
background: ${darken(0.1, selected)};
}
`;
}}
`;
์๋ ์์ ๋ ์ด๊ฑฐ์๋๋ฐ ์ด๊ฒ ๊ณ์ ์๋ฌ๊ฐ ๋์
const colorStyles = ({ theme, color }) => {
const selected = theme?.palette?.[color] ?? "#228be6";
return css`
background: ${selected};
&:hover {
background: ${lighten(0.1, selected)};
}
&:active {
background: ${darken(0.1, selected)};
}
`;
};
์ด๋ ๊ฒ ํ์ด์ gpt๋ง๋ก๋
css\`` ์์ ํจ์๋ฅผ ๋ฃ๊ณ , ๋ ๊ทธ ํจ์ ์์์ props`๋ฅผ ์ฐ๊ณ ์์ด์ ๋ฌธ๋ฒ์ด ๊ผฌ์ฌ ์์๋ ๊ฑฐ์์.
`css`` ์์์๋ ๋ฐ๋ก ์คํ์ผ ๋ฌธ์์ด์ ์จ์ผ์ง, JS ํจ์ ์์ฒด๋ฅผ ๋ฃ์ผ๋ฉด ์ ๋ฉ๋๋ค.
๋ผ๋ค์ ํ ์ ๋ฐฐ์ ์ต๋๋ค;
โ์ ๊ทผ๋ฐ size๊ฐ ์๋์ ์ํด์;;;;;
๊ทธ๋์ ์๋ ํจ์๋ก ๋ฐ๊ฟ์คฌ๋๋ฐ => ์ด๋ฒ์ ๊ฐ๊ฒฉ์ด ์๋ ์ํจ
๋ํ์ฅ ํํฐ ใ ใ ๊ทธ๋๋ ํ๊ฑฐ์ ์๋ฏธ๋ฅผ ๋๊ฒ ์ต๋๋ค + ๋ค์ outline์ด๋ fullWidth๋ ํ๋ ๋ฐฉ๋ฒ์ด ๊ฐ์ผ๋ ๋์ด๊ฐ๊ฒ์ ใ
๐ Dialog ๋ง๋ค๊ธฐ
๐ ํธ๋์ง์ ๊ตฌํํ๊ธฐ
ํ๋ฉด dialog๊ฐ ๋ฐ๋/๋ด๋ ค๊ฐ๋ ๋ค ํธ๋ ์ง์ ์ด ์๊ธฐ๊ฒ ๋ฉ๋๋ค..
์ด๋ ๊ฒ ๋์ธ๋ฐ์ ๋ญ๊ฐ ์๋ก์ด๊ฑด๋ฐ ๋ด์ฉ์ด ์ข ๋ง์์ ๋ค์ ์ฒ์ฒํ ๋ด๋ณผ๊ฒ์
'WINK-(Web & App) > React.js ์คํฐ๋' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[2025 1ํ๊ธฐ React.js ์คํฐ๋] ์ด์์ค #5์ฃผ์ฐจ (0) | 2025.05.22 |
---|---|
[2025 1ํ๊ธฐ React.js ์คํฐ๋] ์ด์ข ๋ฏผ #4์ฃผ์ฐจ (0) | 2025.05.08 |
[2025 1ํ๊ธฐ React.js ์คํฐ๋] ์ ์ฑ์ #4์ฃผ์ฐจ (0) | 2025.05.08 |
[2025 1ํ๊ธฐ React.js ์คํฐ๋] ๊ฐ๋ฏผ์ง #4์ฃผ์ฐจ (0) | 2025.05.08 |
[2025 1ํ๊ธฐ React.js ์คํฐ๋] ์ต์ํฌ #4์ฃผ์ฐจ (0) | 2025.05.08 |