튜토리얼

CSS 상대 색상 구문: 모든 색상을 동적으로 변환

8분 읽기

CSS는 오랫동안 색상을 저장할 수 있었지만 색상을 조작하려면 JavaScript, Sass 함수 또는 빌드 단계가 필요했습니다. CSS 상대 색상 구문이 이를 변경합니다. 변수, 키워드 또는 색상 값에서 기존 색상을 가져와 스타일시트에서 직접 특정 채널을 변환할 수 있습니다. 런타임 시 순수 CSS를 통해 밝게 하고, 색조를 변경하고, 채도를 낮추고, 투명도를 조정할 수 있습니다.

이 기능은 Chrome 119, Firefox 128 및 Safari 16.4에 도입되어 2026년에 프로덕션 용도로 사용할 수 있을 만큼 충분히 높은 브라우저 보급률을 제공합니다. rgb(), hsl(), oklch(), lab(), lch() 등 모든 최신 CSS 색상 기능과 함께 작동합니다.

상대 색상 구문이란 무엇입니까?

상대 색상 구문은 시작 부분에 from <color> 절을 사용하여 CSS 색상 기능을 확장합니다. 이는 브라우저가 원래 색상을 해당 채널로 분해한 다음 해당 채널을 사용하여 새 색상을 재구성하도록 지시합니다(수정 사항 포함).

가장 기본적인 예는 from 키워드를 사용하여 색상을 변경하지 않고 전달합니다.

