CSS 상대 색상 구문

다른 색상의 채널과 값을 기반으로 새 색상을 만듭니다.

Adam Argyle
Adam Argyle

Chrome 119는 CSS 색상 수준 5의 매우 강력한 색상 기능입니다. 상대적 색상 문법은 CSS 내에서 색상을 조작할 수 있는 원활한 경로를 만들어 주며, 작성자와 디자이너는 다음과 같은 작업을 할 수 있습니다.

상대 색상 문법 전에 색상의 불투명도를 수정하려면 색상 채널(일반적으로 HSL)의 맞춤 속성을 만들고 이를 최종 색상 및 최종 변형 색상으로 조합해야 합니다. 즉, 많은 색상 조각을 관리해야 하므로 빠르게 부담이 될 수 있습니다.

:root {
  --brand-hue: 300deg;
  --brand-saturation: 75%;
  --brand-lightness: 50%;

  --brand-hsl:
    var(--brand-hue)
    var(--brand-saturation)
    var(--brand-lightness);

  --brand-color: hsl(var(--brand-hsl));

  /* all this work just so I can set the opacity to 50% in a variant */
  --brand-color-variant: hsl(var(--brand-hsl) / 50%);
}

상대 색상 구문 후에 필요한 색상 공간 또는 구문으로 브랜드 색상을 만들고 코드를 훨씬 적게 사용하여 절반 불투명도 변형을 만들 수 있습니다. 또한 스타일과 시스템의 인텐트를 훨씬 쉽게 읽을 수 있습니다.

:root {
  --brand-color: hsl(300deg 75% 50%);
  --brand-color-variant: hsl(from var(--brand-color) h s l / 50%);
}

이 게시물에서는 구문을 학습하고 일반적인 색상 조작을 설명하는 데 도움이 됩니다.

동영상을 선호한다면 이 GUI 챌린지에서 다음 도움말의 대부분을 다룹니다.

구문 개요

상대 색상 구문의 목표는 다른 색상에서 색상을 유도하는 것입니다. 기본 색상은 원래 색상이라고 하며 새 from 키워드 다음에 오는 색상입니다. 브라우저는 이 원래 색상을 변환하고 분할하며 이 부분을 새 색상 정의에 사용할 수 있는 변수로 제공합니다.

RGB 구문(녹색 r g b / alpha)의 다이어그램이 표시됩니다. 화살표는 녹색 상단을 떠나 함수 시작 부분의 RGB 시작 부분을 향하고 있습니다. 이 화살표는 4개의 화살표로 분할되어 관련 변수를 가리킵니다. 4개의 화살표는 빨간색, 녹색, 파란색, 알파입니다. 빨간색과 파란색의 값은 0, 녹색은 128, 알파는 100%입니다.

위의 다이어그램은 새 색상의 색상 공간으로 변환되는 원래 색상 green를 보여줍니다. 이러한 색상은 새로운 rgb() 색상 값으로 직접 사용되는 r, g, b, alpha 변수로 표현되는 개별 숫자로 변환됩니다.

이 이미지는 분류, 프로세스, 변수를 보여주지만 색상이 변경되지는 않습니다. 변수는 색상으로 다시 배치되므로 여전히 녹색이 됩니다.

from 키워드

구문의 첫 번째 부분은 색상 지정에 추가되는 from <color> 부분입니다. 값을 지정하기 직전에 이 작업을 수행합니다. 다음은 rgb()의 값이 지정되기 직전에 from green가 모두 추가된 코드 예시입니다.

.syntax-introduction_same-colors {
  color: green;
  color: rgb(0 128 0);
  color: rgb(from green r g b);    /* result = rgb(0 128 0) */
}

from 키워드는 기능적 표기법의 첫 번째 매개변수로 표시될 때 색상 정의를 상대 색상으로 변환합니다. from 키워드 다음에 CSS는 다음 색상을 결정하는 색상인 색상을 예상합니다.

색상 변환

간단히 말해 녹색을 새로운 색상에 사용할 수 있도록 rg 및 b 채널로 변환합니다.

rgb(from green r g b)           /* r=0 g=128 b=0 */
rgb(from rgb(0 128 0) r g b);   /* r=0 g=128 b=0 */

맞춤 속성의 색상

