AD JB Toolbox 01

CSS 강좌 / 변수 사용하는 방법: var()·상속·대체값

CSS 변수는 --이름: 값으로 선언하는 사용자 지정 속성(custom property)이며, 실제 CSS 속성에서 var(--이름)으로 참조합니다. 반복되는 색과 간격을 한곳에서 관리하고, 구성 요소 안에서 값을 덮어써 필요한 범위만 바꿀 수 있습니다. 변수가 없을 때의 대체값과, 변수가 있지만 사용하는 속성에 맞지 않을 때의 결과는 다릅니다.

변수로 관리할 값을 고르기

여러 버튼과 카드에 같은 강조색을 사용한다면 각각의 선택자에 색상 코드를 복사하는 대신 의미 있는 변수로 묶을 수 있습니다. 강조색을 바꿀 때 한 선언을 수정하면 그 값을 참조하는 곳이 함께 바뀝니다. 아직 한 곳에서만 쓰이고 별도의 역할이 없는 값까지 모두 변수로 만들면 오히려 이름을 추적하는 부담이 커질 수 있습니다.

:root {
  --accent: #1d5f91;
  --space-unit: .5rem;
}
.button { color: white; background: var(--accent); }
.card { border: 2px solid var(--accent); padding: calc(var(--space-unit) * 3); }

위 코드에서 색을 선언하는 것만으로 화면이 바뀌지는 않습니다. background나 border처럼 실제 속성이 var로 참조해야 합니다. 이름은 --blue처럼 현재 색을 고정하기보다 --accent처럼 역할을 나타내면 나중에 다른 색으로 바꿀 때 덜 혼란스럽습니다. --accent와 --Accent는 서로 다른 이름이므로 대소문자와 철자를 일치시키세요.

var()는 color나 padding 같은 속성의 값에 사용합니다. 선택자나 속성 이름을 변수로 대체할 수 없으며, @media (min-width: ...)나 컨테이너 크기 쿼리의 조건값에 var()를 넣어 분기점을 정할 수도 없습니다. 분기점은 해당 조건문에 직접 작성하고, 요소의 색상·간격처럼 변수가 적용될 수 있는 값과 구분하세요.

전역 값·상속·구성 요소의 범위

HTML 문서에서 :root는 최상위 html 요소에 일치하므로 문서에서 공통으로 쓸 기본값을 두기에 편리합니다. 일반적인 -- 사용자 지정 속성은 자손에게 상속됩니다. 카드 안에 선언한 값은 제목 같은 자손에서 사용할 수 있지만 관계없는 형제 카드로 전달되지 않습니다.

