์•Œ๊ธฐ ์‰ฌ์šด BEM ์•Œ์•„๋ณด๊ธฐ(CSS)

block__element_modifier๋ชจ๋“ˆ ๊ธฐ๋ฐ˜์˜ ๋ฐฉ๋ฒ•๋ก  (+mix)

๊ณต์‹ ๋ฌธ์„œ(https://en.bem.info)์—์„œ๋Š” BEM์„ ์ด๋ ‡๊ฒŒ ์„ค๋ช…ํ•œ๋‹ค.

BEM(Block, Element, Modifier)๋Š” ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜ ์ ‘๊ทผ ๋ฐฉ์‹์ด๋‹ค. ๊ธฐ๋ณธ ์•„์ด๋””์–ด๋Š” ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค(UI)๋ฅผ ๋…๋ฆฝ๋œ ๋ธ”๋ก์œผ๋กœ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ณต์žกํ•œ UI๋„ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

BEM์€ ๋ชจ๋“ˆ์„ Block, Element, Modifier ๋‹จ์œ„๋กœ ๋ถ„ํ•ดํ•˜๋ฉฐ, ๊ฐ ์•ž ๊ธ€์ž๋ฅผ ๋”ฐ์„œ BEM์œผ๋กœ ๋ถ€๋ฅธ๋‹ค. BEM์€ ๋Ÿฌ์‹œ์•„ Yandex์‚ฌ์—์„œ ๊ฐœ๋ฐœํ•œ ๋ฐฉ๋ฒ•๋ก ์œผ๋กœ ์‹ค์ œ๋กœ ์ด ๋ฐฉ๋ฒ•์— ๊ธฐ๋ฐ˜ํ•œ CSS ์„ค๊ณ„ ๊ธฐ๋ฒ•์ด ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์ง€๋งŒ BEM์€ CSS์—๋งŒ ๊ตญํ•œ๋˜์ง€๋Š” ์•Š๋Š”๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด BEM์˜ ๊ณตํ†ต ๊ทœ์น™๊ณผ ๋ชจ๋“ˆ์˜ ๊ฐœ๋ณ„ ๊ทœ์น™์„ ์•Œ์•„๋ณด์ž.

CSS style์„ ์œ„ํ•œ BEM ๊ณตํ†ต ๊ทœ์น™

– ID ์…€๋ ‰ํ„ฐ์™€ ํƒœ๊ทธ ์…€๋ ‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
– ๋„ค์ŠคํŒ…๋œ ์…€๋ ‰ํ„ฐ ์‚ฌ์šฉ์„ ์ตœ์†Œํ™”ํ•œ๋‹ค.
– CSS ํด๋ž˜์Šค ๋„ค์ด๋ฐ ์ปจ๋ฒค์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฆ„ ์ถฉ๋Œ์„ ํ”ผํ•˜๊ณ  ์…€๋ ‰ํ„ฐ์˜ ๋ชฉ์ ์„ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•œ๋‹ค.
– Blocks, Elements, Modifiers๋ฅผ ๊ตฌ๋ถ„ํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.
– Blocks๋ฅผ ์žฌ์‚ฌ์šฉํ•œ๋‹ค.

BEM์˜ ๋„ค์ด๋ฐ ๊ทœ์น™

๋ชจ๋‘ ์†Œ๋ฌธ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ๋‘ ๋‹จ์–ด๋Š” ํ•˜์ดํ”ˆ(-)์œผ๋กœ ์—ฐ๊ฒฐํ•œ๋‹ค.

Blockblock, block-two
Elementblock ์ด๋ฆ„์„ ์ƒ์†๋ฐ›์•„ ์–ธ๋”์Šค์ฝ”์–ด ๋‘ ๊ฐœ(__)๋กœ ์—ฐ๊ฒฐblock__element, block-two__element-two
ModifierBlock/Element ์ด๋ฆ„ ์ƒ์†๋ฐ›์•„ ์–ธ๋”์Šค์ฝ”์–ด ํ•˜๋‚˜(_)๋กœ ์—ฐ๊ฒฐ. ํ‚ค-๊ฐ’ ์Œ์€ ์Šค๋„ค์ดํฌ ์ผ€์ด์Šค(_)๋ฅผ ์‚ฌ์šฉ.
block_modifier, block__element_modifier, element_key_value
Modifier
(MindBEMding)
Block/Element ์ด๋ฆ„ ์ƒ์†๋ฐ›์•„ ํ•˜์ดํ”ˆ ๋‘๊ฐœ(–)๋กœ ์—ฐ๊ฒฐ. ํ‚ค-๊ฐ’์—์„œ ํ‚ค๋Š” ์ƒ๋žต๊ฐ€๋Šฅ.block–modifier, element–value

๋ชจ๋“ˆ์˜ ๊ฐœ๋ณ„ ๊ทœ์น™

๋…ผ๋ฆฌ์ , ๊ธฐ๋Šฅ์ ์œผ๋กœ ๋…๋ฆฝ๋˜์–ด ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•œ ๋ชจ๋“ˆ๋กœ ์ •์˜ํ•œ๋‹ค. ํด๋ž˜์Šค ์ด๋ฆ„์€ ‘ํ˜•ํƒœ’๊ฐ€ ์•„๋‹ˆ๋ผ ‘๋ชฉ์ , ์šฉ๋„’๋ฅผ ๋‚˜ํƒ€๋‚ด์•ผ ํ•œ๋‹ค.

EX) head, logo, menu (O)
blue-button, small-title (X)

block์€ ๋‹ค๋ฅธ block ๋‚ด๋ถ€์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, modifier๋ฅผ ํ†ตํ•ด ์œ„์น˜๋‚˜ ๋ชจ์–‘์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ฆผ – block์˜ ์ค‘์ฒฉ(์ถœ์ฒ˜: en.bem.info)

Element

block์„ ๊ตฌ์„ฑํ•˜๋ฉฐ block ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“ˆ๋กœ ์ •์˜ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด menu__item์€ menu๋ผ๋Š” block์„ ๊ตฌ์„ฑํ•˜๋ฉฐ menu ๋ฐ–์—์„œ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ element๊ฐ€ ๋œ๋‹ค.

๊ทธ๋ฆผ – block์„ ๊ตฌ์„ฑํ•˜๋Š” element(์ถœ์ฒ˜:en.bem.info)


element ํด๋ž˜์Šค ์ด๋ฆ„๋„ block๊ณผ ๋™์ผํ•˜๊ฒŒ ‘ํ˜•ํƒœ’๊ฐ€ ์•„๋‹ˆ๋ผ ‘์šฉ๋„’๋ฅผ ๋‚˜ํƒ€๋‚ด์•ผ ํ•œ๋‹ค.
element๋Š” ์„ ํƒ์  ์š”์†Œ์ด๋ฏ€๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ์ƒ๊ด€์—†์ง€๋งŒ element ์ด๋ฆ„์„ ์ค‘์ฒฉํ•˜์—ฌ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

EX) block__element__element, menu__button__icon (X)

Modifier

block/element์˜ ๋ชจ์–‘์ด๋‚˜ ๋™์ž‘์„ ์ •์˜ํ•˜๋Š” ๋ชจ๋“ˆ์ด๋‹ค.
modifier๋Š” ์„ ํƒ์  ์š”์†Œ์ด๋ฏ€๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ์ƒ๊ด€์—†์ง€๋งŒ ๋‹จ๋…์œผ๋กœ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ณ  block/element์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
๊ฐ™์€ block์ด๋ผ๋„ modifier์— ๋”ฐ๋ผ ๋ชจ์–‘์ด ๋ณ€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, modifier๋Š” ๋Ÿฐํƒ€์ž„์ด๋‚˜ block์— ๋”ฐ๋ผ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋‹ค.
modifier ํด๋ž˜์Šค ์ด๋ฆ„์€ ํ˜•ํƒœ(ํฌ๊ธฐ, ์ƒ‰, ์ƒํƒœ, ๋™์ž‘)์„ ๋‚˜ํƒ€๋‚ด์•ผ ํ•œ๋‹ค. ํ˜•ํƒœ๋กœ ๋‚˜๋ˆ„๋ฉด boolean, key-value ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ์œผ๋ฉฐ, ๊ฐ๊ฐ์˜ ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

– boolean : ex) active, disabled
– key-value : ex) color_red, line_doubled (์Šค๋„ค์ดํฌ ์ผ€์ด์Šค๋กœ ํ‘œํ˜„)

modifier์˜ ์ˆ˜๋Š” ์ œํ•œ์ด ์—†์œผ๋ฏ€๋กœ ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ๋ถ™์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๋™์ผํ•œ ์Šคํƒ€์ผ์€ ์ค‘๋ณตํ•˜์ง€ ์•Š๋Š”๋‹ค.

MIX

mix๋Š” ํ•˜๋‚˜์˜ ์š”์†Œ์— ์—ญํ• ์ด ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ฒ•์ด๋‹ค.
์žฅ์ ์€ ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌํ•˜์ง€ ์•Š๊ณ  ๊ธฐ์กด์˜ ์Šคํƒ€์ผ๊ณผ ์กฐํ•ฉํ•ด์„œ ์ƒˆ๋กœ์šด ๋ชจ๋“ˆ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
block+element, block+block, element+element ๋“ฑ์˜ mix๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ƒ˜ํ”Œ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

