[๐Ÿค–] CSS ๋ณ€์ˆ˜(Custom Properties) ์‹ฌํ™”: ๋™์  ํ…Œ๋งˆ, ์Šค์ฝ”ํ•‘, JavaScript ํ™œ์šฉ ์ „๋žต

CSS ๋ณ€์ˆ˜(Custom Properties)์˜ ๊ธฐ๋ณธ๋ถ€ํ„ฐ ๋™์  ํ…Œ๋งˆ ๊ตฌํ˜„, ์Šค์ฝ”ํ•‘ ์ „๋žต, ๊ทธ๋ฆฌ๊ณ  JavaScript์™€์˜ ์ƒํ˜ธ์ž‘์šฉ๊นŒ์ง€ ์‹ค๋ฌด์— ๋ฐ”๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์‹ฌํ™” ํ™œ์šฉ๋ฒ•์„ ๋ธ”๋ฃจ๊ฐ€ ์ž์„ธํžˆ ์•Œ๋ ค๋“œ๋ ค์š”.

19๋ถ„
๋‹จ์–ด: 1,783๊ฐœ
๊ฒŒ์‹œ๊ธ€ ์ธ๋„ค์ผ
์ •๋ณด

๐Ÿค– ์ด ํฌ์ŠคํŒ…์€ Gemini 2.5 Flash AI๊ฐ€ ์ž‘์„ฑํ–ˆ์–ด์š”.
๋‚ด์šฉ์˜ ์ •ํ™•์„ฑ์„ ์œ„ํ•ด ๊ฒ€ํ† ๋ฅผ ๊ฑฐ์ณค์ง€๋งŒ, ์‹ค๋ฌด ์ ์šฉ ์ „ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ํ•จ๊ป˜ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.

์œ ์šฉํ•œ ํŒ

์ด ๊ธ€์—์„œ๋Š” CSS ๋ณ€์ˆ˜(Custom Properties)์˜ ํ•ต์‹ฌ ๊ฐœ๋…๋ถ€ํ„ฐ ๋™์  ํ…Œ๋งˆ ๊ตฌํ˜„, ์Šค์ฝ”ํ•‘ ์ „๋žต, ๊ทธ๋ฆฌ๊ณ  JavaScript๋ฅผ ํ™œ์šฉํ•œ ์ƒํ˜ธ์ž‘์šฉ๊นŒ์ง€ ์‹ค๋ฌด์— ํ•„์š”ํ•œ ๋ชจ๋“  ๊ฒƒ์„ ์‹ฌ๋„ ์žˆ๊ฒŒ ๋‹ค๋ค„๋ณผ๊ฒŒ์š”.

์•ˆ๋…•ํ•˜์„ธ์š”, 10๋…„ ์ด์ƒ ๊ฒฝ๋ ฅ์˜ ์‹œ๋‹ˆ์–ด ํ’€์Šคํƒ ๊ฐœ๋ฐœ์ž์ด์ž ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ SEO ์ „๋ฌธ๊ฐ€ ๋ธ”๋ฃจ์˜ˆ์š”. ์ €๋Š” ์‹ค์ œ ์กด์žฌํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋Š” ์•„๋‹ˆ์ง€๋งŒ, ์—ฌ๋Ÿฌ๋ถ„์˜ ์„ฑ์žฅ์„ ๋•๊ธฐ ์œ„ํ•ด ์‹ค๋ฌด ๊ฒฝํ—˜์„ ๋ฐ”ํƒ•์œผ๋กœ ์œ ์šฉํ•œ ์ •๋ณด๋ฅผ ๊ณต์œ ํ•ด ๋“œ๋ฆฌ๊ณ  ์žˆ์–ด์š”.

์˜ค๋Š˜์€ ํ”„๋ŸฐํŠธ์—”๋“œ ๊ฐœ๋ฐœ์˜ ์ƒ์‚ฐ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ค๋Š” **CSS ๋ณ€์ˆ˜(Custom Properties)**์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๊ฒŒ ๋‹ค๋ค„๋ณด๋ ค๊ณ  ํ•ด์š”. ๋‹จ์ˆœํ•œ ์ƒ์ˆ˜๋ฅผ ๋„˜์–ด ๋™์ ์ธ ์Šคํƒ€์ผ๋ง๊ณผ ํšจ์œจ์ ์ธ ํ…Œ๋งˆ ๊ด€๋ฆฌ๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” CSS ๋ณ€์ˆ˜์˜ ์ง„์ •ํ•œ ๊ฐ€์น˜๋ฅผ ํ•จ๊ป˜ ํƒ๊ตฌํ•ด ๋ด์š”.

๐Ÿค” CSS ๋ณ€์ˆ˜, ์™œ ๋‹ค์‹œ ์ฃผ๋ชฉํ•ด์•ผ ํ• ๊นŒ์š”?

