다른 색상의 채널과 값을 기반으로 새 색상을 만듭니다.
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
키워드 뒤에 오는 색상입니다. 브라우저는 이 원래 색상을 변환하여 분해하고 새 색상 정의에 사용할 수 있도록 변수로 제공합니다.
위의 다이어그램은 원래 색상 green
가 새 색상의 색상 공간으로 변환되고 r
, g
, b
, alpha
변수로 표시되는 개별 숫자로 변환된 후 새 rgb()
색상의 값으로 직접 사용되는 것을 보여줍니다.
이 이미지는 분류, 프로세스, 변수를 보여주지만 색상도 변경하지 않습니다. 변수는 변경되지 않은 색상으로 다시 바뀌므로 여전히 녹색이 됩니다.
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가 색상(다음 색상의 영감을 줄 색상)을 예상합니다.
색상 변환
간단히 말해 녹색을 새로운 색상에 사용할 수 있도록 r, g, 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 */
}
사용 사례 및 데모
다음 예시와 사용 사례에는 유사하거나 동일한 결과를 얻기 위한 여러 대체 문법이 있습니다. 이러한 변형은 색상 공간과 색상 공간에서 제공하는 채널에서 비롯됩니다.
또한 많은 예시에서 by
및 to
라는 표현으로 색상 조정을 보여줍니다. 색상 변경 by
은 상대 색상 변경입니다. 변수의 값을 사용하고 현재 값을 기반으로 조정하는 변경입니다. 색상 변경 to
은 절대 색상 변경입니다. 변수의 값을 사용하지 않고 완전히 새로운 값을 지정하는 변경입니다.
모든 데모는 이 Codepen 컬렉션에서 확인할 수 있습니다.
색상 밝게 하기
OKLCH, OKLAB, XYZ 또는 sRGB 색상 공간은 색상을 밝게 할 때 가장 예측 가능한 결과를 제공합니다.
금액만큼 밝게 지정
다음 예 .lighten-by-25
는 색상 blue
을 가져와 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
를 사용하여 orchid
의 바이브런스를 상대 50%
만큼 증가시킵니다.
.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-half
에서는 hsl()
의 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()
를 사용하여 원하는 만큼 색조를 회전합니다.
색상의 보색을 찾으려면 반바퀴 회전하면 됩니다. 이 경우 h
채널에서 180
를 더하거나 빼면 결과를 얻을 수 있습니다.
.complementary-color {
background: hsl(from blue calc(h + 180) s l);
}
색상 대비
접근 가능한 색상 대비율을 달성하는 방법으로 L* (Lstar)를 고려하세요.
이는 calc()
에서 LCH 및 OKLCH의 (대략적으로) 지각적으로 균일한 밝기 (L) 채널을 사용합니다. 저대비, 중간 대비, 고대비 중 어느 것을 타겟팅하는지에 따라 L* delta는 약 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));
}
삼각 팔레트
보색과 마찬가지로 삼색 색상 팔레트는 기본 색상이 주어지면 서로 반대되지만 조화로운 색조 회전입니다. 보완 색상이 색상의 반대쪽에 있는 경우(예: 색상환의 가운데를 통과한 직선) 3색 팔레트는 선의 삼각형과 같아 기본 색상에서 동일한 두 색상을 균등하게 회전합니다.
색조 120deg
를 회전하여 이 작업을 실행합니다.
이는 색상 이론을 약간 단순화한 것이지만 관심이 있다면 더 복잡한 삼각 팔레트를 시작하는 데 충분합니다.
: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% 또는 5도에 불과하므로 위의 deeppink 예시보다 훨씬 미묘합니다. 따라서 이 리더보드가 우아하게 어떤 색조로든 표시될 수 있는 이유를 알아보기 위해서는 날카로운 눈이 필요합니다.
리더보드 아래의 슬라이더에서 색조를 변경하고 상대 색상 문법이 아름다운 색상 순간을 만들어내는 것을 확인하세요.
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))
);
}