<!-- HTML -->
<div class="header">
  <div class="logo header__logo"></div>
</div>

/* CSS */
.logo {
  width:100px;
  height:50px;
}
.header__logo {
  margin: 12px;
}

๋‹ค๋ฅธ ์š”์†Œ์™€ ๊ด€๊ณ„๋œ ๋ ˆ์ด์•„์›ƒ๊ณผ ๊ด€๋ จ๋œ ๋ถ€๋ถ„์€ mix, block ๋‚ด๋ถ€์˜ ๋ฌธ์ œ๋Š” modifier๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
mix๋Š” ๋…๋ฆฝ์„ฑ๊ณผ ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’์€ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.


์ฐธ๊ณ 
https://en.bem.info
– ๋‹ค์–‘ํ•œ ์˜ˆ์ œ๋กœ ๋ฐฐ์šฐ๋Š” CSS ์„ค๊ณ„ ์‹ค์ „ ๊ฐ€์ด๋“œ


CSS ์„ค๊ณ„๋ฅผ ์œ„ํ•œ ๊ธฐ๋ณธ ๊ฐ€์ด๋“œ

๋ณ€๊ฒฝ๊ณผ ํ™•์žฅ์— ๊ฐ•ํ•˜๊ณ  ์•ˆ์ •์ ์ธ CSS ๊ตฌ์กฐ๋ฅผ ์œ„ํ•œ ๊ธฐ๋ฒ•

๋‹ค์–‘ํ•œ ์˜ˆ์ œ๋กœ ๋ฐฐ์šฐ๋Š” CSS ์„ค๊ณ„ ์‹ค์ „๊ฐ€์ด๋“œ์—์„œ ์†Œ๊ฐœํ•˜๋Š” ์„ค๊ณ„์˜ ํ•ต์‹ฌ์„ ์•Œ์•„๋ณด์ž.

CSS์˜ ์—ฌ๋Ÿฌ ์„ค๊ณ„ ๊ธฐ๋ฒ•๋“ค๋„ ๊ฒฐ๊ตญ์—๋Š” ๋‹ค์Œ ์—ฌ๋Ÿ ๊ฐ€์ง€ ๋ฆฌ์ŠคํŠธ์— ์†ํ•œ๋‹ค๊ณ  ํ•˜๋‹ˆ ํ•ต์‹ฌ์„ ๊ด€ํ†ตํ•˜๋Š” ํฌ์ธํŠธ๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

1. ํŠน์„ฑ์— ๋”ฐ๋ฅธ CSS ๋ถ„๋ฅ˜
2. ๋А์Šจํ•œ ์Šคํƒ€์ผ์˜ ๊ฒฐํ•ฉ
3. ์ ๋‹นํ•œ ์˜ํ–ฅ ๋ฒ”์œ„
4. ํŠน์ • ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•œ ์ ์ ˆํ•œ ์˜์กด๋„
5. ์ ์ ˆํ•œ ๋ช…์‹œ๋„(specificity)
6. ์˜ํ–ฅ ๋ฒ”์œ„๊ฐ€ ์œ ์ถ” ๊ฐ€๋Šฅํ•œ ํด๋ž˜์Šค ๋„ค์ž„
7. ํ˜•ํƒœ, ๊ธฐ๋Šฅ, ์—ญํ• ์˜ ์œ ์ถ”๊ฐ€ ๊ฐ€๋Šฅํ•œ ํด๋ž˜์Šค ๋„ค์ž„
8. ํ™•์žฅ ์šฉ์ด์„ฑ

1. ํŠน์„ฑ์— ๋”ฐ๋ฅธ CSS ๋ถ„๋ฅ˜

์ฒซ ๋ฒˆ์งธ๋Š” CSS ์—ญํ• ์ด๋‚˜ ํŠน์„ฑ์— ๋”ฐ๋ผ ๋ถ„๋ฅ˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๋ฒ ์ด์Šค ๊ทธ๋ฃน : ์‚ฌ์ดํŠธ์—์„œ ๋ฒ ์ด์Šค๊ฐ€ ๋˜๊ฑฐ๋‚˜ ๊ณตํ†ต์œผ๋กœ ์ ์šฉ๋˜๋Š” ์‚ฌํ•ญ ๋“ฑ
๋ ˆ์ด์•„์›ƒ ๊ทธ๋ฃน : ํ—ค๋”(header), ํ‘ธํ„ฐ(footer), ์ฝ˜ํ…์ธ (content) ์˜์—ญ ๋“ฑ
๋ชจ๋“ˆ ๊ทธ๋ฃน : ์žฌ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋“ˆ ๋“ฑ

๋ชจ๋“ˆ ์ž์ฒด์—๋Š” ๋ ˆ์ด์•„์›ƒ๊ณผ ๊ด€๋ จ๋œ ๋ถ€๋ถ„์€ ์„ค์ •ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๋ชจ๋“ˆ์€ ์ž์‹ ์˜ ๋ ˆ์ด์•„์›ƒ์—๋Š” ๊ด€์—ฌํ•˜์ง€ ์•Š๊ณ  ํ•ด๋‹น ๋ชจ๋“ˆ ์ž์ฒด์˜ ์—ญํ•  ๋ฐ ์ž๋…€ ์š”์†Œ์˜ ์Šคํƒ€์ผ๋ง์—๋งŒ ๊ด€์‹ฌ์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ ๋ ˆ์ด์•„์›ƒ๊ณผ ๊ด€๋ จ๋œ ๋ถ€๋ถ„์ด๋ž€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

-position, z-index, top/right/bottom/left, float, width, margin

/* ๋ฒ ์ด์Šค */
body {
  font-family: 'Noto Sans';
}

/* ๋ ˆ์ด์•„์›ƒ */
layout_content {
  width: 1000px;
  padding: 10px;
  margin: 0 auto;
}

/* ๋ชจ๋“ˆ */
.bl_media {
  display: flex;
  justify-items: center;
  align-items: center;
}

.bl_media_title {
  margin: 5px;
  font-weight: bold;
}

2. ๋А์Šจํ•œ ์Šคํƒ€์ผ์˜ ๊ฒฐํ•ฉ

์ •ํ™•ํžˆ๋Š” HTML๊ณผ ์Šคํƒ€์ผ๋ง์˜ ๋А์Šจํ•œ ๊ฒฐํ•ฉ์ด๋‹ค. ๋А์Šจํ•œ ๊ฒฐํ•ฉ์ด๋ž€ ์˜์กดํ•˜์ง€ ์•Š๋Š” ์ƒํƒœ๋ฅผ ์ด์•ผ๊ธฐํ•˜๋Š”๋ฐ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ์š”์†Œํ˜• ์…€๋ ‰ํ„ฐ๋ฅผ ํ”ผํ•˜๊ณ  ํด๋ž˜์Šค ์…€๋ ‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

p{}, div{}, h1{}๊ณผ ๊ฐ™์ด ์š”์†Œ์˜ ์Šคํƒ€์ผ์„ ์ง์ ‘ ์ •์˜ํ•˜๋Š” ์š”์†Œํ˜• ์…€๋ ‰ํ„ฐ๋Š” ์š”์†Œ์˜ ๋ณ€๊ฒฝ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋ฉด ์Šคํƒ€์ผ์ด ์ค‘๋ณต๋˜๊ฑฐ๋‚˜ ๋ˆ„๋ฝ๋  ๊ฐ€๋Šฅ์„ฑ์ด ํฌ๋ฏ€๋กœ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

3. ์ ๋‹นํ•œ ์˜ํ–ฅ ๋ฒ”์œ„

์˜ํ–ฅ ๋ฒ”์œ„๋ฅผ ๊ฐ€๋Šฅํ•œ ์ข๊ฒŒ ํ•˜๊ฑฐ๋‚˜ ์˜ํ–ฅ ๋ฒ”์œ„๊ฐ€ ๋„“์€ CSS์˜ ์Šคํƒ€์ผ์„ ์ตœ์†Œํ™”ํ•œ๋‹ค.

์˜ํ–ฅ ๋ฒ”์œ„๋ฅผ ๊ณ ๋ คํ•˜์ง€ ์•Š์€ ์ฑ„ ์Šคํƒ€์ผ์„ ์ถ”๊ฐ€ํ•˜๋‹ค๋ณด๋ฉด ์˜๋„ํ•˜์ง€ ์•Š์€ ๋ถ€๋ถ„์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฏ€๋กœ ์ตœ๋Œ€ํ•œ ๋ฒ”์œ„๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋ถ€๋ชจ ์š”์†Œ๋ฅผ ํฌํ•จ์‹œํ‚ค๊ฑฐ๋‚˜ ์†์ž์™€ ์ž๋…€ ์…€๋ ‰ํ„ฐ์˜ ์‚ฌ์šฉ๋„ ํ•จ๊ป˜ ๊ฒ€ํ† ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

4. ํŠน์ • ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•œ ์ ์ ˆํ•œ ์˜์กด๋„