rgb from green 읽기는 매우 명확하고 이해하기 쉽습니다. 이러한 이유로 from 색상에서 미스터리를 제거할 수 있으므로 맞춤 속성과 상대 색상 문법이 큰 도움이 됩니다. 또한 선택한 형식으로 새 색상을 만들므로 일반적으로 맞춤 속성 색상의 색상 형식을 알 필요가 없습니다.

rgb(from rgb(255 105 180) r g b) /* ????? */
rgb(from var(--hotpink) r g b)   /* clear */

원하는 색상 공간에서 작업

기능적인 색상 표기법을 선택하여 색공간을 선택할 수 있습니다.

rgb(from hsl(120 100% 25%) r g b)     /*  r=0   g=128  b=0    */
hsl(from hsl(120 100% 25%) h s l)     /*  h=120 s=100% l=25%  */
hwb(from hsl(120 100% 25%) h w b)     /*  h=120 w=0%   b=50%  */
lch(from hsl(120 100% 25%) l c h)     /*  l=46  c=68   h=134  */

상대 색상 구문에는 이러한 변환 단계가 있습니다. from 이후의 색상은 상대 색상의 시작 부분에 지정된 대로 색상 공간으로 변환됩니다. 입력과 출력이 일치할 필요가 없기 때문에 매우 편리합니다.

색공간을 선택하는 기능은 선호보다 색 교체 유형에 더 중점을 두는 경향이 있기 때문에 색공간을 선택하는 기능도 도움이 됩니다. 환경설정은 색상 형식이나 채널 유형이 아닌 결과에 있습니다. 이는 사용 사례를 보여주는 섹션에서 훨씬 더 명확해집니다. 다양한 색상 공간이 다양한 작업에서 탁월하기 때문입니다.

변수 조합하기, 매칭하기, 생략하기, 반복하기

이 구문의 이상하지만 흥미로운 점은 변수는 정리될 필요가 없으며 반복될 수 있습니다.

rgb(from green g g g)    /* rgb(128 128 128) */
rgb(from green b r g)    /* rgb(0 0 128) */
rgb(from green 0 0 g)    /* rgb(0 0 128) */

변수로서의 불투명도

이 문법은 불투명도를 alpha이라는 변수로 제공합니다. 선택사항이며 기능적 색상 표기법에서 / 뒤에 있습니다.