0๏ธโƒฃ ๊ธฐ์กด CSS ๊ด€๋ฆฌ์˜ ์–ด๋ ค์›€ ๐Ÿคฏ

์—ฌ๋Ÿฌ๋ถ„์€ CSS๋ฅผ ์ž‘์„ฑํ•˜๋ฉด์„œ ํŠน์ • ์ƒ‰์ƒ์ด๋‚˜ ์—ฌ๋ฐฑ ๊ฐ’์„ ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋‹ค๊ฐ€, ๋‚˜์ค‘์— ๊ทธ ๊ฐ’์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•  ๋•Œ๋งˆ๋‹ค ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ์ฐพ์•„ ์ˆ˜์ •ํ•˜๋А๋ผ ๊ณ ์ƒํ–ˆ๋˜ ๊ฒฝํ—˜์ด ์žˆ์œผ์‹ค ๊ฑฐ์˜ˆ์š”. ์ด๋Ÿฐ ๋ฐฉ์‹์€ ๊ฐœ๋ฐœ ์‹œ๊ฐ„์„ ๋Š˜๋ฆฌ๊ณ , ํœด๋จผ ์—๋Ÿฌ์˜ ๊ฐ€๋Šฅ์„ฑ์„ ๋†’์ด๋ฉฐ, ์ฝ”๋“œ์˜ ์ผ๊ด€์„ฑ์„ ํ•ด์น˜๋Š” ์ฃผ๋ฒ”์ด ๋˜๊ณค ํ•ด์š”.

ํŠนํžˆ, ์›น์‚ฌ์ดํŠธ์˜ ํ…Œ๋งˆ(๋‹คํฌ ๋ชจ๋“œ, ๋ผ์ดํŠธ ๋ชจ๋“œ ๋“ฑ)๋ฅผ ๋ณ€๊ฒฝํ•ด์•ผ ํ•  ๋•Œ๋งˆ๋‹ค CSS ํŒŒ์ผ ์ „์ฒด๋ฅผ ๋ณต์‚ฌํ•˜๊ฑฐ๋‚˜ ๋ณต์žกํ•œ SCSS ๋ณ€์ˆ˜ ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ๋˜ ๊ธฐ์–ต๋„ ์žˆ์œผ์‹ค ๊ฑฐ์˜ˆ์š”. ์ด๋Ÿฐ ์ ‘๊ทผ ๋ฐฉ์‹์€ ํ™•์žฅ์„ฑ์ด ๋–จ์–ด์ง€๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๋งค์šฐ ์–ด๋ ค์›Œ์š”.

1๏ธโƒฃ CSS ๋ณ€์ˆ˜์˜ ๋“ฑ์žฅ๊ณผ ํ•ต์‹ฌ ์ด์  โœจ

CSS ๋ณ€์ˆ˜, ๋˜๋Š” ๊ณต์‹ ๋ช…์นญ์ธ Custom Properties๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ–ˆ์–ด์š”. CSS ๋ณ€์ˆ˜๋Š” CSS ๋‚ด์—์„œ ๊ฐ’์„ ์ •์˜ํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์˜ˆ์š”. ๋งˆ์น˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ ๋ณ€์ˆ˜์ฒ˜๋Ÿผ, ํ•œ ๋ฒˆ ์ •์˜ํ•ด๋‘๋ฉด ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๊ณ , ํ•„์š”์— ๋”ฐ๋ผ ๊ฐ’์„ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์–ด์š”.

์ •๋ณด

CSS ๋ณ€์ˆ˜์˜ ํ•ต์‹ฌ ์ด์ 

  • ์žฌ์‚ฌ์šฉ์„ฑ: ๋ฐ˜๋ณต๋˜๋Š” ๊ฐ’์„ ํ•œ ๊ณณ์— ์ •์˜ํ•˜์—ฌ ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ์œ ์ง€๋ณด์ˆ˜์„ฑ: ๊ฐ’ ๋ณ€๊ฒฝ ์‹œ ํ•œ ๊ณณ๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ๋˜๋ฏ€๋กœ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๋งค์šฐ ์‰ฌ์›Œ์ ธ์š”.
  • ๋™์  ์ œ์–ด: JavaScript๋ฅผ ํ†ตํ•ด ๋Ÿฐํƒ€์ž„์— ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜์—ฌ ๋™์ ์ธ ์Šคํƒ€์ผ๋ง์ด ๊ฐ€๋Šฅํ•ด์š”.
  • ์Šค์ฝ”ํ•‘: ์บ์Šค์ผ€์ด๋”ฉ ๊ทœ์น™์„ ๋”ฐ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ „์—ญ ๋ฐ ์ง€์—ญ ์Šค์ฝ”ํ”„๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.