์ปจํ…์ŠคํŠธ๋ž€ ์œ„์น˜ ๋˜๋Š” ์ƒํ™ฉ์„ ์˜๋ฏธํ•˜๋ฉฐ, ์ด ์ปจํ…์ŠคํŠธ๊ฐ€ ๋ณ€ํ•  ๋•Œ ์ฝ”๋“œ๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์„ ์ฃผ์˜ํ•ด์•ผ ํ•œ๋‹ค. ์‚ฌ์šฉ ๋ชฉ์ ์ด ๋ช…ํ™•ํ•˜๋‹ค๋ฉด ๋ฌธ์ œ์—†์ง€๋งŒ ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” ์…€๋ ‰ํ„ฐ๋ฅผ ๋ถˆํ•„์š”ํ•œ ๋ถ€๋ถ„๊นŒ์ง€ ๊ตฌ์ฒดํ™”ํ•˜๊ฒŒ ๋˜๋ฉด ํ•ด๋‹น ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์‰ฝ๋‹ค.

/* id์ธ main์„ ์ง€์ •ํ•˜๊ฒŒ ๋˜๋ฉด ํ•ด๋‹น ๋ชจ๋“ˆ ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ .title_top ํด๋ž˜์Šค๊ฐ€ ๋˜์–ด ์˜์กด๋„๊ฐ€ ๋†’์•„์ง. -> ๋ถˆํ•„์š”ํ•œ #main ์ œ๊ฑฐ */
#main .title_top{
  display:flex;
  align-items: center;
  color: green;
}

5. ์ ์ ˆํ•œ ๋ช…์‹œ๋„(specificy)

์šฐ์„ ์ˆœ์œ„๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ช…์‹œ๋„์™€ ๊ด€๋ จ๋œ ๋‚ด์šฉ์€ ์—ฌ๊ธฐ๋ฅผ ํด๋ฆญํ•˜๋ฉด ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ช…์‹œ๋„๊ฐ€ ๋†’์€ CSS์˜ ๋‹จ์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

– ์…€๋ ‰ํ„ฐ ์˜ˆ์ธก์ด ์–ด๋ ค์›€
– ๋‹ค๋ฅธ ์š”์†Œ(๋ถ€๋ชจ ์š”์†Œ ๋“ฑ)์— ๋Œ€ํ•œ ์˜์กด๋„ ์ƒ์Šน
– ๋ฎ์–ด์“ฐ๊ธฐ์˜ ์–ด๋ ค์›€
– ์œ ์ง€ ๋ณด์ˆ˜์˜ ์–ด๋ ค์›€

๋‹น์—ฐํžˆ !important๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ธฐ๋ณธ์ด๋ฉฐ, ์…€๋ ‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํด๋ž˜์Šค ์…€๋ ‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. id ์…€๋ ‰ํ„ฐ๋Š” ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋งค์šฐ ๋†’์œผ๋ฉฐ ํ•œ ํŽ˜์ด์ง€ ์•ˆ์—์„œ ๋™์ผํ•œ ๊ฐ’์€ ํ•œ๋ฒˆ ๋ฐ–์— ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋Š” ์ œ์•ฝ๋„ ์žˆ์œผ๋ฏ€๋กœ id๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์ ์€ ๋งŽ์ง€ ์•Š๋‹ค.

๋”ฐ๋ผ์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ํด๋ž˜์Šค ์…€๋ ‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์˜๋„ํ•˜์ง€ ์•Š์€ ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋’ค์„ž์ด์ง€ ์•Š๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.

6. ์˜ํ–ฅ ๋ฒ”์œ„๊ฐ€ ์œ ์ถ” ๊ฐ€๋Šฅํ•œ ํด๋ž˜์Šค ๋„ค์ž„

๊ทœ๋ชจ๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ๋ชจ๋“ˆ์ด๋‚˜ ํด๋ž˜์Šค๋„ ๋Š˜์–ด๋‚˜๋ฏ€๋กœ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค ์ˆ˜์ •์ด ์–ด๋–ค ๋ฒ”์œ„๊นŒ์ง€ ์˜ํ–ฅ์„ ๋ฏธ์น ์ง€๋ฅผ ์ด๋ฆ„์—์„œ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.

HTML์—์„œ ์ •์˜๋œ ์š”์†Œ์˜ ํด๋ž˜์Šค ๋„ค์ž„๋งŒ ๋ณด๊ณ ๋„ CSS์˜ ์˜ํ–ฅ ๋ฒ”์œ„๋ฅผ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์ž.

ํด๋ž˜์Šค ๋„ค์ž„์œผ๋กœ ์˜ํ–ฅ ๋ฒ”์œ„๋ฅผ ์‰ฝ๊ฒŒ ์œ ์ถ”ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ž๋…€ ์š”์†Œ์— ๋ฃจํŠธ ์š”์†Œ์˜ ํด๋ž˜์Šค ๋„ค์ž„์„ ํฌํ•จํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

7. ํ˜•ํƒœ, ๊ธฐ๋Šฅ, ์—ญํ• ์˜ ์œ ์ถ”๊ฐ€ ๊ฐ€๋Šฅํ•œ ํด๋ž˜์Šค ๋„ค์ž„

์˜ํ–ฅ ๋ฒ”์œ„์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ˜•ํƒœ, ๊ธฐ๋Šฅ, ์—ญํ• ๋„ ์œ ์ถ”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ๋„ค์ž„์„ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค.

– title1, title2, title3
– main-title, nav-title, sub-title

๋‘ ํ•ญ๋ชฉ ์ค‘ ํ˜•ํƒœ๋‚˜ ๊ธฐ๋Šฅ, ์—ญํ• ์˜ ์œ ์ถ”๊ฐ€ ์‰ฌ์šด ์ชฝ์ด ์–ด๋””์ธ์ง€๋Š” ๋ถ„๋ช…ํ•˜๋‹ค. ๊ฐ ๋ชจ๋“ˆ์˜ ๊ธฐ๋Šฅ์ด๋‚˜ ์—ญํ• ์— ๋งž์ถฐ ์ด๋ฆ„์„ ๋ถ™์ด๋Š” ๊ฒƒ์ด ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค. ํŠนํžˆ ์ž‘์€ ๊ทœ๋ชจ์˜ ์ฝ”๋“œ๋ผ๋ฉด title1, title2์™€ ๊ฐ™์ด ๋„ค์ž„์„ ๋Œ€์ถฉ ์ง€์ •ํ•˜๊ธฐ ์‰ฝ๋‹ค. ํ•˜์ง€๋งŒ ๊ทœ๋ชจ๋ž€ ์–ธ์ œ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ์ปค์งˆ์ง€ ๋ชจ๋ฅด๋ฏ€๋กœ ํ•ญ์ƒ ์Šต๊ด€์ ์œผ๋กœ ์ด๋ฆ„์—์„œ ํ˜•ํƒœ, ๊ธฐ๋Šฅ, ์—ญํ• ์„ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ๊ณ  ๊ตฌ์ฒด์„ฑ๊ณผ ๋ฒ”์šฉ์„ฑ์˜ ๊ท ํ˜•์„ ๋งž์ถ”๋„๋ก ํ•˜๋Š” ๋…ธ๋ ฅ์ด ํ•„์š”ํ•˜๋‹ค.

8. ํ™•์žฅ ์šฉ์ด์„ฑ

ํ™•์žฅ์„ฑ์ด๋ž€ ๊ฒฐ๊ตญ ๊ธฐ๋Šฅ์˜ ์ถ”๊ฐ€๋‚˜ ์œ ์ง€์™€ ์—ฐ๊ฒฐ๋˜๋Š” ๋ถ€๋ถ„์œผ๋กœ, ํ•ญ์ƒ ๊ฐ€๋Šฅ์„ฑ์„ ์—ด์–ด๋‘์–ด์•ผ ํ•œ๋‹ค.

ํ™•์žฅ์ด ์‰ฝ๋„๋ก ํด๋ž˜์Šค๋ฅผ ์„ค๊ณ„ํ•˜๊ฑฐ๋‚˜ ์ถ”๊ฐ€ํ•˜๋Š” ํด๋ž˜์Šค์—๋Š” ๊ธฐ๋Šฅ, ์—ญํ• ์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ์ƒ์„ธ๋„์™€ ์˜ํ–ฅ ๋ฒ”์œ„๋ฅผ ๊ฐ–๋„๋ก ํ•œ๋‹ค.

ํ™•์žฅ์ด ์‰ฌ์šด ํด๋ž˜์Šค๋ž€ ๋ฉ€ํ‹ฐ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ, ํ•˜๋‚˜์˜ ํด๋ž˜์Šค์—๋Š” ๋ณดํŽธ์ ์ธ ์†์„ฑ, ์ถ”๊ฐ€ ํด๋ž˜์Šค์—๋Š” ํŠน์ • ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ฎ์–ด์“ฐ๊ธฐ๋ฅผ ํ†ตํ•ด ์—ฌ๋Ÿฌ ํด๋ž˜์Šค๋กœ ์Šคํƒ€์ผ์„ ์ง€์ •ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

