--primary-color: #4f46e5; — 단 한 줄.
색상·폰트·간격을 한 곳에서 관리하고, 다크모드도 3줄로 구현해요.
:root에 선언하고 var()로 불러쓰는 재사용 가능한 값들
CSS 변수(정식 명칭: CSS 커스텀 프로퍼티)는 CSS 파일 안에서 값을 변수처럼 저장하고 재사용하는 기능이에요.
--변수명: 값; 형태로 선언하고, var(--변수명)으로 사용해요.
JavaScript의 변수처럼, 한 번 선언해두면 여러 곳에서 불러써요.
가장 큰 장점은 유지보수예요. 사이트 메인 컬러를 바꾸고 싶다면
기존에는 CSS 파일에서 특정 색상값이 쓰인 곳을 전부 찾아서 바꿔야 했어요.
CSS 변수를 쓰면 :root { --primary: #새색상; } 한 줄만 바꾸면 사이트 전체가 바뀌어요.
:root에 선언하면 HTML 전체에서 var()로 불러쓸 수 있어요. 색상, 폰트, 간격 등 모든 값에 적용 가능해요.
변수 선언 한 줄만 바꾸면 그 변수를 쓰는 CSS 전체가 일괄 업데이트돼요. 찾기·바꾸기 없이도 일관성을 유지해요.
@media (prefers-color-scheme: dark)에서 변수 값만 바꿔주면 전체 테마가 다크모드로 전환돼요.
element.style.setProperty('--primary', '#ff0000')로 JS에서도 실시간으로 CSS 변수를 변경할 수 있어요.
:root 란? HTML 문서의 최상위 요소(<html>)를 선택하는 CSS 의사 클래스예요. :root에 CSS 변수를 선언하면 문서 전체에서 접근 가능한 전역 변수가 돼요. 꼭 :root가 아니어도 되지만, 전역으로 쓰려면 :root에 선언하는 게 관행이에요.
AI에게 "내 사이트 CSS 변수 세트 만들어줘. 메인 색상은 파란색이고, 카드·버튼·텍스트에 쓸 변수도 포함해줘"라고 하면 완성된 :root 블록을 바로 받을 수 있어요.
이 페이지 ④ 만들어보기에서 색상 피커로 직접 변수 값을 바꿔보면서 개념을 익혀보세요.
색상 팔레트부터 다크모드까지 — 실제 코드로 보는 활용법
사이트에서 사용하는 모든 색상을 변수로 등록해요. 디자이너가 색상을 바꾸면 변수 값만 업데이트하면 돼요. 브랜드 색상이 일관되게 유지돼요.
폰트 크기를 변수로 관리하면 타이포그래피 스케일이 일관돼요. 기본 폰트를 키우고 싶을 때 변수 하나만 바꾸면 비율이 그대로 유지돼요.
여백과 padding 값을 변수로 통일하면 레이아웃이 일관돼요. --radius처럼 모서리 반경도 변수로 관리하면 전체 UI 느낌을 한 번에 변경할 수 있어요.
라이트모드·다크모드에서 달라지는 값만 변수로 빼두면, @media 쿼리에서 변수만 덮어써요. 수십 개의 CSS 속성을 일일이 바꾸지 않아도 돼요.
var() fallback 값: var(--primary, #4f46e5)처럼 두 번째 인수로 기본값을 지정할 수 있어요. 변수가 정의되지 않았을 때 기본값이 사용돼서, 예상치 못한 스타일 깨짐을 방지해요.
복붙 후 색상만 바꾸면 내 사이트 전체 테마가 완성돼요
/* ═══════════════════════════════════════ 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); }
색상 피커로 --primary-color를 바꾸면 버튼·카드·텍스트가 실시간으로 변해요
위의 슬라이더와 색상 피커를 조작하면 이 카드의 상단 라인 색상, 모서리 반경, 텍스트 크기가 바뀌어요.
CSS 변수CSS 변수로 테마를 한 번에 관리해요.
위 데모는 document.documentElement.style.setProperty('--변수명', '값')으로 JavaScript에서 CSS 변수를 실시간 변경하는 방법을 보여줘요. 이 기법으로 테마 전환, 다크모드 토글, 사용자 맞춤 설정 등을 구현할 수 있어요.
CSS 변수 사용 시 가장 많이 헷갈리는 것들
CSS 변수(Custom Properties)는 IE 11에서 지원되지 않아요. Edge, Chrome, Firefox, Safari 등 모든 현대 브라우저에서는 완벽하게 지원해요. 2024년 기준으로 IE 11의 전 세계 점유율은 0.5% 미만이고, 마이크로소프트도 2022년에 IE를 공식 종료했어요.
IE를 지원해야 하는 환경(기업용 인트라넷 등)이라면 CSS 변수를 쓰지 않거나, PostCSS의 postcss-custom-properties 플러그인으로 변수를 빌드 시 실제 값으로 변환할 수 있어요. 하지만 일반적인 웹사이트라면 IE는 신경 쓰지 않아도 돼요.
두 가지 방법이 있어요:
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 속성처럼 상속돼요. 부모 요소에 선언된 변수는 모든 자식 요소에서 var()로 접근할 수 있어요.
그래서 :root(= <html>)에 선언하면 페이지 전체에서 쓸 수 있는 전역 변수가 돼요. 특정 컴포넌트 안에서만 쓰고 싶으면 그 컴포넌트 클래스 선택자에 선언하면 돼요.
자식 요소에서 같은 이름의 변수를 재선언하면 부모 값을 덮어써요. 이 특성을 활용하면 컴포넌트별로 독립적인 스타일 시스템을 만들 수 있어요.
var(--변수명, 기본값) 형태로 두 번째 인수에 기본값을 지정할 수 있어요. 변수가 정의되지 않았거나 값이 유효하지 않을 때 기본값이 대신 사용돼요.
예: color: var(--text-color, #374151); — --text-color가 없으면 #374151이 사용돼요.
여러 단계 fallback도 가능해요: var(--brand-color, var(--primary, #4f46e5)). 이렇게 하면 --brand-color가 없으면 --primary를, 그것도 없으면 #4f46e5를 사용해요.
서드파티 라이브러리나 외부 컴포넌트에서 변수가 정의되지 않은 환경을 고려할 때 유용해요. 라이브러리를 배포한다면 fallback 값을 꼭 지정하는 습관을 들이세요.
CSS 변수를 마스터했다면 이것들도 도전해보세요