.card { --card-accent: var(--accent); }
.card.warning { --card-accent: #a63e32; }
.card { border-color: var(--card-accent); }
.card h2 { color: var(--card-accent); }

이 규칙은 아래 전체 예제의 구성 요소 부분입니다. .card.warning은 두 클래스를 모두 가진 카드에 일치합니다. HTML 클래스의 나열 순서로 승패가 정해지는 것이 아니라 선택자 일치와 캐스케이드가 값을 결정합니다. 전역 accent를 바꾸면 기본 카드가 바뀌고, 자신만의 card-accent를 지정한 경고 카드는 원래 경고색을 유지합니다.

변수를 다른 변수로 조합할 때는 어느 요소에서 값이 계산되는지도 중요합니다. 부모에서 --line-color: var(--accent)를 계산한 뒤 자손에 상속했다면, 자손에서 accent만 덮어쓴다고 이미 상속된 line-color가 항상 다시 계산되는 것은 아닙니다. 자손의 accent를 따라야 할 파생 값은 해당 요소에서 선언하거나 실제 속성에서 accent를 직접 참조하는 편이 분명합니다. 범위와 상속의 정의는 CSS 사용자 지정 속성 명세를 참고하세요.

var의 대체값은 잘못된 모든 값을 고치는 장치가 아닙니다

var(--notice-color, #6a3989)는 변수 값이 없어 사용할 수 없는 경우 보라색 대체값을 제공합니다. 변수가 정의되어 20px처럼 다른 속성에서는 의미가 있는 값이어도, 그 값이 color에 맞지 않으면 color 선언은 계산 시점에 유효하지 않게 됩니다. 이 경우 “보라색으로 대체된다”고 기대하면 안 됩니다.

변수 상태 color 선언의 결과 전체 예제의 색
notice-color가 없음 var의 대체값 사용 보라색
notice-color가 빨간색 정의된 값 사용 빨간색
notice-color가 20px color에 맞지 않아 상속·초기값 규칙 적용 color는 상속 속성이므로 부모의 초록색

다음처럼 같은 규칙에 파란색 선언이 먼저 있어도 두 번째 선언의 변수 치환 뒤 값이 맞지 않으면 첫 번째 파란색으로 되돌아가지 않습니다. 캐스케이드에서 선택한 선언이 계산 시점에 무효가 된 뒤 color의 상속 규칙이 적용됩니다. 같은 상황에서 상속되지 않는 속성은 그 속성의 초기값으로 처리될 수 있습니다. MDN 사용자 지정 속성 안내는 대체값과 잘못된 값의 차이를 설명합니다.

.sample {
  color: #1d5f91;
  color: var(--notice-color, #6a3989);
}
.sample.bad { --notice-color: 20px; }

대체값에도 다른 var를 넣을 수 있습니다. 예를 들어 var(--button-accent, var(--accent, #1d5f91))은 버튼 전용 값, 공통 값, 마지막 기본색 순으로 사용할 값을 찾습니다. 하지만 숫자·길이·색의 용도가 뒤섞이면 같은 문제가 생기므로 변수 이름과 사용처를 함께 관리해야 합니다.

calc로 값을 조합할 때 단위 확인하기

아래 전체 예제는 --space-unit: .5rem에 3을 곱해 카드의 안쪽 여백을 만듭니다. rem은 최상위 글자 크기를 기준으로 하므로 글자 크기가 커지면 간격도 함께 커집니다. 식을 문자열처럼 붙여 만드는 대신 calc()로 계산하며, 덧셈·뺄셈 연산자 주위에는 공백을 둡니다. 변수에 길이를 저장할 때는 em·rem과 길이의 계산 기준도 함께 구분하세요.

:root {
  --space-unit: .5rem;
  --space-card: calc(var(--space-unit) * 3);
}
.card { padding: var(--space-card); }

변수에 단위를 포함할지 숫자만 둘지 일관되게 선택합니다. 길이 변수에 2처럼 단위 없는 값을 넣으면 단위를 요구하는 사용처에서 맞지 않을 수 있습니다. 색을 담은 변수에 calc를 적용하는 것처럼 용도가 다른 조합도 피하세요. 수식의 기본 문법은 MDN calc 문서를 참고하세요.

전체 예제: 범위·간격·대체값 비교

다음 코드를 UTF-8의 custom-properties.html로 저장하고 브라우저에서 여세요. 두 카드의 강조색과 세 문장의 글자색을 비교합니다. 색의 의미를 글자로도 적어 색상만으로 결과를 구분하지 않게 했습니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>CSS 변수의 범위와 대체값</title>
  <style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 1rem; color: #183044; font-family: sans-serif; line-height: 1.6; }
main { max-width: 46rem; margin-inline: auto; }
h1 { font-size: 1.5rem; } h2 { font-size: 1.2rem; }
button, input { font: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 3px solid #164f73; outline-offset: 3px; }
:root { --space-unit: .5rem; --space-card: calc(var(--space-unit) * 3); --accent: #1d5f91; }
.cards { display: grid; gap: 1rem; }
.card { --card-accent: var(--accent); padding: var(--space-card); border: 2px solid var(--card-accent);
  border-radius: .5rem; background: #f6f9fb; }
.card h2 { color: var(--card-accent); margin-block: 0 .5rem; }
.card p { margin: 0; }
.card.warning { --card-accent: #a63e32; }
.fallback-area { margin-block: 2rem; padding: 1rem; border: 1px solid #8a9ba7; color: #28633b; }
.sample { color: #1d5f91; color: var(--notice-color, #6a3989); }
.sample.bad { --notice-color: 20px; }
.sample.good { --notice-color: #a63e32; }
  </style>
</head>
<body>
<main>
<h1>변수의 범위와 대체값</h1>
<div class="cards">
  <article class="card"><h2>기본 카드</h2><p>제목과 테두리에 같은 강조색을 사용합니다.</p></article>
  <article class="card warning"><h2>경고 카드</h2><p>이 카드 안에서만 강조색을 바꿉니다.</p></article>
</div>
<section class="fallback-area">
  <h2>부모의 글자색은 초록색</h2>
  <p class="sample missing">미정의: 보라색 대체값</p>
  <p class="sample bad">20px: color에 맞지 않아 부모의 초록색 상속</p>
  <p class="sample good">빨간색 정의: 해당 색 사용</p>
</section>
</main>
</body>
</html>
  1. 기본 카드의 제목과 테두리는 파란색, 경고 카드는 빨간색인지 확인합니다. 아래 세 문장은 각각 보라색·초록색·빨간색입니다.
  2. root의 accent만 #28633b로 바꿉니다. 기본 카드의 제목과 테두리가 함께 바뀌고 경고 카드는 유지됩니다. 확인 후 #1d5f91로 되돌립니다.
  3. space-unit만 1rem으로 바꿉니다. 두 카드의 안쪽 여백이 함께 늘어납니다. 확인 후 .5rem으로 복원합니다.
  4. bad의 notice-color만 20px에서 #1d5f91로 바꿉니다. 해당 문장이 초록색에서 파란색으로 바뀝니다. 확인 후 20px로 복원합니다.
  5. bad의 notice-color 선언만 삭제합니다. 이번에는 보라색 대체값이 사용됩니다. 앞 단계의 파란색 결과와 비교한 뒤 원래 선언을 복원합니다.

변수가 적용되지 않을 때 확인할 순서

  • 개발자 도구에서 해당 요소에 변수 이름과 값이 실제로 있는지 확인합니다. 철자·대소문자·선언 범위를 먼저 봅니다.
  • 자손이나 다른 규칙이 같은 변수를 덮어쓰는지 확인합니다. 공통 값이 바뀌어도 구성 요소의 고유 값이 유지되는 것은 오류가 아닐 수 있습니다.
  • 변수를 실제 속성에서 참조했는지와 치환된 값의 단위·유형이 맞는지 확인합니다.
  • 여러 변수를 거쳐 값이 만들어진다면 계산되는 요소와 상속된 값을 확인합니다. 같은 변수를 자기 자신으로 참조하거나 순환 참조하는 선언도 피합니다.

디자인의 공통 색·간격과 구성 요소별 예외를 구분하고, 변경 전후 결과를 확인하면 변수의 이점을 얻을 수 있습니다. 변수 이름의 개수를 늘리는 것보다 어느 범위에서 어떤 값을 공유하는지 명확히 만드는 것이 유지보수에 도움이 됩니다.

같은 카테고리의 다른 글
CSS 강좌 / 넘치는 콘텐츠와 긴 문자열 처리하기

CSS 강좌 / 넘치는 콘텐츠와 긴 문자열 처리하기

같은 내용에 visible·hidden·auto·scroll을 적용해 넘침 처리를 비교합니다. 긴 URL 줄바꿈과 실제 말줄임표 예제를 실행하고, 원문 보존과 키보드 스크롤을 함께 확인합니다.

CSS 강좌 / @keyframes 애니메이션과 움직임 줄이기

CSS 강좌 / @keyframes 애니메이션과 움직임 줄이기

키프레임의 중간 상태와 재생 시간·지연·방향·횟수·종료 상태를 비교합니다. 일시 정지와 움직임 감소 설정까지 전체 예제로 확인합니다.

CSS / Tutorial / placeholder의 색, 글자 모양 등 꾸미는 방법

CSS / Tutorial / placeholder의 색, 글자 모양 등 꾸미는 방법

placeholder는 HTML5에서 새로 나온 속성으로 input 요소나 textarea 요소에 안내문을 넣을 수 있습니다. 기본 모양은 회색의 글자로, 배경색이 하얀색 또는 밝은 색이면 보기에 괜찮습니다. 하지만 배경색이 어두운 색이거나 화려한 색이면 회색 글자가 어울리지 않을 수 있습니다. placeholder는 ::placeholder 선택자로 선택하여 꾸밀 수 있습니다.

CSS 강좌 / 모바일·큰 화면·확대 보기에서 레이아웃 점검하기

CSS 강좌 / 모바일·큰 화면·확대 보기에서 레이아웃 점검하기

점검용 페이지에서 화면 폭, 확대, 긴 문자열과 키보드 조작을 확인합니다. 가로 넘침과 글자 잘림을 재현하고 원인 확인부터 수정·재점검까지 실습합니다.

CSS 강좌 / Flexbox 정렬·간격·줄바꿈·크기 조절하기

CSS 강좌 / Flexbox 정렬·간격·줄바꿈·크기 조절하기

Flexbox의 아이템 정렬과 여러 줄 정렬을 구분하고, gap·줄바꿈·grow·shrink·basis를 비교 예제로 익힙니다. 긴 문자열이 넘치는 원인과 크기·줄바꿈의 해결 방법도 다룹니다.

CSS 강좌 / 표와 셀의 크기 조절하기

CSS 강좌 / 표와 셀의 크기 조절하기

표의 자동·고정 레이아웃, 30:70 열 너비, 긴 문자열의 영향을 같은 데이터로 비교합니다. 모바일 가로 스크롤과 키보드 이동을 확인하고 말줄임 원문을 보존하는 방법을 설명합니다.

CSS 강좌 / 표 꾸미기 / 테두리

CSS 강좌 / 표 꾸미기 / 테두리

테두리는 border 속성으로 만듭니다. table, th, td 요소에 적용할 수 있습니다. tr 요소에는 적용되지 않습니다.

CSS 강좌 / 글꼴, 글자 크기, 굵기, 줄 간격 설정하기

CSS 강좌 / 글꼴, 글자 크기, 굵기, 줄 간격 설정하기

글꼴·글자 크기·굵기·줄 간격을 설정하고 실제 사용된 글꼴을 확인하는 방법을 설명합니다. 단위 없는 line-height와 em 값의 상속 차이를 실행 가능한 예제로 비교합니다.

CSS / Tutorial / 원 또는 타원 만드는 방법

CSS / Tutorial / 원 또는 타원 만드는 방법

CSS의 border-radius 속성으로 원 또는 타원을 만들 수 있습니다. HTML 문서에 다음과 같이 내용이 없는 요소를 하나 만듭니다. 적절히 크기를 정하여 정사각형을 만들고, 배경색을 넣습니다. border-radius 속성을 추가하고, 값에 50%를 넣으면 원이 만들어집니다.

CSS 강좌 / 기본 선택자 - 요소, 클래스, ID, 속성

CSS 강좌 / 기본 선택자 - 요소, 클래스, ID, 속성

요소·클래스·ID·속성 선택자를 같은 HTML에 적용해 대상과 결과를 비교합니다. 복합 클래스, 공백으로 구분한 속성값, 필수 입력칸을 포함한 전체 예제와 선택자 수정 실습을 제공합니다.