์ด๋Ÿฌํ•œ ์ด์  ๋•๋ถ„์— CSS ๋ณ€์ˆ˜๋Š” ์ผ๊ด€๋œ ๋””์ž์ธ ์‹œ์Šคํ…œ ๊ตฌ์ถ•, ํšจ์œจ์ ์ธ ํ…Œ๋งˆ ๊ด€๋ฆฌ, ๊ทธ๋ฆฌ๊ณ  JavaScript์™€์˜ ์œ ๊ธฐ์ ์ธ ์ƒํ˜ธ์ž‘์šฉ์„ ํ†ตํ•œ ๋™์  UI ๊ตฌํ˜„์— ํ•„์ˆ˜์ ์ธ ์š”์†Œ๋กœ ์ž๋ฆฌ ์žก์•˜์–ด์š”.

โš™๏ธ CSS ๋ณ€์ˆ˜ ์‹ฌํ™” ํ™œ์šฉ ์ „๋žต

0๏ธโƒฃ ์ „์—ญ/์ง€์—ญ ์Šค์ฝ”ํ•‘๊ณผ ์บ์Šค์ผ€์ด๋”ฉ์˜ ์ดํ•ด ๐ŸŒ

CSS ๋ณ€์ˆ˜๋Š” CSS์˜ ๊ธฐ๋ณธ ์›๋ฆฌ์ธ ์บ์Šค์ผ€์ด๋”ฉ(Cascading)์„ ๊ทธ๋Œ€๋กœ ๋”ฐ๋ผ์š”. ์ด๋Š” ๋ณ€์ˆ˜๊ฐ€ ์„ ์–ธ๋œ ์œ„์น˜์— ๋”ฐ๋ผ ์œ ํšจ ๋ฒ”์œ„(์Šค์ฝ”ํ”„)๊ฐ€ ๊ฒฐ์ •๋œ๋‹ค๋Š” ์˜๋ฏธ์˜ˆ์š”.

๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์€ :root ์˜์‚ฌ ํด๋ž˜์Šค์— ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜์—ฌ ์ „์—ญ ๋ณ€์ˆ˜๋กœ ๋งŒ๋“œ๋Š” ๊ฑฐ์˜ˆ์š”. :root๋Š” ๋ฌธ์„œ์˜ ์ตœ์ƒ์œ„ ์š”์†Œ์ธ <html>์„ ์˜๋ฏธํ•˜๋ฉฐ, ์—ฌ๊ธฐ์— ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ๋ฌธ์„œ ์ „์ฒด์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด์š”.