์ด๋ฅผ ํ†ตํ•ด HTML์€ ๋ณต์žกํ•ด์ง€์ง€๋งŒ CSS๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•ด์ง€๋Š” ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ๋„ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ๋ฉ€ํ‹ฐ ํด๋ž˜์Šค์˜ ์ด์ ์€ ๋ถˆ๊ทœ์น™ํ•œ ์ƒํ™ฉ์—์„œ๋„ ํด๋ž˜์Šค ํ•˜๋‚˜๋งŒ์œผ๋กœ ์›ํ•˜๋Š” ์ž‘์—…์„ ์™„๋ฃŒํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ„๊ฒฐํ•จ์ด๋‹ค.

๊ฒฐ๊ตญ ๋ชจ๋“  ํ•ญ๋ชฉ์€ ๋ณ„๊ฐœ์˜ ์‚ฌํ•ญ์ด ์•„๋‹ˆ๋ผ ๋‹ค ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ๊ณ , ์ž‘์€ ์ˆ˜์ • ํ•˜๋‚˜๊ฐ€ ํฐ ๋‚˜๋น„ํšจ๊ณผ๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์ ์„ ๋ช…์‹ฌํ•ด์•ผ ํ•œ๋‹ค.

๋งค๋ฒˆ ํ•˜๋‚˜ํ•˜๋‚˜ ์ฒดํฌํ•ด๊ฐ€๋ฉด์„œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ๋ณด๋‹ค๋Š” ์ž‘์„ฑ ๋ฐฉ์‹์ด ๊ณ ๋ฏผ๋˜๊ฑฐ๋‚˜ ์ž์œจ์„ฑ์ด ์ฃผ์–ด์กŒ์„ ๋•Œ, ํ•ด๋‹น ๋ฆฌ์ŠคํŠธ๋ฅผ ๋– ์˜ฌ๋ฆฌ๋ฉด์„œ ์ž‘์„ฑํ•˜๋‹ค๋ณด๋ฉด ์ƒ๊ฐ๋ณด๋‹ค๋„ ๋” ๊ฒฌ๊ณ ํ•œ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.


์ฐธ๊ณ  : ๋‹ค์–‘ํ•œ ์˜ˆ์ œ๋กœ ๋ฐฐ์šฐ๋Š” CSS ์„ค๊ณ„ ์‹ค์ „๊ฐ€์ด๋“œ(2021, ์ œ์ดํŽ)

์„ฑ๋Šฅ์— ์ค‘์š”ํ•œ repaint, reflow์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž

reflow์™€ repaint๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์š”์ธ ๋ถ„์„ํ•˜๊ธฐ

๋จผ์ € ํŽ˜์ด์ง€๊ฐ€ ๋ Œ๋”๋ง๋˜๋Š” ๊ณผ์ •์—์„œ reflow์™€ repaint์˜ ๋‹จ๊ณ„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

(DOM + CSSOM) render tree > layout(reflow) > paint(repaint) > composite

์—ฌ๊ธฐ์„œ ์„ฑ๋Šฅ๊ณผ ๊ด€๋ จ์ด ๊นŠ์€ reflow, repaint ๋‹จ๊ณ„์— ๊ด€ํ•ด ์•Œ์•„๋ณด์ž.

reflow

reflow(๋˜๋Š” layout)๋Š” render tree ์ƒ์„ฑ ํ›„ ์š”์†Œ์˜ ํฌ๊ธฐ์™€ ์œ„์น˜๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋‹จ๊ณ„์ด๋‹ค. ์ดˆ๊ธฐ ๋ Œ๋”๋ง ์‹œ ์ตœ์ดˆ๋กœ ๋ฐœ์ƒํ•˜๊ณ  ์š”์†Œ์˜ ํฌ๊ธฐ๋‚˜ ์œ„์น˜ ๋ณ€๊ฒฝ, ์š”์†Œ์˜ ์ถ”๊ฐ€๋‚˜ ์‚ญ์ œ ๋“ฑ ๋ ˆ์ด์•„์›ƒ์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค reflow๊ฐ€ ๋‹ค์‹œ ๋ฐœ์ƒํ•œ๋‹ค.

reflow๋Š” ์ž์‹๊ณผ ๋ถ€๋ชจ ๊ทธ๋ฆฌ๊ณ  ์š”์†Œ ์ž์‹ ์—๊ฒŒ๋„ ์˜ํ–ฅ์„ ๋ฏธ์น˜๋ฏ€๋กœ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ์ฃผ๋ฉฐ, ๋ ˆ์ด์•„์›ƒ์„ ๊ณ„์‚ฐํ•˜๋Š” reflow ํ›„ ๊ฐ€์‹œ์ ์ธ ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” paint ๋‹จ๊ณ„๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

