본문으로 건너뛰기
개발 머꼬
개발 노트CSS
hohyeon.dev22

CSS 변수에 잘못된 값이 들어갔더니 fallback도 아니고 검정색이 된 이유

  • #CSS
  • #Debugging
  • #Engineering Note

문제 발생

테마 변수에 오타가 들어갔더니, 글자색이 지정한 파란색도 fallback도 아닌 검정색이 됐습니다.

:root { --text-color: 16px; }   /* color 자리에 길이가 들어감 */

p { color: blue; }
p { color: var(--text-color, red); }   /* red도 아니고 검정 */

한 줄 위의 color: blue가 살아남을 줄 알았는데 그것도 아니었습니다.

원인 분석

두 개념이 섞여 있습니다.

var()의 fallback은 커스텀 속성이 정의되지 않았거나 유효하지 않을 때 쓰입니다. 여기서는 --text-color가 멀쩡히 정의돼 있으므로 fallback이 쓰일 이유가 없고, 치환은 성공합니다. 문제는 치환된 뒤 color: 16px이 되어 그 속성에 맞지 않는다는 것입니다.

이 상황을 invalid at computed-value time이라고 부릅니다. MDN이 결과를 그대로 적습니다 — 브라우저가 유효하지 않은 var() 치환을 만나면 그 속성의 초기값 또는 상속값이 사용됩니다. 순서는 이렇습니다: 상속되는 속성이고 부모에 값이 있으면 상속값을, 아니면 그 속성의 초기값을 씁니다.

그래서 일반적인 CSS 오타처럼 "그 선언만 무시되고 앞의 선언이 살아남는" 동작이 아닙니다. color: blue는 이미 덮여 있고, 최종적으로 초기값인 검정이 남습니다.

fallback 문법에도 함정이 있습니다. MDN 설명대로 fallback 문법은 쉼표를 허용해서 var(--foo, red, blue)의 fallback은 red, blue입니다 — 첫 쉼표 뒤 전부가 fallback입니다. 여러 단계 fallback은 var()를 중첩해야 합니다.

해결 방안

  1. @property로 타입을 등록합니다. 잘못된 값이 들어오면 등록된 initial-value로 떨어져 예측 가능해집니다.
@property --text-color {
  syntax: "<color>";
  inherits: true;
  initial-value: #1a1a1a;
}

MDN이 명시하듯 syntaxinherits는 필수이고, syntax: "*"가 아니면 initial-value도 필요합니다. 둘 중 하나라도 빠지면 규칙 전체가 무시됩니다.

  1. 등록하면 애니메이션도 가능해집니다. 등록된 커스텀 속성은 전환·애니메이션 대상이 됩니다 — 등록 전에는 값이 그냥 튀는 문자열이었습니다.

  2. fallback은 중첩으로 씁니다.

color: var(--text-color, var(--brand-color, #1a1a1a));
  1. DevTools에서 계산값을 확인합니다. 이 버그는 스타일 패널에서 선언이 취소선 없이 멀쩡해 보이는데 결과만 다릅니다. Computed 탭에서 실제 적용값을 봐야 드러납니다.

  2. JS로 값을 넣는 경로를 특히 조심합니다. element.style.setProperty("--x", value)에 숫자나 undefined가 들어가면 같은 상황이 됩니다. 값에 단위를 붙이는 책임을 한 곳으로 모읍니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.