:root { --primary-color: #007bff; /* ์ „์—ญ ๊ธฐ๋ณธ ์ƒ‰์ƒ */ --secondary-color: #6c757d; /* ์ „์—ญ ๋ณด์กฐ ์ƒ‰์ƒ */ --spacing-unit: 8px; /* ์ „์—ญ ์—ฌ๋ฐฑ ๋‹จ์œ„ */ } body { color: var(--primary-color); margin: var(--spacing-unit); }

ํŠน์ • ์š”์†Œ๋‚˜ ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋ฉด, ํ•ด๋‹น ๋ณ€์ˆ˜๋Š” ๊ทธ ์š”์†Œ์™€ ๊ทธ ์ž์†์—๊ฒŒ๋งŒ ์œ ํšจํ•œ ์ง€์—ญ ๋ณ€์ˆ˜๊ฐ€ ๋ผ์š”. ์ด ์ง€์—ญ ๋ณ€์ˆ˜๋Š” ์ „์—ญ ๋ณ€์ˆ˜์™€ ์ด๋ฆ„์ด ๊ฐ™๋”๋ผ๋„ ์ง€์—ญ ์Šค์ฝ”ํ”„ ๋‚ด์—์„œ ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œ(์žฌ์ •์˜)ํ•  ์ˆ˜ ์žˆ์–ด์š”.

.card { --primary-color: #28a745; /* .card ๋‚ด๋ถ€์—์„œ๋งŒ ์ ์šฉ๋˜๋Š” ์ง€์—ญ ์ƒ‰์ƒ */ border: 1px solid var(--primary-color); padding: calc(var(--spacing-unit) * 2); } .card h2 { color: var(--primary-color); /* .card ๋‚ด๋ถ€์˜ primary-color ์ ์šฉ */ } .footer { /* .card ์™ธ๋ถ€์ด๋ฏ€๋กœ ์ „์—ญ primary-color๊ฐ€ ์ ์šฉ */ background-color: var(--primary-color); }

์ด์ฒ˜๋Ÿผ ์บ์Šค์ผ€์ด๋”ฉ ์›๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๋ฉด ๋ณ€์ˆ˜์˜ ์šฐ์„ ์ˆœ์œ„์™€ ์œ ํšจ ๋ฒ”์œ„๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ƒ์œ„ ์š”์†Œ์— ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” ํ•˜์œ„ ์š”์†Œ์— ์ƒ์†๋˜์ง€๋งŒ, ํ•˜์œ„ ์š”์†Œ์—์„œ ๊ฐ™์€ ์ด๋ฆ„์˜ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋ฉด ํ•ด๋‹น ์ง€์—ญ์—์„œ๋งŒ ์ƒˆ๋กœ์šด ๊ฐ’์ด ์ ์šฉ๋˜๋Š” ๋ฐฉ์‹์ด์—์š”.

1๏ธโƒฃ ๋™์  ํ…Œ๋งˆ ๊ตฌํ˜„ ๋งˆ์Šคํ„ฐํ•˜๊ธฐ ๐ŸŽจ

CSS ๋ณ€์ˆ˜์˜ ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ ํ™œ์šฉ ์‚ฌ๋ก€ ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐ”๋กœ ๋™์  ํ…Œ๋งˆ(Dynamic Theming) ๊ตฌํ˜„์ด์—์š”. ๋‹คํฌ ๋ชจ๋“œ, ๋ผ์ดํŠธ ๋ชจ๋“œ, ํ˜น์€ ์‚ฌ์šฉ์ž ์ •์˜ ํ…Œ๋งˆ๋ฅผ JavaScript ์—†์ด, ํ˜น์€ ์ตœ์†Œํ•œ์˜ JavaScript๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”.

ํ•ต์‹ฌ ์•„์ด๋””์–ด๋Š” :root์— ํ…Œ๋งˆ ๊ด€๋ จ ๋ณ€์ˆ˜๋“ค์„ ์ •์˜ํ•˜๊ณ , JavaScript๋ฅผ ์ด์šฉํ•ด :root ์š”์†Œ์˜ ํŠน์ • CSS ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฑฐ์˜ˆ์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ชจ๋“  ํ•˜์œ„ ์š”์†Œ์˜ ์Šคํƒ€์ผ์ด ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ๋ผ์š”.

:root { --bg-color: #ffffff; --text-color: #333333; --border-color: #dddddd; } /* ๋‹คํฌ ๋ชจ๋“œ ํด๋ž˜์Šค๊ฐ€ body์— ์ถ”๊ฐ€๋  ๋•Œ ๋ณ€์ˆ˜ ์˜ค๋ฒ„๋ผ์ด๋“œ */ body.dark-theme { --bg-color: #333333; --text-color: #f0f0f0; --border-color: #555555; } body { background-color: var(--bg-color); color: var(--text-color); transition: background-color 0.3s ease, color 0.3s ease; } .container { border: 1px solid var(--border-color); padding: 20px; }

JavaScript์—์„œ๋Š” document.documentElement (์ฆ‰, <html> ์š”์†Œ)์˜ ํด๋ž˜์Šค๋ฅผ ํ† ๊ธ€ํ•˜๊ฑฐ๋‚˜, ์ง์ ‘ setProperty๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€์ˆ˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์–ด์š”.

2๏ธโƒฃ JavaScript์™€ CSS ๋ณ€์ˆ˜์˜ ๊ฐ•๋ ฅํ•œ ์‹œ๋„ˆ์ง€ โœจ

CSS ๋ณ€์ˆ˜๋Š” JavaScript์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋  ๋•Œ ๊ทธ ์ง„๊ฐ€๋ฅผ ๋ฐœํœ˜ํ•ด์š”. JavaScript๋ฅผ ํ†ตํ•ด CSS ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์ฝ๊ฑฐ๋‚˜ ์„ค์ •ํ•จ์œผ๋กœ์จ, ๋Ÿฐํƒ€์ž„์— ๋™์ ์œผ๋กœ UI๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์–ด์š”.

๊ฐ’ ์ฝ๊ธฐ: ํŠน์ • ์š”์†Œ์— ์ ์šฉ๋œ CSS ๋ณ€์ˆ˜ ๊ฐ’์„ ์ฝ์œผ๋ ค๋ฉด window.getComputedStyle() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์š”. ์ด ๋ฉ”์„œ๋“œ๋Š” ์š”์†Œ์— ์ตœ์ข…์ ์œผ๋กœ ๊ณ„์‚ฐ๋œ ๋ชจ๋“  ์Šคํƒ€์ผ์„ ํฌํ•จํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, getPropertyValue()๋กœ ํŠน์ • ๋ณ€์ˆ˜ ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์–ด์š”.

const rootStyles = getComputedStyle(document.documentElement); const primaryColor = rootStyles.getPropertyValue('--primary-color'); console.log('ํ˜„์žฌ primary-color:', primaryColor.trim()); // ๊ณต๋ฐฑ ์ œ๊ฑฐ const myElement = document.getElementById('my-element'); const elementStyles = getComputedStyle(myElement); const elementBgColor = elementStyles.getPropertyValue('--bg-color'); console.log('my-element์˜ ๋ฐฐ๊ฒฝ์ƒ‰:', elementBgColor.trim());

๊ฐ’ ์„ค์ •: ์š”์†Œ์˜ CSS ๋ณ€์ˆ˜ ๊ฐ’์„ ์„ค์ •ํ•˜๋ ค๋ฉด element.style.setProperty() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์š”. ์ด๋Š” ์ธ๋ผ์ธ ์Šคํƒ€์ผ๋กœ ์ ์šฉ๋˜๋ฏ€๋กœ, ์บ์Šค์ผ€์ด๋”ฉ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์•„์š”.

const myElement = document.getElementById('my-element'); // ํŠน์ • ์š”์†Œ์˜ CSS ๋ณ€์ˆ˜ ๋ณ€๊ฒฝ myElement.style.setProperty('--item-color', 'purple'); // `:root` (<html>) ์š”์†Œ์˜ CSS ๋ณ€์ˆ˜ ๋ณ€๊ฒฝ document.documentElement.style.setProperty('--primary-color', '#ff6347');

์ด๋Ÿฌํ•œ ์ƒํ˜ธ์ž‘์šฉ์€ ์‚ฌ์šฉ์ž์˜ ์ธํ„ฐ๋ž™์…˜์— ๋”ฐ๋ผ ์‹ค์‹œ๊ฐ„์œผ๋กœ UI์˜ ์ƒ‰์ƒ, ํฌ๊ธฐ, ์œ„์น˜ ๋“ฑ์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋Š” ๋ณต์žกํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋งค์šฐ ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉ๋  ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์Šฌ๋ผ์ด๋” ๊ฐ’์— ๋”ฐ๋ผ ์š”์†Œ์˜ ๋„ˆ๋น„๋ฅผ ์กฐ์ ˆํ•˜๊ฑฐ๋‚˜, ํŠน์ • ์ด๋ฒคํŠธ์— ๋”ฐ๋ผ ๋ฒ„ํŠผ์˜ ์ƒ‰์ƒ์„ ๋ณ€๊ฒฝํ•˜๋Š” ๋“ฑ์˜ ๋™์ ์ธ ํšจ๊ณผ๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿงช ์‹ค์ „ ์ฝ”๋“œ ์˜ˆ์‹œ

์ด์ œ ์‹ค์ œ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด CSS ๋ณ€์ˆ˜์˜ ํ™œ์šฉ๋ฒ•์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณผ๊ฒŒ์š”.

0๏ธโƒฃ ๊ธฐ๋ณธ ํ…Œ๋งˆ ์„ค์ • ๋ฐ ์ง€์—ญ ๋ณ€์ˆ˜ ์˜ค๋ฒ„๋ผ์ด๋“œ ๐Ÿง‘โ€๐Ÿ’ป

๋จผ์ €, ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜๊ณ  ํŠน์ • ์ปดํฌ๋„ŒํŠธ์—์„œ ์ด๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜๋Š” ์˜ˆ์‹œ์˜ˆ์š”. .card ์š”์†Œ ๋‚ด์—์„œ --card-bg ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•˜๊ณ , h2 ์š”์†Œ์˜ ์ƒ‰์ƒ์„ ๋ณ€๊ฒฝํ•ด๋ณผ๊ฒŒ์š”.

<div class="container"> <h1>๋ธ”๋ฃจ์˜ CSS ๋ณ€์ˆ˜ ์‹ฌํ™” ๊ฐ€์ด๋“œ</h1> <p>์ „์—ญ ๋ณ€์ˆ˜ `--primary-color`๋Š” ์ด ๊ธ€์˜ ๊ธฐ๋ณธ ์ƒ‰์ƒ์œผ๋กœ ์‚ฌ์šฉ๋ผ์š”.</p> <div class="card"> <h2>์นด๋“œ ์ œ๋ชฉ</h2> <p>์ด ์นด๋“œ๋Š” ์ง€์—ญ ๋ณ€์ˆ˜ `--card-bg`๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐฐ๊ฒฝ์ƒ‰์ด ๋‹ฌ๋ผ์š”.</p> <button>์ž์„ธํžˆ ๋ณด๊ธฐ</button> </div> <div class="another-element"> <p>์ด ์š”์†Œ๋Š” ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์š”.</p> </div> </div>
:root { --primary-color: #007bff; --text-color: #333; --bg-color: #f8f9fa; --border-radius: 8px; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 20px; background-color: var(--bg-color); color: var(--text-color); } h1 { color: var(--primary-color); } .card { --card-bg: #e2f0cb; /* ์ง€์—ญ ๋ณ€์ˆ˜ ์„ ์–ธ */ --card-text: #2c3e50; background-color: var(--card-bg); color: var(--card-text); border-radius: var(--border-radius); padding: 20px; margin-top: 30px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } .card h2 { color: var(--primary-text-color, #0056b3); /* ํด๋ฐฑ ๊ฐ’ ์‚ฌ์šฉ */ /* `--primary-text-color`๊ฐ€ ์ •์˜๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด `#0056b3`๋ฅผ ์‚ฌ์šฉํ•ด์š”. */ } .another-element { background-color: var(--primary-color); color: white; padding: 15px; margin-top: 20px; border-radius: var(--border-radius); } button { background-color: var(--primary-color); color: white; padding: 10px 15px; border: none; border-radius: 5px; cursor: pointer; transition: background-color 0.3s ease; } button:hover { background-color: #0056b3; }

์œ„ ์ฝ”๋“œ์—์„œ .card h2์— var(--primary-text-color, #0056b3)์™€ ๊ฐ™์ด ํด๋ฐฑ(fallback) ๊ฐ’์„ ์ง€์ •ํ•œ ๊ฒƒ์„ ๋ณด์‹ค ์ˆ˜ ์žˆ์–ด์š”. ์ด๋Š” --primary-text-color ๋ณ€์ˆ˜๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์ง€ ์•Š์„ ๊ฒฝ์šฐ #0056b3๋ฅผ ์‚ฌ์šฉํ•˜๋ผ๋Š” ์˜๋ฏธ์˜ˆ์š”. ๋ณ€์ˆ˜ ์‚ฌ์šฉ์˜ ์•ˆ์ •์„ฑ์„ ๋†’์ด๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ž๋‹ˆ๋‹ค.

1๏ธโƒฃ JavaScript๋กœ ๋‹คํฌ/๋ผ์ดํŠธ ๋ชจ๋“œ ์ „ํ™˜ ๊ตฌํ˜„ ๐ŸŒ™โ˜€๏ธ

์ด๋ฒˆ์—๋Š” ๋ฒ„ํŠผ ํด๋ฆญ์œผ๋กœ ์›น์‚ฌ์ดํŠธ์˜ ํ…Œ๋งˆ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์˜ˆ์‹œ๋ฅผ ๋ณด์—ฌ๋“œ๋ฆด๊ฒŒ์š”. HTML์— ํ† ๊ธ€ ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€ํ•˜๊ณ , JavaScript๋กœ body ์š”์†Œ์— dark-theme ํด๋ž˜์Šค๋ฅผ ํ† ๊ธ€ํ•˜๋Š” ๋ฐฉ์‹์ด์—์š”.

<div class="theme-switcher"> <button id="theme-toggle">ํ…Œ๋งˆ ํ† ๊ธ€ (ํ˜„์žฌ: ๋ผ์ดํŠธ)</button> </div> <div class="content"> <p>์ด๊ณณ์˜ ํ…์ŠคํŠธ๋Š” ํ…Œ๋งˆ์— ๋”ฐ๋ผ ์ƒ‰์ƒ์ด ๋ณ€ํ•ด์š”.</p> <div class="box"> <h3>๋ฐ•์Šค ์ œ๋ชฉ</h3> <p>๋ฐ•์Šค์˜ ๋ฐฐ๊ฒฝ์ƒ‰๊ณผ ํ…์ŠคํŠธ ์ƒ‰์ƒ๋„ ํ•จ๊ป˜ ๋ณ€ํ•ด์š”.</p> </div> </div>
:root { --page-bg: #ffffff; --page-text: #222222; --box-bg: #f0f0f0; --box-text: #333333; --button-bg: #007bff; --button-text: #ffffff; } body.dark-theme { --page-bg: #222222; --page-text: #ffffff; --box-bg: #333333; --box-text: #f0f0f0; --button-bg: #6c757d; --button-text: #ffffff; } body { background-color: var(--page-bg); color: var(--page-text); transition: background-color 0.3s ease, color 0.3s ease; margin: 0; padding: 20px; min-height: 100vh; display: flex; flex-direction: column; align-items: center; } .theme-switcher { margin-bottom: 20px; } .content { text-align: center; max-width: 600px; width: 100%; } .box { background-color: var(--box-bg); color: var(--box-text); padding: 20px; border-radius: 10px; margin-top: 20px; transition: background-color 0.3s ease, color 0.3s ease; } #theme-toggle { background-color: var(--button-bg); color: var(--button-text); padding: 10px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 1rem; transition: background-color 0.3s ease; } #theme-toggle:hover { opacity: 0.9; }
document.addEventListener('DOMContentLoaded', () => { const themeToggleBtn = document.getElementById('theme-toggle'); const body = document.body; // ๋กœ์ปฌ ์Šคํ† ๋ฆฌ์ง€์—์„œ ์ €์žฅ๋œ ํ…Œ๋งˆ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ const savedTheme = localStorage.getItem('theme') || 'light'; if (savedTheme === 'dark') { body.classList.add('dark-theme'); themeToggleBtn.textContent = 'ํ…Œ๋งˆ ํ† ๊ธ€ (ํ˜„์žฌ: ๋‹คํฌ)'; } else { themeToggleBtn.textContent = 'ํ…Œ๋งˆ ํ† ๊ธ€ (ํ˜„์žฌ: ๋ผ์ดํŠธ)'; } themeToggleBtn.addEventListener('click', () => { if (body.classList.contains('dark-theme')) { body.classList.remove('dark-theme'); localStorage.setItem('theme', 'light'); themeToggleBtn.textContent = 'ํ…Œ๋งˆ ํ† ๊ธ€ (ํ˜„์žฌ: ๋ผ์ดํŠธ)'; } else { body.classList.add('dark-theme'); localStorage.setItem('theme', 'dark'); themeToggleBtn.textContent = 'ํ…Œ๋งˆ ํ† ๊ธ€ (ํ˜„์žฌ: ๋‹คํฌ)'; } }); });

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

2๏ธโƒฃ ๋Ÿฐํƒ€์ž„์— ๋™์ ์œผ๋กœ ์Šคํƒ€์ผ ๋ณ€๊ฒฝํ•˜๊ธฐ โš™๏ธ

๋งˆ์ง€๋ง‰์œผ๋กœ JavaScript๋ฅผ ์ด์šฉํ•ด ๋Ÿฐํƒ€์ž„์— CSS ๋ณ€์ˆ˜๋ฅผ ๋™์ ์œผ๋กœ ์ œ์–ดํ•˜๋Š” ์˜ˆ์‹œ์˜ˆ์š”. ์Šฌ๋ผ์ด๋” ๊ฐ’์„ ์กฐ์ ˆํ•˜์—ฌ ๋ฐ•์Šค์˜ ๋„ˆ๋น„๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€๊ฒฝํ•ด๋ณผ๊ฒŒ์š”.

<div class="dynamic-control"> <label for="width-slider">๋ฐ•์Šค ๋„ˆ๋น„ ์กฐ์ ˆ:</label> <input type="range" id="width-slider" min="50" max="300" value="150"> </div> <div id="dynamic-box" class="resizable-box"> <p>์ด ๋ฐ•์Šค์˜ ๋„ˆ๋น„๋Š” ์Šฌ๋ผ์ด๋”๋กœ ์กฐ์ ˆ๋ผ์š”.</p> </div>
.resizable-box { --box-width: 150px; /* ์ดˆ๊ธฐ ๋„ˆ๋น„ */ width: var(--box-width); height: 100px; background-color: #ffda63; border: 2px solid #e0b000; border-radius: 8px; display: flex; justify-content: center; align-items: center; margin-top: 20px; transition: width 0.1s ease-out; /* ๋ถ€๋“œ๋Ÿฌ์šด ์ „ํ™˜ ํšจ๊ณผ */ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .dynamic-control { margin-top: 30px; display: flex; align-items: center; gap: 10px; } input[type="range"] { width: 200px; }
document.addEventListener('DOMContentLoaded', () => { const widthSlider = document.getElementById('width-slider'); const dynamicBox = document.getElementById('dynamic-box'); // ์ดˆ๊ธฐ ๊ฐ’ ์„ค์ • dynamicBox.style.setProperty('--box-width', `${widthSlider.value}px`); widthSlider.addEventListener('input', (event) => { const newWidth = event.target.value; dynamicBox.style.setProperty('--box-width', `${newWidth}px`); }); });

์ด์ฒ˜๋Ÿผ setProperty๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์ด๋‚˜ ๋‹ค๋ฅธ ๋กœ์ง์— ๋”ฐ๋ผ CSS ๋ณ€์ˆ˜ ๊ฐ’์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ๋งค์šฐ ๋™์ ์ธ UI๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋Š” CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด๋„ ๊ฐ•๋ ฅํ•œ ๋™์  ์Šคํƒ€์ผ๋ง์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ค€๋‹ต๋‹ˆ๋‹ค.

๐Ÿ“ ์ •๋ฆฌํ•˜๋ฉฐ

0๏ธโƒฃ ํ•ต์‹ฌ ์š”์•ฝ ๋ฐ ์‹ค๋ฌด ํŒ ๐Ÿš€

์˜ค๋Š˜ ์šฐ๋ฆฌ๋Š” CSS ๋ณ€์ˆ˜(Custom Properties)๊ฐ€ ๋‹จ์ˆœํ•œ ์ƒ์ˆ˜๋ฅผ ๋„˜์–ด, ํ˜„๋Œ€ ์›น ๊ฐœ๋ฐœ์—์„œ ์–ผ๋งˆ๋‚˜ ๊ฐ•๋ ฅํ•˜๊ณ  ์œ ์—ฐํ•œ ๋„๊ตฌ์ธ์ง€ ์‚ดํŽด๋ณด์•˜์–ด์š”. ์บ์Šค์ผ€์ด๋”ฉ์„ ๋”ฐ๋ฅด๋Š” ์Šค์ฝ”ํ•‘ ๋•๋ถ„์— ์ „์—ญ/์ง€์—ญ ์Šคํƒ€์ผ์„ ์ฒด๊ณ„์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , JavaScript์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ํ†ตํ•ด ๋™์ ์ธ ํ…Œ๋งˆ ๋ณ€๊ฒฝ ๋ฐ ์‹ค์‹œ๊ฐ„ UI ์กฐ์ž‘์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค๋Š” ์ ์ด ํ•ต์‹ฌ์ด์—์š”.

์‹ค๋ฌด์—์„œ CSS ๋ณ€์ˆ˜๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ํŒ:

  • ๋””์ž์ธ ํ† ํฐ์œผ๋กœ ํ™œ์šฉ: ์ƒ‰์ƒ, ํฐํŠธ ํฌ๊ธฐ, ์—ฌ๋ฐฑ ๋“ฑ ๋””์ž์ธ ์‹œ์Šคํ…œ์˜ ํ•ต์‹ฌ ๊ฐ’์„ CSS ๋ณ€์ˆ˜๋กœ ์ •์˜ํ•˜๋ฉด ์ผ๊ด€๋œ UI๋ฅผ ์‰ฝ๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ํด๋ฐฑ(Fallback) ๊ฐ’ ํ™œ์šฉ: var(--my-variable, #fallback-value)์™€ ๊ฐ™์ด ํด๋ฐฑ ๊ฐ’์„ ์ง€์ •ํ•˜์—ฌ ๋ณ€์ˆ˜๊ฐ€ ์ •์˜๋˜์ง€ ์•Š์•˜์„ ๋•Œ์˜ ์•ˆ์ •์„ฑ์„ ํ™•๋ณดํ•˜์„ธ์š”.
  • ์˜๋ฏธ ์žˆ๋Š” ์ด๋ฆ„: ๋ณ€์ˆ˜ ์ด๋ฆ„์€ --primary-color์ฒ˜๋Ÿผ ์˜๋ฏธ๋ฅผ ๋ช…ํ™•ํžˆ ๋‹ด์•„์„œ ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๋“ค๋„ ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ์„ธ์š”.
  • ๋””๋ฒ„๊น…: ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์—์„œ ์š”์†Œ์˜ Computed ํƒญ์„ ํ†ตํ•ด ์–ด๋–ค ๋ณ€์ˆ˜ ๊ฐ’์ด ์ตœ์ข…์ ์œผ๋กœ ์ ์šฉ๋˜์—ˆ๋Š”์ง€ ์‰ฝ๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

1๏ธโƒฃ ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๋‚˜์•„๊ฐ€๊ธฐ ๐Ÿ’ก

CSS ๋ณ€์ˆ˜๋Š” ์ด์ œ ํ”„๋ŸฐํŠธ์—”๋“œ ๊ฐœ๋ฐœ์˜ ํ•„์ˆ˜์ ์ธ ๋ถ€๋ถ„์ด ๋˜์—ˆ์–ด์š”. ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ์— CSS ๋ณ€์ˆ˜๋ฅผ ์ ๊ทน์ ์œผ๋กœ ๋„์ž…ํ•˜์—ฌ ๋” ํšจ์œจ์ ์ด๊ณ  ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฌ์šด ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด๋‚˜๊ฐ€์‹œ๊ธธ ๋ฐ”๋ผ์š”.

๋” ๋‚˜์•„๊ฐ€, CSS ๋ณ€์ˆ˜๋ฅผ ํ™œ์šฉํ•˜์—ฌ Storybook๊ณผ ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๋™์ ์œผ๋กœ ํ…Œ๋งˆ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜, CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(Styled Components, Emotion ๋“ฑ)์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์—ฌ ๋”์šฑ ๊ฐ•๋ ฅํ•œ ์Šคํƒ€์ผ๋ง ๊ฒฝํ—˜์„ ๋งŒ๋“ค์–ด๋ณผ ์ˆ˜๋„ ์žˆ์–ด์š”. ๋ฌด๊ถ๋ฌด์ง„ํ•œ ๊ฐ€๋Šฅ์„ฑ์ด ์—ด๋ ค ์žˆ๋‹ต๋‹ˆ๋‹ค!

๐Ÿ“ฎ ์ฐธ๊ณ 

์—ฐ๊ด€๋œ ํฌ์ŠคํŠธ