/* This is a no-op — produces the same color as the input */
color: oklch(from #3B82F6 l c h);

그 자체로는 별로 유용하지 않지만, 추출된 채널 값을 수정할 때 실제적인 힘이 발휘됩니다.

/* Lighten by increasing L (lightness) */
color: oklch(from #3B82F6 calc(l + 0.15) c h);

/* Shift hue by 30 degrees */
color: oklch(from #3B82F6 l c calc(h + 30));

/* Desaturate by reducing chroma */
color: oklch(from #3B82F6 l calc(c * 0.5) h);

/* Make semi-transparent */
color: oklch(from #3B82F6 l c h / 0.5);

이들 각각은 다른 채널을 그대로 유지하면서 단일 채널을 변환합니다. 이전에는 전처리기가 없는 순수 CSS에서는 불가능했던 일입니다.

from 키워드

from 키워드는 상대 색상 구문의 구문 핵심입니다. 색상 함수의 여는 괄호 바로 뒤와 채널 값 앞에 나타납니다.

color-function(from <origin-color> <channel1> <channel2> <channel3> [/ <alpha>])

<origin-color>는 유효한 CSS 색상 값일 수 있습니다.

/* From a hex code */
oklch(from #FF5733 l c h)

/* From a named color */
oklch(from tomato l c h)

/* From a CSS custom property */
oklch(from var(--brand-color) l c h)

/* From another color function */
oklch(from rgb(59, 130, 246) l c h)

/* From currentColor */
oklch(from currentColor l c h)

from currentColor 변형은 특히 강력합니다. 이를 통해 구성 요소는 정확한 값을 알지 못한 채 상속된 텍스트 색상을 변환할 수 있습니다.

색상 기능별 채널 이름

각 색상 기능은 from 키워드 뒤에 특정 이름으로 해당 채널을 노출합니다.

기능 채널 1 채널 2 채널 3 알파
oklch() l c h alpha
oklab() l a b alpha
hsl() h s l alpha
rgb() r g b alpha
lab() l a b alpha
lch() l c h alpha

hsl()에서 from 분해의 채널 순서는 함수 서명(h, s, l)을 반영합니다. oklch()에서는 l, c, h입니다. 사용 중인 기능의 채널 순서를 항상 확인하세요.

교차 기능 변환

원점 색상은 출력 기능과 일치할 필요가 없습니다. 브라우저는 자동으로 변환합니다:

/* Input is hex, output is oklch — browser converts first, then decomposes */
oklch(from #FF5733 calc(l + 0.1) c h)

/* Input is hsl, output is rgb */
rgb(from hsl(200, 80%, 50%) calc(r * 0.9) g b)

이러한 교차 기능 변환은 디자인 토큰을 어떤 형식으로든 저장할 수 있고 조작을 위해 선호하는 모든 형식으로 출력을 생성할 수 있음을 의미합니다.

개별 채널 조정

상대 색상에 대한 가장 일반적인 작업에는 추출된 채널 값을 수정하는 calc()가 포함됩니다.

밝기 조정(OKLCH)

OKLCH를 사용하면 l 채널 범위는 0(검은색)부터 1(흰색)까지입니다. 고정 값을 더하거나 빼면 OKLCH 밝기가 지각적으로 균일하기 때문에 예상대로 더 밝거나 더 어두운 결과가 생성됩니다.

:root {
  --base: oklch(0.58 0.20 250);
}

.lighter  { color: oklch(from var(--base) calc(l + 0.15) c h); }
.lightest { color: oklch(from var(--base) calc(l + 0.30) c h); }
.darker   { color: oklch(from var(--base) calc(l - 0.15) c h); }
.darkest  { color: oklch(from var(--base) calc(l - 0.30) c h); }

OKLCH 밝기는 지각적으로 보정되므로 l에 0.15를 추가하면 색상의 색조에 관계없이 동일한 크기의 인지 밝기 점프가 생성됩니다. HSL과 달리 색상이 노란색인지 파란색인지에 따라 동일한 증분이 다르게 보입니다.

채도 조정

c 채널은 색상 강도를 제어합니다. 0으로 설정하면 동일한 밝기의 중간 회색이 생성됩니다. 크기를 줄이면 완전히 회색으로 표시되지 않고 채도가 낮아집니다.

/* Muted variant — 50% less chroma */
color: oklch(from var(--brand) l calc(c * 0.5) h);

/* Fully desaturated gray at the same lightness */
color: oklch(from var(--brand) l 0 h);

/* More vivid — 30% more chroma (may go out of sRGB gamut on some hues) */
color: oklch(from var(--brand) l calc(c * 1.3) h);

색조 변화

h 채널은 0에서 360까지의 각도 값입니다. 추가하거나 빼면 색상환 주위의 색조가 이동합니다.

/* Complementary color — opposite side of the wheel */
color: oklch(from var(--brand) l c calc(h + 180));

/* Analogous +30° */
color: oklch(from var(--brand) l c calc(h + 30));

/* Analogous -30° */
color: oklch(from var(--brand) l c calc(h - 30));

여러 채널 조정을 결합하면 단일 선언으로 복잡한 변환이 생성됩니다.

/* Lighter, more muted, and slightly different hue — a tonal variant */
color: oklch(from var(--brand) calc(l + 0.12) calc(c * 0.6) calc(h + 15));

알파 채널

슬래시 구문을 사용하여 투명도를 수정합니다.

/* 50% opacity version of the brand color */
background: oklch(from var(--brand) l c h / 0.5);

/* Fully opaque version of a color that might have transparency */
color: oklch(from var(--text-muted) l c h / 1);

/* Scale existing alpha — if origin is 0.8 opacity, reduce to ~0.4 */
background: oklch(from var(--overlay) l c h / calc(alpha * 0.5));

순수 CSS에서 색조 및 음영 만들기

색상 스케일에 대한 전통적인 접근 방식에서는 모든 음영을 미리 계산하고 이를 변수로 저장해야 합니다. 상대 색상 구문을 사용하면 단일 기본 변수에서 전체 척도를 생성할 수 있습니다.

:root {
  --primary: oklch(0.58 0.20 250);

  /* Scale — no pre-computation needed */
  --primary-50:  oklch(from var(--primary) 0.97 calc(c * 0.1) h);
  --primary-100: oklch(from var(--primary) 0.94 calc(c * 0.2) h);
  --primary-200: oklch(from var(--primary) 0.88 calc(c * 0.4) h);
  --primary-300: oklch(from var(--primary) 0.78 calc(c * 0.6) h);
  --primary-400: oklch(from var(--primary) 0.68 calc(c * 0.8) h);
  --primary-500: var(--primary);
  --primary-600: oklch(from var(--primary) calc(l - 0.08) c h);
  --primary-700: oklch(from var(--primary) calc(l - 0.16) c h);
  --primary-800: oklch(from var(--primary) calc(l - 0.24) c h);
  --primary-900: oklch(from var(--primary) calc(l - 0.32) c h);
  --primary-950: oklch(from var(--primary) calc(l - 0.38) c h);
}

--primary를 원하는 색상으로 변경하면 전체 11단계 척도가 브라우저에서 자동으로 재생성됩니다. 빌드 단계도 없고, JavaScript도 없고, Sass도 없습니다.

매우 정확한 인식 단계가 필요한 생산 디자인 시스템의 경우 Shade Generator는 수동으로 조정된 50-950 스케일을 제공합니다. 상대 색상 접근 방식은 유연성보다 정확성이 덜 중요한 소규모 부품이나 신속한 프로토타입 제작에 이상적입니다.

배경에 접근 가능한 색조

일반적인 패턴은 알림 배너 및 경고 상자에 대해 매우 밝은 색조의 배경을 만드는 것입니다.

:root {
  --success: oklch(0.65 0.20 145);  /* A vivid green */
  --warning: oklch(0.75 0.18 70);   /* A warm amber */
  --danger:  oklch(0.62 0.24 25);   /* A strong red */
}

.alert-success {
  background: oklch(from var(--success) 0.96 0.04 h);
  border-left: 3px solid var(--success);
  color: oklch(from var(--success) 0.30 0.14 h);
}

.alert-warning {
  background: oklch(from var(--warning) 0.97 0.04 h);
  border-left: 3px solid var(--warning);
  color: oklch(from var(--warning) 0.35 0.14 h);
}

.alert-danger {
  background: oklch(from var(--danger) 0.96 0.04 h);
  border-left: 3px solid var(--danger);
  color: oklch(from var(--danger) 0.32 0.14 h);
}

배경은 경고 색상의 매우 높은 밝기, 낮은 채도 버전입니다. 텍스트는 매우 어둡고 채도가 중간 정도인 버전을 사용합니다. 색상(h)은 모든 경우에 원래 색상에서 유지됩니다. 모든 것이 자동으로 색상을 유지합니다.

OKLCH를 사용한 실제 사례

테마 적응형 호버 상태

.card {
  --card-accent: oklch(0.60 0.18 260);
  background: var(--card-accent);
  transition: background-color 150ms ease;
}

.card:hover {
  /* Darken slightly on hover — works regardless of what the accent is */
  background: oklch(from var(--card-accent) calc(l - 0.06) c h);
}

이 패턴은 강조 색상이 prop 또는 사용자 정의 속성으로 전달되는 구성 요소 라이브러리에서 특히 강력합니다. 호버 상태는 모든 변형에 대해 별도의 호버 색상을 요구하지 않고도 항상 상황에 맞게 적절합니다.

컬러 배경의 텍스트

.chip {
  --chip-color: oklch(0.62 0.20 260);

  /* Background: very light tint */
  background: oklch(from var(--chip-color) 0.94 0.06 h);

  /* Text: very dark version of same hue */
  color: oklch(from var(--chip-color) 0.28 0.16 h);

  /* Border: medium-light version */
  border: 1px solid oklch(from var(--chip-color) 0.78 0.12 h);
}

이렇게 하면 배경, 텍스트, 테두리가 동일한 색상을 공유하므로 모두 조화로운 컬러 칩이 생성됩니다. --chip-color를 변경하면 전체 세트가 업데이트됩니다.

from currentColor를 사용한 다크 모드 적응

.icon-wrapper {
  /* Icon color inherits from text context */
  color: var(--color-text-primary);
}

.icon-wrapper:hover {
  /* Subtly darker version of whatever color the icon currently is */
  color: oklch(from currentColor calc(l - 0.08) c h);
}

.icon-wrapper .background-glow {
  /* Semi-transparent version of the icon color, for a glow effect */
  background: oklch(from currentColor l c h / 0.15);
}

currentColor 원점은 이 구성 요소가 특정 색상 값을 알 필요 없이 다크 모드를 포함한 모든 텍스트 색상 컨텍스트에서 올바르게 작동함을 의미합니다.

보완 악센트 생성하기

기본 브랜드 색상에서 파생된 보색 강조 색상이 필요한 디자인의 경우:

:root {
  --brand: oklch(0.60 0.20 250);   /* Blue */

  /* Complement: opposite hue, same lightness and chroma */
  --accent: oklch(from var(--brand) l c calc(h + 180));
  /* Result: approximately orange at hue ~70° */

  /* Softer complement for backgrounds */
  --accent-bg: oklch(from var(--brand) 0.95 0.06 calc(h + 180));
}

이는 수학적으로 보색을 생성합니다. 보다 정교한 분할-상보 방식을 위해서는 180° 대신 ±150° 또는 ±160°로 오프셋하십시오.

브라우저 지원 및 대체

상대 색상 구문은 다음에서 지원됩니다.

  • Chrome/Edge: 버전 119부터(2023년 11월)
  • Firefox: 버전 128부터(2024년 7월)
  • Safari: 버전 16.4(2023년 3월)부터 — Safari가 먼저 출시됨

글로벌 지원은 2026년 초 기준으로 약 85~88%입니다. 더 넓은 적용 범위를 얻으려면 폴백을 제공하세요.

.btn-hover {
  /* Fallback: pre-computed hex for older browsers */
  background-color: #1D4ED8;
}

@supports (color: oklch(from red l c h)) {
  .btn-hover {
    /* Modern: dynamically derived from the base */
    background-color: oklch(from var(--btn-bg) calc(l - 0.08) c h);
  }
}

@supports 테스트 (color: oklch(from red l c h))는 OKLCH 지원뿐만 아니라 상대 색상 구문 지원을 구체적으로 확인합니다. 이는 OKLCH 및 상대 색상 구문이 다른 브라우저 버전에 제공되므로 중요합니다.

주요 내용

  • 상대 색상 구문은 CSS 색상 함수 내에서 from <origin-color>를 사용하여 해당 색상을 채널로 분해한 다음 calc()로 수정하고 새로운 색상으로 재구성할 수 있습니다.
  • OKLCH는 채널(명도, 채도, 색조)이 디자인 의도에 밀접하게 매핑되고 밝기가 지각적으로 균일하기 때문에 상대 색상 조작에 사용하는 가장 좋은 기능입니다. 동일한 증분은 동일한 모양의 변화를 생성합니다.
  • 단일 채널을 독립적으로 조정할 수 있습니다. l에 추가하여 밝게 하고, c를 곱하여 채도를 낮추고, h에 추가하여 색상을 변경하거나, alpha를 수정하여 투명도를 변경합니다.
  • from currentColor 오리진은 상속된 텍스트 색상에서 색상을 파생하는 자체 적응 구성 요소를 생성하여 다크 모드를 포함한 모든 상황에서 자동으로 수정됩니다.
  • 브라우저 지원은 2023년 말/2024년 중반 이후의 모든 최신 브라우저에 적용됩니다. 특히 상대 색상 구문에 대한 지원을 감지하려면 @supports (color: oklch(from red l c h))를 사용하십시오.
  • 생산 설계 시스템에서 정밀하고 수동으로 조정된 50-950 스케일을 위해 Shade Generator를 사용하십시오. 구성 요소의 동적 런타임 파생 변형에 대해 상대 색상 구문을 사용합니다.
  • 색상 변환기를 사용하여 기존 16진수 브랜드 색상을 OKLCH 값으로 변환하여 상대 색상 표현을 작성하기 전에 l, ch 채널을 이해합니다.

관련 색상

관련 브랜드

관련 도구