🎨 CSS · 디자인 시스템 · 테마

CSS 변수 (Custom Properties)
완전 정복 가이드

--primary-color: #4f46e5; — 단 한 줄.
색상·폰트·간격을 한 곳에서 관리하고, 다크모드도 3줄로 구현해요.

⏱️ 약 10분 📅 2026년 4월 🏷️ CSS · 디자인 시스템 👶 입문 난이도
① 개념

CSS 변수란 무엇인가요?

:root에 선언하고 var()로 불러쓰는 재사용 가능한 값들

CSS 변수(정식 명칭: CSS 커스텀 프로퍼티)는 CSS 파일 안에서 값을 변수처럼 저장하고 재사용하는 기능이에요. --변수명: 값; 형태로 선언하고, var(--변수명)으로 사용해요. JavaScript의 변수처럼, 한 번 선언해두면 여러 곳에서 불러써요.

가장 큰 장점은 유지보수예요. 사이트 메인 컬러를 바꾸고 싶다면 기존에는 CSS 파일에서 특정 색상값이 쓰인 곳을 전부 찾아서 바꿔야 했어요. CSS 변수를 쓰면 :root { --primary: #새색상; } 한 줄만 바꾸면 사이트 전체가 바뀌어요.

♻️

한 번 선언, 어디서나 사용

:root에 선언하면 HTML 전체에서 var()로 불러쓸 수 있어요. 색상, 폰트, 간격 등 모든 값에 적용 가능해요.

🔧

유지보수 1줄로 끝

변수 선언 한 줄만 바꾸면 그 변수를 쓰는 CSS 전체가 일괄 업데이트돼요. 찾기·바꾸기 없이도 일관성을 유지해요.

🌙

다크모드 3줄로 구현

@media (prefers-color-scheme: dark)에서 변수 값만 바꿔주면 전체 테마가 다크모드로 전환돼요.

JavaScript에서도 제어 가능

element.style.setProperty('--primary', '#ff0000')로 JS에서도 실시간으로 CSS 변수를 변경할 수 있어요.

💡

:root 란? HTML 문서의 최상위 요소(<html>)를 선택하는 CSS 의사 클래스예요. :root에 CSS 변수를 선언하면 문서 전체에서 접근 가능한 전역 변수가 돼요. 꼭 :root가 아니어도 되지만, 전역으로 쓰려면 :root에 선언하는 게 관행이에요.

✨ 바이브코더 TIP

AI에게 "내 사이트 CSS 변수 세트 만들어줘. 메인 색상은 파란색이고, 카드·버튼·텍스트에 쓸 변수도 포함해줘"라고 하면 완성된 :root 블록을 바로 받을 수 있어요.

이 페이지 ④ 만들어보기에서 색상 피커로 직접 변수 값을 바꿔보면서 개념을 익혀보세요.

② 활용 예시

CSS 변수 4가지 핵심 활용법

색상 팔레트부터 다크모드까지 — 실제 코드로 보는 활용법

/* 🎨 색상 팔레트 변수 */ :root { --primary: #4f46e5; --secondary: #7c3aed; --success: #16a34a; --danger: #dc2626; --neutral: #6b7280; }

색상 팔레트 관리

사이트에서 사용하는 모든 색상을 변수로 등록해요. 디자이너가 색상을 바꾸면 변수 값만 업데이트하면 돼요. 브랜드 색상이 일관되게 유지돼요.

/* 📏 폰트 크기 시스템 */ :root { --text-xs: 0.75rem; /* 12px */ --text-sm: 0.875rem; /* 14px */ --text-base: 1rem; /* 16px */ --text-lg: 1.125rem; /* 18px */ --text-xl: 1.25rem; /* 20px */ --text-2xl: 1.5rem; /* 24px */ }

폰트 크기 시스템

폰트 크기를 변수로 관리하면 타이포그래피 스케일이 일관돼요. 기본 폰트를 키우고 싶을 때 변수 하나만 바꾸면 비율이 그대로 유지돼요.

/* 📐 간격(Spacing) 시스템 */ :root { --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-6: 24px; --space-8: 32px; --space-12: 48px; --radius: 12px; }

간격 & 모서리 반경

여백과 padding 값을 변수로 통일하면 레이아웃이 일관돼요. --radius처럼 모서리 반경도 변수로 관리하면 전체 UI 느낌을 한 번에 변경할 수 있어요.

/* 🌙 다크모드 전환 */ :root { --bg: #ffffff; --text: #111827; --border: #e5e7eb; } @media (prefers-color-scheme: dark) { :root { --bg: #111827; --text: #f9fafb; --border: #374151; } }

자동 다크모드

라이트모드·다크모드에서 달라지는 값만 변수로 빼두면, @media 쿼리에서 변수만 덮어써요. 수십 개의 CSS 속성을 일일이 바꾸지 않아도 돼요.

var() fallback 값: var(--primary, #4f46e5)처럼 두 번째 인수로 기본값을 지정할 수 있어요. 변수가 정의되지 않았을 때 기본값이 사용돼서, 예상치 못한 스타일 깨짐을 방지해요.

③ 완성 코드

실전 테마 CSS 변수 완성 코드

복붙 후 색상만 바꾸면 내 사이트 전체 테마가 완성돼요

style.css — :root 블록
/* ═══════════════════════════════════════
   CSS 변수 테마 시스템
   복붙 후 색상값만 바꿔서 사용하세요.
═══════════════════════════════════════ */

:root {
  /* 🎨 브랜드 색상 */
  --primary:         #4f46e5;
  --primary-soft:    #eef2ff;
  --primary-border:  #c7d2fe;
  --secondary:       #7c3aed;

  /* ✅ 상태 색상 */
  --success:         #16a34a;
  --success-soft:    #f0fdf4;
  --warning:         #d97706;
  --warning-soft:    #fffbeb;
  --danger:          #dc2626;
  --danger-soft:     #fff1f2;

  /* ⚫ 회색 계열 */
  --gray-50:         #f9fafb;
  --gray-100:        #f3f4f6;
  --gray-200:        #e5e7eb;
  --gray-500:        #6b7280;
  --gray-700:        #374151;
  --gray-900:        #111827;

  /* 📏 타이포그래피 */
  --font-sans:  'Noto Sans KR', -apple-system, sans-serif;
  --font-mono:  'JetBrains Mono', monospace;
  --text-sm:    0.875rem;
  --text-base:  1rem;
  --text-lg:    1.125rem;
  --text-xl:    1.25rem;
  --text-2xl:   1.5rem;

  /* 📐 간격 & 레이아웃 */
  --radius:     12px;
  --radius-sm:  8px;
  --radius-full:9999px;
  --space-2:    8px;
  --space-4:    16px;
  --space-6:    24px;
  --space-8:    32px;

  /* 🌑 그림자 */
  --shadow-sm:  0 1px 3px rgba(0,0,0,.08);
  --shadow:     0 4px 12px rgba(0,0,0,.08);
  --shadow-lg:  0 8px 28px rgba(0,0,0,.10);
}

/* 🌙 다크모드 자동 전환 */
@media (prefers-color-scheme: dark) {
  :root {
    --gray-50:    #1f2937;
    --gray-100:   #374151;
    --gray-200:   #4b5563;
    --gray-900:   #f9fafb;
  }
}

/* 💡 사용 예시 */
.btn-primary {
  background: var(--primary);
  border-radius: var(--radius);
  padding: var(--space-2) var(--space-6);
  color: #fff;
  font-size: var(--text-base);
}
④ 만들어보기

인터랙티브 CSS 변수 데모

색상 피커로 --primary-color를 바꾸면 버튼·카드·텍스트가 실시간으로 변해요

:root 변수 제어판
10px
16px

카드 컴포넌트

위의 슬라이더와 색상 피커를 조작하면 이 카드의 상단 라인 색상, 모서리 반경, 텍스트 크기가 바뀌어요.

CSS 변수

CSS 변수로 테마를 한 번에 관리해요.

현재 적용된 변수:
💡

위 데모는 document.documentElement.style.setProperty('--변수명', '값')으로 JavaScript에서 CSS 변수를 실시간 변경하는 방법을 보여줘요. 이 기법으로 테마 전환, 다크모드 토글, 사용자 맞춤 설정 등을 구현할 수 있어요.

⑤ FAQ

자주 묻는 질문

CSS 변수 사용 시 가장 많이 헷갈리는 것들

인터넷 익스플로러(IE)에서도 작동하나요?

CSS 변수(Custom Properties)는 IE 11에서 지원되지 않아요. Edge, Chrome, Firefox, Safari 등 모든 현대 브라우저에서는 완벽하게 지원해요. 2024년 기준으로 IE 11의 전 세계 점유율은 0.5% 미만이고, 마이크로소프트도 2022년에 IE를 공식 종료했어요.

IE를 지원해야 하는 환경(기업용 인트라넷 등)이라면 CSS 변수를 쓰지 않거나, PostCSS의 postcss-custom-properties 플러그인으로 변수를 빌드 시 실제 값으로 변환할 수 있어요. 하지만 일반적인 웹사이트라면 IE는 신경 쓰지 않아도 돼요.

JavaScript에서 CSS 변수를 어떻게 변경하나요?

두 가지 방법이 있어요:

1. 전역 변수 변경 (문서 전체에 적용)
document.documentElement.style.setProperty('--primary', '#ff0000');

2. 특정 요소에만 변경
element.style.setProperty('--primary', '#ff0000');

반대로 현재 변수 값을 읽어오려면:
getComputedStyle(document.documentElement).getPropertyValue('--primary').trim();

이 기능을 활용하면 사용자가 테마 색상을 직접 고르는 기능, 다크모드 토글 버튼 등을 쉽게 구현할 수 있어요.

특정 컴포넌트에만 다른 변수 값을 적용할 수 있나요?

네! CSS 변수는 상속되기 때문에 특정 요소에서 변수를 덮어쓰면 그 요소와 자식들에게만 새 값이 적용돼요. 이걸 로컬 스코프(Local Scope)라고 해요.

예를 들어 .dark-section { --bg: #1e1e2e; --text: #fff; }로 선언하면, .dark-section 안의 요소들은 모두 어두운 배경색을 갖게 돼요.

이 방법으로 같은 컴포넌트(버튼, 카드)를 색상만 다르게 변형하는 것도 가능해요. .btn-danger { --primary: var(--danger); }처럼 변수끼리 연결할 수도 있어요.

CSS 변수가 상속되는 원리가 뭔가요?

CSS 변수는 일반 CSS 속성처럼 상속돼요. 부모 요소에 선언된 변수는 모든 자식 요소에서 var()로 접근할 수 있어요.

그래서 :root(= <html>)에 선언하면 페이지 전체에서 쓸 수 있는 전역 변수가 돼요. 특정 컴포넌트 안에서만 쓰고 싶으면 그 컴포넌트 클래스 선택자에 선언하면 돼요.

자식 요소에서 같은 이름의 변수를 재선언하면 부모 값을 덮어써요. 이 특성을 활용하면 컴포넌트별로 독립적인 스타일 시스템을 만들 수 있어요.

var()의 fallback(기본값)은 어떻게 사용하나요?

var(--변수명, 기본값) 형태로 두 번째 인수에 기본값을 지정할 수 있어요. 변수가 정의되지 않았거나 값이 유효하지 않을 때 기본값이 대신 사용돼요.

예: color: var(--text-color, #374151);--text-color가 없으면 #374151이 사용돼요.

여러 단계 fallback도 가능해요: var(--brand-color, var(--primary, #4f46e5)). 이렇게 하면 --brand-color가 없으면 --primary를, 그것도 없으면 #4f46e5를 사용해요.

서드파티 라이브러리나 외부 컴포넌트에서 변수가 정의되지 않은 환경을 고려할 때 유용해요. 라이브러리를 배포한다면 fallback 값을 꼭 지정하는 습관을 들이세요.

⑥ 다음 단계

다음에 배워볼 것들

CSS 변수를 마스터했다면 이것들도 도전해보세요

📐
Flexbox 레이아웃
가로·세로 정렬을 자유자재로 다루는 Flexbox 인터랙티브 가이드
CSS
🔗
OG 태그
카카오톡·슬랙 링크 공유 시 멋진 미리보기 카드 만들기
HTML · SEO
🔘
플로팅 버튼
화면에 고정되는 버튼 — CSS 변수로 색상 관리도 해봐요
CSS · JS
🌐
파비콘 만들기
브라우저 탭 아이콘을 SVG로 직접 만드는 방법
SVG · HTML