rgb(from #00800080 r g b / alpha)             /* alpha=50% */
rgb(from rgba(0,128,0,.5) r g b / alpha)      /* alpha=50% */
rgb(from rgb(0 128 0 / 50%) r g b / alpha)    /* alpha=50% */

변수에 calc() 또는 다른 CSS 함수 사용

지금까지는 계속해서 녹색을 만들었습니다. 문법을 배우고 변환 및 디스트럭처링 단계에 익숙해집니다. 이제 변수를 수정하고 출력을 입력과 같지 않도록 변경합니다.

green                              /*  h=120 s=100% l=25%  */
hsl(from green calc(h * 2) s l)    /*  h=240 s=100% l=25%  */

이제 네이비입니다! 색조가 두 배로 증가하여 120의 색조를 가져와 240로 변환하여 색상이 완전히 변경되었습니다. 이는 색상환을 따라 색조를 회전시켰으며, 이는 HSL, HWB, LCH, OKLCH와 같은 원통형 색상 공간으로 매우 간단하게 만드는 깔끔한 방법입니다.

채널 값을 시각적으로 확인할 수 있어 추측하거나 사양을 기억하지 않아도 정확한 계산을 할 수 있도록 이 상대적 색상 구문 채널 값 도구를 사용해 보세요. 지정한 구문에 기초하여 각 채널 값을 보여주므로, 어떤 값을 사용할 수 있는지 정확하게 알 수 있습니다.

브라우저 지원 확인

@supports (color: rgb(from white r g b)) {
  /* safe to use relative color syntax */
}

사용 사례 및 데모

다음 예시 및 사용 사례에는 유사하거나 동일한 결과를 얻을 수 있는 대체 구문이 많이 있습니다. 이러한 변형은 색상 공간과 제공되는 채널에 따라 달라집니다.

또한 byto의 설명을 사용한 색상 조정을 보여주는 여러 예도 있습니다. 색상 변경 by은 상대적인 색상 변경입니다. 즉, 변수 값을 사용하고 현재 값을 기반으로 조정을 수행합니다. 색상 변경 to은 절대적인 색상 변경입니다. 즉, 변수 값을 사용하지 않고 완전히 새로운 값을 지정하는 변경입니다.

모든 데모는 이 Codepen 컬렉션에서 찾을 수 있습니다.

색상을 밝게

OKLCH, OKLAB, XYZ 또는 sRGB 색상 공간은 색상을 밝게 할 때 가장 예측 가능한 결과를 제공합니다.

조금 더 밝게 하기

다음 예시 .lighten-by-25blue 색상을 OKLCH로 변환한 후 현재 값에 1.25을 곱하여 l (밝기) 채널을 늘려 파란색을 밝게 합니다. 이렇게 하면 파란색 밝기를 흰색으로 25% 높일 수 있습니다.

.lighten-by-25 {
  background: oklch(from blue calc(l * 1.25) c h);
}

특정 값으로 밝게

다음 .lighten-to-75 예에서는 l 채널을 사용하여 blue를 밝히지 않고 대신 값을 75%로 완전히 바꿉니다.

.lighten-to-75 {
  background: oklch(from blue 75% c h);
}

색상을 어둡게 합니다.

색상을 밝게 하는 데 효과적인 동일한 색상 공간은 색상을 어둡게 하는 데에도 좋습니다.

약간 어둡게

다음 예시 .darken-by-25는 파란색을 OKLCH로 변환한 후 값에 .75을 곱하여 l (밝기) 채널을 25% 줄여 파란색을 어둡게 합니다. 그러면 파란색이 검은색에 25% 가까워집니다.

.darken-by-25 {
  background: oklch(from blue calc(l * .75) c h);
}

지정된 값으로 어둡게

다음 .darken-to-25 예는 l 채널을 사용하여 blue를 어둡게 하지 않고 대신 값을 25%로 완전히 바꿉니다.

.darken-to-25 {
  background: oklch(from blue 25% c h);
}

색상 채도

양만큼 채도

다음 .saturate-by-50 예에서는 hsl()s를 사용하여 상대적 50%만큼 orchid의 생동감을 높입니다.

.saturate-by-50 {
  background: hsl(from orchid h calc(s * 1.5) l);
}

특정 양으로 선명하게

다음 .saturate-to-100 예에서는 hsl()s 채널을 사용하지 않고 대신 원하는 채도 값을 지정합니다. 이 예에서는 채도가 100%로 증가합니다.

.saturate-to-100 {
  background: hsl(from orchid h 100% l);
}

색상 채도 낮추기

채도 낮춤

다음 예시 .desaturate-by-halfhsl()s를 사용하여 indigo의 채도를 절반으로 줄입니다.

.desaturate-by-half {
  background: hsl(from indigo h calc(s / 2) l);
}

특정 값으로 채도 낮추기

채도를 줄이는 대신 원하는 특정 값으로 채도를 낮출 수 있습니다. 다음 .desaturate-to-25 예에서는 indigo를 기반으로 새 색상을 만들지만 채도를 25%로 설정합니다.

.desaturate-to-25 {
  background: hsl(from indigo h 25% l);
}

크로마로 색상을 보강합니다.

이 효과는 색상 채도와 비슷하지만 몇 가지 차이점이 있습니다. 첫째, saturation 변경이 아닌 chroma 변경입니다. 이는 높은 동적 범위로 부스트할 수 있는 색상 공간이 채도를 사용하지 않기 때문입니다. chroma를 특징으로 하는 색상 공간은 높은 동적 범위를 사용할 수 있으므로 작성자가 채도보다 더 높은 색 선명도를 높일 수 있습니다.

.increase-chroma {
  background: oklch(from orange l calc(c + .1) h);
}

색상 불투명도 조정

색상의 반투명 변형을 만드는 것은 디자인 시스템에서 실행되는 가장 일반적인 색상 조정 중 하나입니다. 이 문서 도입부의 예를 놓쳤다면 문제 영역을 잘 설명합니다.

불투명도 조정

.decrease-opacity-by-25 {
  background: rgb(from lime r g b / calc(alpha / 2));
}

불투명도를 특정 값으로 조정

.decrease-opacity-to-25 {
  background: rgb(from lime r g b / 25%);
}

색상 반전

색상 반전은 색상 라이브러리에서 찾을 수 있는 일반적인 색상 조정 함수입니다. 이렇게 하는 한 가지 방법은 색상을 RGB로 변환한 후 각 채널의 값을 1에서 빼는 것입니다.

.invert-each-rgb-channel {
  background: rgb(from yellow calc(255 - r) calc(255 - g) calc(255 - b));
}

색상 보완

색상을 반전시키는 것이 아니라 보완하는 것이 목표라면 색조 회전을 사용하는 것이 좋습니다. 색조를 각도로 제공하는 색상 공간을 선택한 다음 calc()를 사용하여 색조를 원하는 만큼 회전합니다. 색상의 보색은 0.5바퀴 회전하여 찾을 수 있습니다. 이 경우 180을 기준으로 h 채널에 더하거나 빼서 결과를 얻을 수 있습니다.

.complementary-color {
  background: hsl(from blue calc(h + 180) s l);
}

색상 대비

액세스 가능한 색상 명암비를 달성하는 방법으로 L&midast; (Lstar)를 고려해 보세요. 이는 calc()에서 LCH 및 OKLCH의 (대략적으로) 균일한 밝기 (L) 채널을 사용합니다. 저대비, 중간 대비, 높은 대비를 타겟팅하는지에 따라 L&midast; 델타는 약 40, 50 또는 60입니다.

이 기법은 LCH 또는 OKLCH의 모든 색조에서 잘 작동합니다.

어두운 색상 대비

.well-contrasting-darker-color 클래스는 델타 60으로 L* 를 보여줍니다. 원래 색상이 어두운 색상 (낮은 값 밝기)이므로 밝기 채널에 60% (.6)가 추가됩니다. 이 기법은 밝은 배경에서 잘 대비되는 색조의 어두운 텍스트 색상을 찾는 데 사용됩니다.

.well-contrasting-darker-color {
  background: darkred;
  color: oklch(from darkred calc(l + .60) c h);
}

밝은 색상 대비

.well-contrasting-lighter-color 클래스는 60%의 델타로 L* 를 보여줍니다. 원래 색상은 밝은 색상 (높은 값의 밝기)이므로 밝기 채널에서 .60을 뺍니다.

.well-contrasting-lighter-color {
  background: lightpink;
  color: oklch(from lightpink calc(l - .60) c h);
}

색상 팔레트

상대적 색상 구문은 색상 팔레트를 만드는 데 매우 유용합니다. 이는 사용할 수 있는 색 공간의 수로 인해 특히 유용하고 강력합니다. 다음 예에서는 모두 OKLCH를 사용합니다. 밝기 채널이 안정적이고 색조 채널은 부작용 없이 회전할 수 있기 때문입니다. 마지막 예에서는 좀 더 흥미로운 결과를 얻기 위해 밝기와 색조 회전 조정의 조합을 보여줍니다.

이에 대한 소스 코드 예를 열고 --base-color를 변경하여 팔레트가 얼마나 동적인지 확인합니다. 재미있어!

동영상을 좋아하신다면 YouTube에서 OKLCH를 사용하여 CSS로 색상 팔레트를 만드는 방법을 자세히 알아보세요.

단색 팔레트

단색 팔레트를 만들려면 동일한 색조이지만 밝기와 어두움이 다양한 팔레트를 만들어야 합니다. 가운데 색상은 팔레트의 소스 색상으로, 밝은 색상의 변형 2개와 어두운 변형 2개가 양쪽에 배치됩니다.

:root {
  --base-color: deeppink;

  --color-0: oklch(from var(--base-color) calc(l + .20) c h); /* lightest */
  --color-1: oklch(from var(--base-color) calc(l + .10) c h);
  --color-2: var(--base-color);
  --color-3: oklch(from var(--base-color) calc(l - .10) c h);
  --color-4: oklch(from var(--base-color) calc(l - .20) c h); /* darkest */
}
상대 색상 구문과 OKLCH로 만든 여러 팔레트를 사용해 보세요.

무료 CSS 변수 라이브러리인 Open Props는 이 전략으로 빌드된 색상 팔레트를 제공하며 가져오기를 통해 쉽게 사용할 수 있습니다. 또한 모두 맞춤설정할 수 있는 색상으로 구성되어 있습니다. 색상을 지정하기만 하면 됩니다.

유사한 팔레트

OKLCH 및 HSL을 사용하면 색조 회전이 매우 쉬우므로 유사한 색상 팔레트를 만드는 것은 쉽습니다. 결과에 원하는 만큼 색조를 회전하고 기본 색상을 변경한 다음 브라우저에서 새 팔레트가 생성되는지 확인합니다.

:root {
  --base-color: blue;

  --primary:   var(--base-color);
  --secondary: oklch(from var(--base-color) l c calc(h - 45));
  --tertiary:  oklch(from var(--base-color) l c calc(h + 45));
}

삼원 팔레트

보색 색상과 마찬가지로 삼원색 색상 팔레트는 기본 색상을 기반으로 반대편이지만 조화로운 색조 회전입니다. 색상환의 가운데를 통해 그려진 직선처럼 보색이 색상의 반대 면에 있는 경우, 삼각 팔레트는 기본 색상에서 동일하게 회전된 두 색상을 찾는 삼각형 선과 같습니다. 이렇게 하려면 색조 120deg를 회전합니다.

이 방법은 색상 이론을 약간 단순화한 것입니다. 관심이 있다면 더 복잡한 3원소 팔레트를 시작하는 것으로 충분합니다.

:root {
  --base-color: yellow;
  --triad-1: oklch(from var(--base-color) l c calc(h - 120));
  --triad-2: oklch(from var(--base-color) l c calc(h + 120));
}

사각팔레트

사각색 팔레트는 색상환 주위에 고르게 나뉘어 있는 4개의 색상으로, 명확한 주요 값이 없는 팔레트를 만듭니다. 두 쌍의 보색처럼 생각할 수도 있습니다. 현명하게 사용하면 큰 효과를 볼 수 있습니다.

이는 색 이론을 약간 단순화한 것입니다. 하지만 관심이 있다면 더 복잡한 4가지 팔레트를 시작하는 것으로 충분합니다.

:root {
  --base-color: lime;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) l c calc(h + 90));
  --color-3: oklch(from var(--base-color) l c calc(h + 180));
  --color-4: oklch(from var(--base-color) l c calc(h + 270));
}