reflow๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ตฌ์ฒด์ ์ธ ์ƒํ™ฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
(https://www.geeksforgeeks.org/what-is-dom-reflow/).

Reflow ๋ฐœ์ƒ ์›์ธ

– DOM์— ์š”์†Œ ์‚ฝ์ž…, ์ œ๊ฑฐ, ์—…๋ฐ์ดํŠธ
– ํŽ˜์ด์ง€์—์„œ ์ˆ˜์ • ์ž‘์—… ๋ฐœ์ƒ(Ex. input ๋ฐ•์Šค ํ…์ŠคํŠธ ์ˆ˜์ •)
– DOM์˜ ์š”์†Œ ์ด๋™
– DOM์˜ ์š”์†Œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ
– offsetHeight ๋˜๋Š” getComputedStyle()๋ฅผ ์‚ฌ์šฉํ•œ ์š”์†Œ ๊ณ„์‚ฐ
– CSS ์Šคํƒ€์ผ ๋ณ€๊ฒฝ
– ์š”์†Œ์˜ ํด๋ž˜์Šค ์ด๋ฆ„ ๋ณ€๊ฒฝ
– ์Šคํƒ€์ผ์‹œํŠธ ์ถ”๊ฐ€ ๋˜๋Š” ์ œ๊ฑฐ
– ์œˆ๋„์šฐ ๋ฆฌ์‚ฌ์ด์ง•
– ์›น ํŽ˜์ด์ง€ ์Šคํฌ๋กค
– ํฐํŠธ ๋ณ€๊ฒฝ
– CSS ์Šˆ๋„ ํด๋ž˜์Šค(์˜์‚ฌ ํด๋ž˜์Šค) ํ™œ์„ฑํ™”(Ex. :hover)
– ์š”์†Œ์— style ์–ดํŠธ๋ฆฌ๋ทฐํŠธ ์„ค์ •

reflow ๋‹จ๊ณ„์—์„œ ๋งŽ์€ ์—ฐ์‚ฐ์ด ๋ฐœ์ƒํ•˜๊ณ  repaint, composite ๋‹จ๊ณ„๋„ ์ด์–ด์„œ ๋ฐœ์ƒํ•˜๋ฏ€๋กœ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ๋ฐ–์— ์—†๋‹ค. ๋”ฐ๋ผ์„œ ํŽ˜์ด์ง€๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ์‹, ์„ฑ๋Šฅ๊ณผ ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ํƒ€ํ˜‘ ๋“ฑ์„ ํ†ตํ•ด reflow๋ฅผ ์ตœ์†Œํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ์•„์•ผ ํ•œ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ reflow๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

Reflow ์ค„์ด๋Š” ๋ฐฉ๋ฒ•

– ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ธ๋ผ์ธ ์Šคํƒ€์ผ์„ ์ง€์ •ํ•˜์ง€ ์•Š๊ณ  ๊ฐœ๋ณ„ ์Šคํƒ€์ผ ์„ค์ •์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ
– ์š”์†Œ์— ํด๋ž˜์Šค๋ช…์„ ์‚ฌ์šฉํ•˜๊ณ  DOM ํŠธ๋ฆฌ์—์„œ ์ตœ๋Œ€ํ•œ ํ•˜๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ
– ์ƒˆ๋กœ์šด ์Šคํƒ€์ผ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „์— DOM์—์„œ ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•œ ๋’ค ๋‹ค์‹œ ์ถ”๊ฐ€ํ•˜๊ธฐ
– ์Šคํƒ€์ผ์„ ์œ„ํ•œ ์žฆ์€ ์—ฐ์‚ฐ ํ”ผํ•˜๊ธฐ
– ์• ๋‹ˆ๋ฉ”์ด์…˜์€ fixed ๋˜๋Š” absolute๋กœ ์ง€์ •ํ•˜๊ธฐ
– ๊ฐ€๋Šฅํ•œ ํ…Œ์ด๋ธ” ๋ ˆ์ด์•„์›ƒ๋ณด๋‹ค ๋ธ”๋ก ๋ ˆ์ด์•„์›ƒ์„ ์‚ฌ์šฉํ•˜๊ธฐ
– ๊ณ ์ •๋œ ํฌ๊ธฐ๋กœ ํ…Œ์ด๋ธ” ์ƒ์„ฑํ•˜๊ธฐ
– ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์Šคํƒ€์ผ ๋ณ€๊ฒฝํ•˜๊ธฐ
– ํ…Œ์ด๋ธ” ๋ ˆ์ด์•„์›ƒ์„ fixed๋กœ ์ง€์ •ํ•˜๊ธฐ

REPAINT

repaint(๋˜๋Š” redraw)๋Š” ๋ ˆ์ด์•„์›ƒ์ด ์•„๋‹Œ, ์š”์†Œ์˜ ๊ฐ€์‹œ์ ์ธ ๋ถ€๋ถ„์ด ๋ณ€๊ฒฝ๋˜๋ฉด ๋ฐœ์ƒํ•˜๋Š” ๋‹จ๊ณ„์ด๋‹ค. ์š”์†Œ์˜ visibility, background, outline ๋“ฑ์ด ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค repaint๊ฐ€ ๋ฐœ์ƒํ•˜์ง€๋งŒ ํ•ด๋‹น ์†์„ฑ์€ ๋ ˆ์ด์•„์›ƒ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฏ€๋กœ reflow๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

repaint๋Š” render tree๋ฅผ ๋ ˆ์ด์–ด๋ณ„๋กœ ๋‚˜๋ˆ„์–ด ์ฒ˜๋ฆฌํ•˜๋ฏ€๋กœ, repaint ๋ฐœ์ƒ ์‹œ ํ•ด๋‹น ๋ ˆ์ด์–ด๋งŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

Reflow์™€ Repaint๋Š” stacking context์™€๋„ ๊ด€๋ จ์ด ์žˆ๋Š”๋ฐ, stacking context๋Š” ๊ฐ„๋‹จํ•˜๊ฒŒ 3์ฐจ์›์ธ z์ถ•์„ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์—ฌ๋Ÿฌ ์š”์†Œ๊ฐ€ ํ•˜๋‚˜์˜ ๋ ˆ์ด์–ด๋กœ ๋ฌถ์ด๊ฒŒ ๋˜๋ฉด ์ฐจ์ง€ํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๋ฌถ์ธ ์š”์†Œ ์ค‘ ํ•˜๋‚˜์˜ ์š”์†Œ์—์„œ ๋ณ€๊ฒฝ์ด ์ƒ๊ธฐ๋ฉด ํ•ด๋‹น ๋ ˆ์ด์–ด์— ์žˆ๋Š” ์š”์†Œ๋ฅผ ๋ชจ๋‘ ๋‹ค์‹œ ๊ทธ๋ ค์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ๋ณ€๊ฒฝ์ด ์ƒ๊ธธ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์š”์†Œ๋ฅผ ํ•˜๋‚˜์˜ ๋ ˆ์ด์–ด๋กœ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌํ•˜๋ฉด ํ•ด๋‹น ๋ ˆ์ด์–ด๋งŒ ๋‹ค์‹œ ๊ทธ๋ฆฌ๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํšจ์œจ์ ์œผ๋กœ ๋ฆฌ๋ Œ๋”๋ง์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•ด๋‹น ์š”์†Œ๋ฅผ ํ•˜๋‚˜์˜ ๋ ˆ์ด์–ด๋กœ ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์กฐ๊ฑด์€ ๋‹ค์Œ ์‚ฌ์ดํŠธ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
stacking context ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ(MDN)

์กฐ๊ฑด ์ค‘ ‘opacity < 1’์ด ์žˆ๋Š”๋ฐ, opacity ๊ฐ’์ด 0~0.99์ธ ์ƒํ™ฉ์—์„œ๋งŒ ๋ ˆ์ด์–ด๊ฐ€ ๋ณ„๋„๋กœ ์ƒ์„ฑ๋œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

opacity๊ฐ€ 1์ผ ๋•Œ๋Š” reflow๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด๋Š” opacity:1์ธ ๊ฒฝ์šฐ ๋‹ค๋ฅธ ์š”์†Œ์™€ ํ•˜๋‚˜์˜ ๋ ˆ์ด์–ด๋ฅผ ์ด๋ฃจ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

Composite

์ƒํ™ฉ์— ๋”ฐ๋ผ Reflow, Repaint๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š” ์†์„ฑ์œผ๋กœ transform, opacity ๋“ฑ์ด ์žˆ๋Š”๋ฐ ์ด ์†์„ฑ์€ ๋ Œ๋”๋ง์˜ ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„์ธ composite๋งŒ ์‹คํ–‰๋œ๋‹ค.

ํ•ด๋‹น ์†์„ฑ์€ CPU๊ฐ€ ์•„๋‹Œ GPU์—์„œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” graphic layer๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ธ๋ฐ composite ๋‹จ๊ณ„์—์„œ layer๋ฅผ ๋ณ‘ํ•ฉํ•œ๋‹ค.

GPU๋Š” CPU์— ๋น„ํ•ด ์—ฐ์‚ฐ์ด ๋น ๋ฅด๊ณ  ์ด๋ฏธ์ง€์™€ ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ๋ณด์ • ๊ธฐ๋Šฅ๋„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์ด๋ฏธ์ง€๋‚˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ฒ˜๋ฆฌ์— ์ข‹์€ ๋Œ€์•ˆ์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

GPU๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์กฐ๊ฑด์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

GPU ์‚ฌ์šฉ ์กฐ๊ฑด

– 3D transforms ์‚ฌ์šฉ(translate3d, translateZ ๋“ฑ)
– <video>, <canvas>, <iframe> ์š”์†Œ ์‚ฌ์šฉ
– transform, opacity๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜
– position:fixed ์š”์†Œ
– will-change ์‚ฌ์šฉ
– filter ์‚ฌ์šฉ

GPU์˜ ์žฅ์ ์€ ๋น ๋ฅธ ์—ฐ์‚ฐ์ด์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋งŽ์ด ์ฐจ์ง€ํ•˜๋Š” ๋‹จ์ ๋„ ์žˆ์œผ๋ฏ€๋กœ ์ ์ •์„ ์—์„œ ์‚ฌ์šฉํ•ด์•ผ ์พŒ์ ํ•œ ํ™˜๊ฒฝ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

์ฐธ๊ณ 
Understanding Repaint and Reflow in Javascript
What is DOM reflow
GPU animation: Doing It Right
Stacking Context

CSS์˜ em, rem, vh, vw, %์˜ ๋‹จ์œ„๋ฅผ ์•Œ์•„๋ณด์ž

๋ฐ˜์‘ํ˜•์„ ์œ„ํ•œ ๋‹จ์œ„์˜ ํ™œ์šฉ

CSS์—์„œ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ด ๋˜๋Š” ํฌ๊ธฐ ๋‹จ์œ„๊ฐ€ ํ”ฝ์…€(px)์ธ๋ฐ์š”.

1px์€ 0.00264cm๋กœ ํ™˜์‚ฐ๋˜๋Š” ๊ธธ์ด๋กœ, 300px์€ ์•ฝ 8cm๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

16px์€ 0.42cm์ธ๋ฐ์š”. ์ด 16px์ด ๋ฐ”๋กœ CSS์—์„œ ๊ธฐ๋ณธ๊ฐ’์ž…๋‹ˆ๋‹ค.

font-size : 16px์€ ์„ธ๋กœ ๊ธธ์ด๊ฐ€ 16px(0.423cm)์ธ ํฐํŠธ ์‚ฌ์ด์ฆˆ๋ผ๋Š” ์˜๋ฏธ๋กœ, ์ถœํŒ๋ฌผ์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์‚ฌ์ด์ฆˆ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ์ด ๊ธฐ๋ณธ ์‚ฌ์ด์ฆˆ 16px์„ ๊ธฐ๋ฐ˜์œผ๋กœ em, rem์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

em

em์€ ๊ธฐ์ค€ ํฌ๊ธฐ์— ๋Œ€ํ•œ ๋ฐฐ์ˆ˜๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ์ค€์€ font-size์ด๋ฉฐ ๊ฐ™์€ ์š”์†Œ์˜ ์‚ฌ์ด์ฆˆ์—์„œ ์‹œ์ž‘ํ•ด ๋ถ€๋ชจ๋กœ ์ฐจ๊ทผ์ฐจ๊ทผ ์˜ฌ๋ผ๊ฐ‘๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๊ฐ™์€ ์š”์†Œ์— font-size:16px์ด ์„ค์ •๋œ ๊ฒฝ์šฐ em์˜ ๊ธฐ์ค€์€ 16px์ด ๋ฉ๋‹ˆ๋‹ค.

.child-size{
    font-size : 16px;
    width : 2em;   // 2 * 16px = 32px;
}

์œ„ ์ฝ”๋“œ์—์„œ child-size ๋‚ด๋ถ€์— font-size๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ํ•ด๋‹น ์š”์†Œ์˜ width : 2em๋Š” 16์˜ 2๋ฐฐ์ธ 32px์ด ๋ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ™์ด child-size ๋‚ด๋ถ€์— font-size๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด ํ•ด๋‹น ์š”์†Œ๋ฅผ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค์—์„œ ๊ธฐ์ค€ ์‚ฌ์ด์ฆˆ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

.parent-size{
    font-size : 20px;
}
.child-size{
    width : 2em;   // 2 * 20px = 40px;
}

์ตœ์ƒ๋‹จ๊นŒ์ง€ ์ด๋™ํ•ด๋„ font-size๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” ์œ„์—์„œ ๋งํ•œ ๊ธฐ๋ณธ๊ฐ’์ธ 16px์„ ๊ธฐ์ค€์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

rem

rem์€ em๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ r์€ root๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ตœ์ƒ๋‹จ์ธ html์— ์ •์˜๋œ ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

html{
    font-size : 20px;
}
.child-size{
    font-size : 16px;
    width : 2rem;   // 2 * 20px = 40px;
}

์ตœ์ƒ๋‹จ์˜ ํฌ๊ธฐ๋ฅผ ๊ธฐ์ค€ํ•˜๋ฏ€๋กœ 20px์ด ๊ธฐ์ค€์ด ๋˜์–ด 2rem์€ 40px๋กœ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.

vw

Viewport Width๋Š” ์Šคํฌ๋กค์„ ํฌํ•จํ•œ ์œˆ๋„์šฐ์˜ ๋„ˆ๋น„๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ, ๋ฐ˜์‘ํ˜•์„ ์œ„ํ•ด ์ƒ๋Œ€์  ํฌ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1vw๋Š” ๋ทฐํฌํŠธ ๋„ˆ๋น„์˜ 1%์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ’์œผ๋กœ ๋„ˆ๋น„๊ฐ€ 1000px์ธ ๊ฒฝ์šฐ 1vw๋Š” 10px, 100vw๋Š” 1000px์ด ๋ฉ๋‹ˆ๋‹ค.

๋ธŒ๋ผ์šฐ์ €์˜ ์‚ฌ์ด์ฆˆ ๋ณ€๊ฒฝ์ด๋‚˜ ๋ชจ๋ฐ”์ผ ๋“ฑ์—์„œ ์ „์ฒด ๋น„์œจ์„ ๋งž์ถ”๊ณ  ์‹ถ์„ ๋•Œ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ™”๋ฉด์„ ๊ฐ€๋กœ๋กœ ๊ฐ€๋“ ์ฑ„์šฐ๊ณ  ์‹ถ์„ ๋•Œ 100vw๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

.layout{
    width : 100vw;
}

vh

Viewport Height๋Š” ์œˆ๋„์šฐ์˜ ๋†’์ด๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ vw์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ทฐํฌํŠธ ๋†’์ด์˜ 1%๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

ํ™”๋ฉด์„ ๊ฐ€๋“ ์ฑ„์šฐ๊ณ  ์‹ถ์„ ๋•Œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋„ˆ๋น„์™€ ๋†’์ด๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

.layout{
    width : 100vw;
    height: 100vh;
}

%

%๋Š” ๋ถ€๋ชจ ์š”์†Œ์— ๋”ฐ๋ผ ํฌ๊ธฐ๊ฐ€ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค.

๋†’์ด๋ฅผ 100%๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋ถ€๋ชจ์˜ ๋†’์ด์˜ 100%๋ฅผ ์„ค์ •ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋ถ€๋ชจ์˜ ๋†’์ด๊ฐ€ 100px์ธ ๊ฒฝ์šฐ ์ž์‹ ์š”์†Œ์—์„œ height : 100%๋ฅผ ์„ค์ •ํ•˜๋ฉด ๋†’์ด๋Š” 50๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

width : 100%์ธ ๊ฒฝ์šฐ ์Šคํฌ๋กค๋ฐ”์˜ ๋„ˆ๋น„๋ฅผ ์ƒ๋žตํ•œ ํฌ๊ธฐ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

font-size : 100%์˜ ๊ฒฝ์šฐ ๋ถ€๋ชจ ์š”์†Œ์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ ๊ธฐ๋ณธ๊ฐ’์€ 16px์ด ๋ฉ๋‹ˆ๋‹ค.

CSS selector ์šฐ์„ ์ˆœ์œ„, ๋ช…์‹œ๋„(specificity)

์š”์†Œ ์„ ํƒ์ž(Element Selector) ์ ์ˆ˜ ๊ณ„์‚ฐํ•˜๊ธฐ

CSS์—์„œ๋Š” ์š”์†Œ์˜ ์„ ํƒ์ž์— ๋”ฐ๋ผ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋‚˜๋‰œ๋‹ค.

์šฐ์„ ์ˆœ์œ„ ๊ฐ€์ค‘์น˜๋ฅผ ํ†ตํ•ด ์Šคํƒ€์ผ์„ ์ ์šฉํ•  ์ˆœ์„œ๋ฅผ ๊ฒฐ์ •ํ•˜์ง€๋งŒ ํ˜„์žฌ๋Š” ๊ฐ€์ค‘์น˜ ๊ณ„์‚ฐ ๋ฐฉ์‹์ด ๋ธŒ๋ผ์šฐ์ €๋ณ„๋กœ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์„ ํƒ์ž์˜ ์ƒ๋Œ€ ์šฐ์„ ์ˆœ์œ„๋ฅผ ์•Œ์•„๋‘๋Š” ๊ฒƒ์ด ๋” ์ข‹๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๊ธฐ์กด์—๋Š” ๊ฐ€์ค‘์น˜๊ฐ€ class:10, id:100์œผ๋กœ, class 10๊ฐœ๊ฐ€ 1๊ฐœ์˜ id์™€ ๋™๋“ฑํ•œ ๊ฐ€์ค‘์น˜๋ฅผ ๊ฐ€์กŒ์ง€๋งŒ ํ˜„์žฌ๋Š” ๊ฐ€์ค‘์น˜๊ฐ€ ๋‹ฌ๋ผ์ ธ ์ผ๋ถ€ ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” 256๊ฐœ์˜ class๊ฐ€ 1๊ฐœ์˜ id์™€ ๋™๋“ฑํ•œ ์šฐ์„  ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„๋‹ค. (์ฐธ๊ณ :stackoverflow)

์„ ํƒ์ž๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฐ€์ง„๋‹ค.

!important > inline style > id > class (pseud0) > element (pseudo)

๋”ฐ๋ผ์„œ ์„ ํƒ์ž๋ณ„๋กœ ์ƒ๋Œ€์ ์ธ ๊ฐ€์ค‘์น˜๋ฅผ ํŒ๋‹จํ•˜์—ฌ ๋†’์€ ์ˆœ์„œ์— ๋”ฐ๋ผ ์™ผ์ชฝ๋ถ€ํ„ฐ comma๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

๋†’์Œinline style , id , class (pseud0) , element (pseudo) <๋‚ฎ์Œ
Ex1) 0 , 1 , 2 , 1
Ex2) 0 , 0 , 200 , 10
๐Ÿ‘‰ Ex1์ด Ex2๋ณด๋‹ค ๊ฐ€์ค‘์น˜๊ฐ€ ๋†’์Œ

