CSS 변수 (Custom Properties) 활용


CSS 변수(Custom Properties)는 스타일시트 전체에서 재사용할 수 있는 값을 정의하는 기능입니다. JavaScript로 동적 제어가 가능하고, 테마 시스템 구축에 필수적인 기술입니다.



언제 사용하나요?



  • 다크모드/라이트모드 테마 구현

  • 일관된 디자인 시스템 구축

  • 반복되는 색상, 크기 값 관리

  • JavaScript와 CSS 간 값 공유



기본 문법


/* 변수 선언 (--로 시작) */
:root {
--primary-color: #3498db;
--secondary-color: #2ecc71;
--font-size-base: 16px;
--spacing-unit: 8px;
--border-radius: 4px;
--shadow: 0 2px 4px rgba(0,0,0,0.1);
}

/* 변수 사용 */
.button {
background-color: var(--primary-color);
padding: calc(var(--spacing-unit) * 2);
border-radius: var(--border-radius);
box-shadow: var(--shadow);
}

/* 기본값 지정 */
.card {
color: var(--text-color, #333);
}


다크모드 구현


/* 라이트 테마 (기본) */
:root {
--bg-color: #ffffff;
--text-color: #333333;
--card-bg: #f5f5f5;
--border-color: #e0e0e0;
}

/* 다크 테마 */
[data-theme="dark"] {
--bg-color: #1a1a1a;
--text-color: #f0f0f0;
--card-bg: #2d2d2d;
--border-color: #404040;
}

/* 시스템 설정 따르기 */
@media (prefers-color-scheme: dark) {
:root {
--bg-color: #1a1a1a;
--text-color: #f0f0f0;
}
}

/* 적용 */
body {
background-color: var(--bg-color);
color: var(--text-color);
}

.card {
background: var(--card-bg);
border: 1px solid var(--border-color);
}


JavaScript로 제어


// 변수 값 읽기
const root = document.documentElement;
const primaryColor = getComputedStyle(root)
.getPropertyValue("--primary-color");

// 변수 값 변경
root.style.setProperty("--primary-color", "#e74c3c");

// 테마 토글
function toggleTheme() {
const current = document.body.dataset.theme;
document.body.dataset.theme =
current === "dark" ? "light" : "dark";
localStorage.setItem("theme", document.body.dataset.theme);
}

// 저장된 테마 적용
document.body.dataset.theme =
localStorage.getItem("theme") || "light";


컴포넌트 스코프


/* 컴포넌트별 변수 오버라이드 */
.btn {
--btn-bg: var(--primary-color);
--btn-color: white;
--btn-padding: 10px 20px;

background: var(--btn-bg);
color: var(--btn-color);
padding: var(--btn-padding);
}

.btn--secondary {
--btn-bg: var(--secondary-color);
}

.btn--outline {
--btn-bg: transparent;
--btn-color: var(--primary-color);
}

.btn--large {
--btn-padding: 15px 30px;
}


디자인 토큰 시스템


:root {
/* 기본 색상 */
--color-blue-50: #eff6ff;
--color-blue-500: #3b82f6;
--color-blue-900: #1e3a8a;

/* 시맨틱 토큰 */
--color-primary: var(--color-blue-500);
--color-bg: var(--color-blue-50);

/* 타이포그래피 */
--font-xs: 0.75rem;
--font-sm: 0.875rem;
--font-base: 1rem;
--font-lg: 1.125rem;
--font-xl: 1.25rem;

/* 스페이싱 (4px 기반) */
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-4: 1rem;
--space-8: 2rem;

/* 브레이크포인트 참조용 */
--breakpoint-sm: 640px;
--breakpoint-md: 768px;
--breakpoint-lg: 1024px;
}


calc()와 함께 사용


.container {
--container-padding: 20px;
width: calc(100% - var(--container-padding) * 2);
padding: var(--container-padding);
}

.grid {
--gap: 16px;
--columns: 3;
display: grid;
gap: var(--gap);
grid-template-columns:
repeat(var(--columns), 1fr);
}

@media (max-width: 768px) {
.grid {
--columns: 2;
--gap: 12px;
}
}


애니메이션 변수


:root {
--transition-fast: 150ms;
--transition-normal: 300ms;
--transition-slow: 500ms;
--ease-out: cubic-bezier(0, 0, 0.2, 1);
}

.button {
transition: all var(--transition-normal) var(--ease-out);
}


브라우저 지원


모든 최신 브라우저 지원 (IE 미지원). IE 대응 시 PostCSS 플러그인 사용.