약간의 색조 회전이 있는 단색

많은 색상 전문가들은 이 묘기를 잘 알고 있습니다. 문제는 단색 색상 스케일은 상당히 지루할 수 있다는 것입니다. 해결 방법은 밝기가 변경될 때마다 새 색상에 작은 또는 주요 색조 회전을 추가하는 것입니다.

다음 예에서는 견본마다 밝기를 10% 낮추고 색조를 10도 회전합니다. 그 결과 그라데이션처럼 매끄럽게 섞인 남색 팔레트가 만들어집니다.

:root {
  --base-color: deeppink;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) calc(l - .10) c calc(h - 10));
  --color-3: oklch(from var(--base-color) calc(l - .20) c calc(h - 20));
  --color-4: oklch(from var(--base-color) calc(l - .30) c calc(h - 30));
  --color-5: oklch(from var(--base-color) calc(l - .40) c calc(h - 40));
}
OKLCH 및 색조 회전으로 빌드된 리더보드를 사용해 보세요.

다음 리더보드 인터페이스는 이 색조 순환게재 전략을 사용합니다. 각 목록 항목은 문서의 색인을 --i라는 변수로 추적합니다. 그런 다음 이 색인은 크로마, 밝기, 색조를 조정하는 데 사용됩니다. 조정은 5% 또는 5deg 차이로, 딥핑크를 사용한 위의 예보다 훨씬 더 섬세하므로 이 리더보드가 이렇게 우아한 색조를 어떤 색으로든 알 수 있는 이유를 눈여겨보아야 합니다.

리더보드 아래의 슬라이더에서 색조를 변경하고, 상대적인 색상 구문이 아름다운 색상 순간을 만드는지 확인하세요.

li {
  --_bg: oklch(
    /* decrease lightness as list grows */
    calc(75% - (var(--i) * 5%))

    /* decrease chroma as list grows */
    calc(.2 - (var(--i) * .01))

    /* lightly rotate the hue as the list grows */
    calc(var(--hue) - (var(--i) + 5))
  );
}