์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด id, class ์„ ํƒ์ž๊ฐ€ ๋ชจ๋‘ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ ์šฐ์„ ์ˆœ์œ„์— ๋”ฐ๋ผid ์Šคํƒ€์ผ์ด ์ ์šฉ๋œ๋‹ค.

.myMenuClass{
  color:green;
}

#myMenuId{
  color:red;
}

<h1 id="myMenuId" class="myMenuClass">This is it</h1>

๊ทธ๋ฆฌ๊ณ  ๊ฐ€์ค‘์น˜์˜ ํ•ฉ์‚ฐ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

#myMenuId{
  color:red;
}

.myMenuClass{
  color:blue;  
}

h1#myMenuId{
  color:orange;  
}

<h1 id="myMenuId" class="myMenuClass">This is it!</h1>

์šฐ์„  ์ˆœ์œ„๋ฅผ ๊ณ„์‚ฐํ•ด๋ณด๋ฉด,

#myMenuId : 0,1,0,0 / .myMenuClass : 0,0,1,0 / h1#myMenuId : 0,1,0,1

๋”ฐ๋ผ์„œ ๋งˆ์ง€๋ง‰ orange color๊ฐ€ ์ ์šฉ๋œ๋‹ค.

!important๋Š” ๋ชจ๋“  ๊ฐ€์ค‘์น˜๋ฅผ ๋ฌด์‹œํ•˜๊ณ  ์ตœ์šฐ์„ ์ ์œผ๋กœ ์ ์šฉํ•˜๋Š” ์น˜ํŠธํ‚ค์™€ ๊ฐ™๋‹ค. !important๊ฐ€ ์š”์†Œ์— ์ค‘๋ณต๋˜๋Š” ๊ฒฝ์šฐ ๊ฐ€์žฅ ๋’ค์— ์„ ์–ธ๋œ !important๊ฐ€ ์ ์šฉ๋œ๋‹ค.

ํ•˜์ง€๋งŒ !important์˜ ์‚ฌ์šฉ&๋‚จ์šฉ์€ ํ‰ํ™”๋กœ์šด ์ƒํƒœ๊ณ„๋ฅผ ์œ„ํ˜‘ํ•˜๋Š” ์กด์žฌ๊ฐ€ ๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ตœ๋Œ€ํ•œ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ •์‹  ๊ฑด๊ฐ•๊ณผ ์ฝ”๋“œ ๊ตฌ์„ฑ์—๋„ ์ข‹๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ ์˜ˆ์™ธ ์‚ฌํ•ญ๋„ ์•Œ์•„๋ณด์ž.

์šฐ์„ ์ˆœ์œ„ ์—†์Œ: *,:where()
๊ฐ€์ค‘์น˜ ํฌํ•จํ•˜์ง€ ์•Š์Œ: >, ~, +
๊ฐ€์žฅ ๋†’์€ ๊ฐ€์ค‘์น˜ ํ•˜๋‚˜๋งŒ ์„ ํƒ: :is(), :not()
ex) :is(#menuId, .menuId, span) -> ๊ฐ€์ค‘์น˜ ๊ฐ€์žฅ ๋†’์€ #menuId๋งŒ ์นด์šดํŠธ

rgba๋ฅผ ์‚ฌ์šฉํ•ด opacity์˜ ์ƒ์† ๋ฌธ์ œ ํ•ด๊ฒฐ(ํˆฌ๋ช…๋„ ์กฐ์ ˆ)

์ž์‹ ๋…ธ๋“œ์— ์ƒ์†๋˜๋Š” opacity์™€ ๋‹จ๋…์ ์ธ rgba

๋ถ€๋ชจ ๋…ธ๋“œ์— opacity ํšจ๊ณผ๋ฅผ ์ฃผ๋ฉด ์ž์‹ ๋…ธ๋“œ์—๋„ ์ƒ์†๋˜์–ด ํˆฌ๋ช… ํšจ๊ณผ๊ฐ€ ํ•จ๊ป˜ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

์ž๋™์œผ๋กœ ์ƒ์†์ด ๋˜๋ฏ€๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์•„๋ž˜ ์„ค์ •์œผ๋กœ ์ƒ‰์ƒ์„ ์ง€์ •ํ•œ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค.
๋ฐฐ๊ฒฝ black
opacity:0.5
background:yellow
background:red

๋ณด๋‹ค์‹œํ”ผ yellow, red์— opacity๊ฐ€ ์ ์šฉ๋˜์–ด ์ƒ‰์ƒ์ด ํ๋ ค์ง„ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ด ์ƒ์† ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”?

๊ฐ„๋‹จํ•˜๊ฒŒ opacity ๋Œ€์‹  rgba๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

ํˆฌ๋ช…๋„๋ฅผ ํฌํ•จํ•˜๋Š” ์ƒ‰์ƒ์˜ ์ง€์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

rgba(R, G, B, opacity);

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์œ„ ๋ฐ•์Šค์— ํ•ด๋‹นํ•˜๋Š” ์ƒ‰์ƒ์ธ #9ADFFD์„ rgba ๋ฐฉ์‹์œผ๋กœ ํ‘œํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

16์ง„์ˆ˜๋ฅผ 10์ง„์ˆ˜๋กœ ๋ณ€ํ˜•ํ•œ ๊ฐ’์ธ 9A=154, DF=223, Fd=253์„ ๊ฐ๊ฐ R, G, B ์œ„์น˜์— ๋„ฃ์–ด์ฃผ๊ณ  ๋งˆ์ง€๋ง‰ ์ธ์ˆ˜๋Š” 0~1 ์‚ฌ์ด์˜ ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

background : rgba(154, 223, 253, 0.5);

์ด์ œ ์ž์‹ ๋…ธ๋“œ๋Š” opacity๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์ƒ‰์ƒ์ด ์„ ๋ช…ํ•ด์ง„ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒ€์€ ๋ฐฐ๊ฒฝ์„ ์‚ฌ์šฉํ•ด๋„ ์ž์‹ ๋…ธ๋“œ์— ์„ ๋ช…๋„๊ฐ€ ์‚ด์•„๋‚œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด๋ฅผ ํ†ตํ•ด ์ƒ์†๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ์— ์‚ฌ์šฉํ•œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

<div class="div0">
    <div class="div1">
      modify
    </div>
    <div class="div2">
      delete
    </div>
</div>

.div0{
  height:100px;
  background : rgba(0, 0, 0, 0.5);
  display:flex;
  justify-content:center;
  align-items:center;
}

.div1{
  width:200px;
  height:50px;
  background-color:gold;
  display:flex;
  justify-content:center;
  align-items:center;
  color:white;
}

.div2{
  width:200px;
  height:50px;
  background-color:red;
  display:flex;
  justify-content:center;
  align-items:center;
  color:white;
}

Emotion(Styled), Props ์ „๋‹ฌํ•˜๊ธฐ(Typescript)

Typescript์™€ ํ•จ๊ป˜ ๋™์  CSS ์Šคํƒ€์ผ ์‚ฌ์šฉํ•˜๊ธฐ
import styled from "@emotion/styled";

const StyledPropsTest = styled.div`
  width: 120px;
  height: 40px;
  font-size: 25px;
  background: ${(props) => (props.testProps ? "blue" : "red")};
  color: white;
`;

const StyledTest = ({testprops}) => {
  return(
    <StyledPropsTest testProps={testprops}>Prop Test</StyledPropsTest>
  )
}

export default StyledTest;

์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ณ€์ˆ˜๋ฅผ CSS์— ์ „๋‹ฌํ•˜์—ฌ ๋™์  ์Šคํƒ€์ผ์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์œ„์™€ ๊ฐ™์ด props๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ Typescipt๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ custom props๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—๋Ÿฌ๋ฅผ ๋งŒ๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

(property) testProps: boolean
Type ‘{ children: string; testProps: boolean; }’ is not assignable to type ‘IntrinsicAttributes & { theme?: Theme | undefined; as?: ElementType<any> | undefined; } & ClassAttributes<HTMLDivElement> & HTMLAttributes<…>’.
Property ‘testProps’ does not exist on type ‘IntrinsicAttributes & { theme?: Theme | undefined; as?: ElementType<any> | undefined; } & ClassAttributes<HTMLDivElement> & HTMLAttributes<…>’.ts(2322)

์ด๋Š” ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ props์˜ ํƒ€์ž…์„ ์ฒดํฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ธ๋ฐ์š”.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„๋‹จํ•˜๊ฒŒ <{data:type}>์˜ ํƒ€์ž… ๋‹จ์–ธ(Type Assertion)์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const StyledPropsTest = styled.div<{testProps:boolean}>`
  width: 120px;
  height: 40px;
  font-size: 25px;
  background: ${(props) => (props.testProps ? "blue" : "red")};
  color: white;
`;

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์—๋Ÿฌ๊ฐ€ ์‚ฌ๋ผ์ง„ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

CSS, calc()๋ฅผ ์‚ฌ์šฉํ•ด main(body) ๋†’์ด ์ž๋™ ์„ค์ •ํ•˜๊ธฐ

CSS์—์„œ calc ๋ฉ”์„œ๋“œ ์‚ฌ์šฉํ•˜๊ธฐ

CSS์—์„œ calc() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด window ์ฐฝ์˜ ์‚ฌ์ด์ฆˆ ๋ณ€๊ฒฝ์— ๋”ฐ๋ผ ์ž๋™์œผ๋กœ ๊ธธ์ด๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

header, main, footer์˜ ๋ ˆ์ด์•„์›ƒ์„ ๋‚˜๋ˆŒ ๋•Œ main์—์„œ calc()๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์œˆ๋„์šฐ ์ฐฝ์˜ ํฌ๊ธฐ๊ฐ€ ์ค„์–ด๋“ค์–ด๋„ main์˜ ๋‚ด์šฉ์ด ์ž˜๋ฆด ์—ผ๋ ค ์—†์ด ๊ฐ€๋ณ€์ ์œผ๋กœ ์ฐฝ์˜ ํฌ๊ธฐ์— ๋งž๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1. ํ•„์š”์„ฑ

์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์œ„์™€ ๊ฐ™์€ ํ™”๋ฉด์ด ์žˆ์„ ๋•Œ ์œˆ๋„์šฐ ์ฐฝ์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ์ค„์ด๋ฉด(resizing) ๊ฐ€์šด๋ฐ main์˜ ์Šคํฌ๋กค์„ ๋๊นŒ์ง€ ๋‚ด๋ ค๋„ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ชจ๋‘ ํ‘œ์‹œ๋˜์ง€ ์•Š์„ ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์Šคํฌ๋กค์„ ๋๊นŒ์ง€ ๋‚ด๋ ธ์ง€๋งŒ ์ด๋ ‡๊ฒŒ r ๊นŒ์ง€๋งŒ ํ‘œ์‹œ๋˜๊ณ  ์•„๋žซ๋ถ€๋ถ„์€ ์งค๋ ค์„œ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฐ ์ƒํ™ฉ์—์„œ main์˜ div ๋†’์ด๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ์ž๋™์œผ๋กœ ์กฐ์ ˆํ•ด์ฃผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์œˆ๋„์šฐ๊ฐ€ ๋ฆฌ์‚ฌ์ด์ง• ๋˜๋”๋ผ๋„ ํ™”๋ฉด์ด ์งค๋ฆฌ์ง€ ์•Š๊ณ  ์œ ์ง€๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ์ ์šฉํ•˜๊ธฐ

main div์˜ ๋†’์ด(height)์— calc() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ‘๋ทฐ ๋†’์ด(vh) – ๋‚˜๋จธ์ง€ ๊ณต๊ฐ„’์„ ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋‹ค๋งŒ ์ „๋‹ฌ๊ฐ’์˜ +, – ์•ž ๋’ค์—๋Š” ๋ฐ˜๋“œ์‹œ ๊ณต๋ฐฑ์„ ์‚ฝ์ž…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

// OK
height: calc(100vh - 300px);

// ์—๋Ÿฌ(๊ณต๋ฐฑ ์—†์Œ)
height: calc(100vh-300px);

๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ, ๋ฆฌ๋ Œ๋”๋ง ์‹œ CSS๋„ ํ•จ๊ป˜ ๋ฆฌ๋กœ๋“œํ•˜๋Š” ๋ฐฉ๋ฒ•(feat.animation)

์ปดํฌ๋„ŒํŠธ ๋ฆฌ๋ Œ๋”๋ง ์‹œ CSS๋„ ํ•จ๊ป˜ ๋ฆฌ๋ Œ๋”๋งํ•˜๋„๋ก ๋งŒ๋“ค๊ธฐ

๋ฆฌ์•กํŠธ๋Š” ๋‚ด๋ถ€ ๋กœ์ง์— ๋”ฐ๋ผ ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์„ ์ตœ์†Œํ™”ํ•˜๋„๋ก ๋˜์–ด์žˆ์ง€๋งŒ ๋•Œ๋กœ๋Š” ์ด ๋กœ์ง์ด ์˜๋„ํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•  ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŠนํžˆ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ค„ ๋•Œ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๊ณ  ๋งˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํด๋ฆญ ์‹œ๋งˆ๋‹ค ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋™์ž‘ํ•˜๋„๋ก ๋งŒ๋“ค๊ณ ์ž ํ•  ๋•Œ ๋‹ค์Œ ๋ฐฉ๋ฒ•์„ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์›๋ฆฌ๋Š” ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” state๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ๋ฆฌ๋ Œ๋”๋ง์„ ์‹คํ–‰ํ•˜๋ฏ€๋กœ ํด๋ฆญ ์‹œ๋งˆ๋‹ค state ๊ฐ’์— ๋ณ€๊ฒฝ์„ ์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ ์ปดํฌ๋„ŒํŠธ์˜ ์ด๋ฏธ์ง€๋ฅผ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

const ColorChange = ({ color }) => {
  const DisplayBox = styled.div`
    width: 300px;
    height: 300px;
    display: flex;
    background: ${color};
    animation: change 3s;

    @keyframes change {
      0% {
        transition-timing-function: cubic-bezier(1, 0, 0.2, 0.5);
      }
      0% {
        width: 0;
      }
    }
  `;

  return <DisplayBox></DisplayBox>;
};

export default ColorChange;

---------------------------------------------------------------
์ปดํฌ๋„ŒํŠธ ํ˜ธ์ถœ
<ColorChange color={color} /> 

red, green์„ ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉฐ ๋ˆ„๋ฅด๋ฉด ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌ๋˜๋Š” state๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฏ€๋กœ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜๋ฉด์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ red์ธ ์ƒํƒœ์—์„œ ๋‹ค์‹œ red๋ฅผ ํ•œ๋ฒˆ ๋” ๋ˆ„๋ฅด๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ํด๋ฆญ๋งˆ๋‹ค CSS๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜์–ด ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ž‘๋™ํ•˜๋„๋ก ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”?

๋‹จ์ˆœํ•˜๊ฒŒ ํด๋ฆญ๋งˆ๋‹ค ์ „๋‹ฌ๋˜๋Š” state์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋„๋ก ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ปดํฌ๋„ŒํŠธ key ์†์„ฑ์œผ๋กœ ์ž„์˜์˜ ๊ฐ’์„ ์ƒ์„ฑํ•˜์—ฌ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

const [randomData, setRandomData] = useState(Math.random());

//๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ํ˜ธ์ถœ ํ•จ์ˆ˜
const changeColor = () => {
     // ์ƒ‰์ƒ ๋ณ€๊ฒฝ ์ž‘์—…
     .......
     // ์ž„์˜์˜ ๊ฐ’ ์ƒ์„ฑ
     setRandomData(Math.random());
}

<ColorChange color={color} key={randomData} /> 

์ „๋‹ฌ๋˜๋Š” color ๊ฐ’์˜ ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•˜์—ฌ ๋ฆฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜๊ณ  ๊ทธ์— ๋”ฐ๋ผ CSS animation๋„ ๋ฆฌ๋กœ๋“œ๋˜์ง€๋งŒ ๊ณ„์† ๊ฐ™์€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ๋™์ผํ•œ color ๊ฐ’์ด ์ „๋‹ฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณ€๊ฒฝ์„ ๊ฐ์ง€ํ•˜์ง€ ๋ชปํ•ด ๋ฆฌ๋ Œ๋”๋ง์ด ๋˜์ง€ ์•Š๋Š” ์›๋ฆฌ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ํด๋ฆญ ์‹œ color ๊ฐ’์€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋”๋ผ๋„ key ๊ฐ’์„ ๊ณ„์† ๋ณ€๊ฒฝํ•˜๋ฉด ๋ฆฌ์•กํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ ๋ณ€๊ฒฝ์„ ์ธ์‹ํ•˜์—ฌ ๊ณ„์† ์ปดํฌ๋„ŒํŠธ์™€ CSS๋ฅผ ๋ฆฌ๋ Œ๋”๋งํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


๋ Œ๋”๋ง์€ ์ตœ๋Œ€ํ•œ ๋ฆฌ์•กํŠธ์—๊ฒŒ ๋งก๊ธฐ๊ณ  ๋ถˆํ•„์š”ํ•œ ๋ Œ๋”๋ง์€ ์ตœ์†Œํ™”ํ•˜๋˜ ์œ„์™€ ๊ฐ™์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์—๋งŒ ๋ถ€๋ถ„์ ์œผ๋กœ ์ ์šฉํ•˜๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ์ž‘๋™ ๋ฐฉ์‹์˜ ์ดํ•ด๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

Next.js + Typescript + Emotion + Tailwind ํ™˜๊ฒฝ ๊ตฌ์ถ•ํ•˜๊ธฐ

Next.js์—์„œ Emotion๊ณผ TailwindCSS๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์„ค์ •

1. Next.js ์„ค์น˜

๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•ด Next.js์˜ ์ตœ์‹  ๋ฒ„์ „ + typescript๋ฅผ ์„ค์น˜ํ•œ๋‹ค.

npx create-next-app@latest --ts

์•„๋ž˜ ๋ช…๋ น์–ด๋กœ ์„ค์น˜ ๋ฐ ๋ฒ„์ „์„ ํ™•์ธํ•œ๋‹ค.

npx next -v

2. emotion ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

emotion ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•œ๋‹ค.

npm i @emotion/react @emotion/styled @emotion/css @emotion/server

3. tailwind, twin.macro ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜

tailwind, twin.macro ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•˜๊ณ  devDependencies์— ์ถ”๊ฐ€ํ•œ๋‹ค.

npm i twin.macro tailwindcss postcss@latest autoprefixer@latest @emotion/babel-plugin babel-plugin-macros --save-dev

config ํŒŒ์ผ ์ƒ์„ฑ์„ ์œ„ํ•ด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

tailwind.config.js๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ž…๋ง›์— ๋งž๊ฒŒ ์‚ฌ์šฉ์ž ์ง€์ • ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

npx tailwindcss init -p
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

styles/globals.css์˜ ์ƒ๋‹จ์— ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. (HTML ํƒœ๊ทธ ๋‚ด์—์„œ ์ธ๋ผ์ธ์œผ๋กœ tailwind๋ฅผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•จ)

@tailwind base;
@tailwind components;
@tailwind utilities;

4. .babelrc ์ƒ์„ฑ

twin.macro์˜ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก plugin ์„ค์ •์„ ํ•ด์•ผ ํ•˜๋ฏ€๋กœ .babelrc ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค.

๋‚ด๋ถ€ ์„ค์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

{
  "presets": ["next/babel"],
  "plugins": ["babel-plugin-macros"]
}

5. ์ž‘๋™ ํ…Œ์ŠคํŠธ

emotion ๋ฐ emotion +tw(tailwind) ์ž‘๋™์„ ํ…Œ์ŠคํŠธํ•œ๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ๋ฅผ pages/index.tsx์— ์ž‘์„ฑํ•˜๊ณ  npm run dev๋กœ ์‹คํ–‰ํ•œ๋‹ค.

import type { NextPage } from "next";
import styles from "../styles/Home.module.css";
import styled from "@emotion/styled/macro";
import tw from "twin.macro";

const Input = tw.input`
    text-center border h-28
`;

const MyDiv = styled.div`
  background: gold;
  font-size: 5rem;
  margin-top: 10px;
`;

const Home: NextPage = () => {
  return (
    <div className={styles.container}>
      <main className={styles.main}>
        <h1 className={styles.title}>
          <Input placeholder="box" />
          <MyDiv>Test Text</MyDiv>
        </h1>
      </main>
    </div>
  );
};

export default Home;

๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.


๊ด€๋ จ ๋งํฌ

nextJS https://nextjs.org/

tailwindCSS https://tailwindcss.com/

emotion https://emotion.sh/docs/introduction

twin.macro https://github.com/ben-rogerson/twin.macro#readme