1. 소개
이 섹션은 규범적이지 않습니다.
이 모듈은 새로운 함수 contrast-color(), color-mix() 및 light-dark()를 추가하고, 기존 함수에는 상대 색상 구문을 확장합니다.
또한 color() 함수도 확장하여 미리 정의된 색상 공간뿐만 아니라, ICC 프로필로 정의된 커스텀 색상 공간(계측된 CMYK 포함)도 CSS에서 사용할 수 있게 합니다.
그리고 device-cmyk를 추가하여, 교정되지 않은 cmyk 색상의 표현도 지원합니다.
2. <color> 문법
CSS의 색상은 <color> 타입으로 표현됩니다:
<color> = <color-base> | currentColor | <system-color> |
<contrast-color()> | <device-cmyk()> | <light-dark-color>
<color-base> = <hex-color> | <color-function> | <named-color> | <color-mix()> | transparent
<color-function> = <rgb()> | <rgba()> |
<hsl()> | <hsla()> | <hwb()> |
<lab()> | <lch()> | <oklab()> | <oklch()> |
<alpha()> |
<color()>
절대 색상은 계산 결과가 절대적이고 색상 계측이 가능한 의미를 갖는 <color> 값입니다. 즉, 값이 다음과 같지 않음을 의미합니다:
-
currentColor (이 값은 color 속성 값에 따라 달라짐)
-
<system-color> (색상 모드에 따라 달라짐)
-
<light-dark-color> (색상 모드에 따라 달라짐)
-
<contrast-color()> (색상 모드에 따라 달라짐)
-
<device-cmyk()> (색상 계측 기준이 없음)
위 값들은 <color-mix()> 나 상대 색상 구문 내에서도 사용할 수 없습니다.
sRGB로 해석되는 색상은 다음과 같습니다:
레거시 색상 문법을 지원하는 함수는 다음과 같습니다:
<hsl()>, <hsla()>, <hwb()>, <lch()>, <oklch()> 색상 함수는 원통 극(극좌표형) 색상 표현을 <hue> 각도로 사용합니다. 나머지 색상 함수는 직교 직사각형 색상 표현을 사용합니다.
3. 색상 혼합: color-mix() 함수
웹 개발자, 디자인 도구 및 디자인 시스템 개발자는 컴포넌트 컬러 관계의 스케일링에 색상 함수를 자주 사용합니다. 여러 플랫폼과 다양한 사용자 취향을 지원하는 디자인 시스템, 그리고 UI의 다크 모드 등 기능이 늘어나면서, 색상을 일일이 수동으로 지정하지 않고 계산 가능한 단일 소스를 활용해 스킴을 생성하는 것이 더욱 유용해졌습니다.

현재는 Sass, HSL 값의 calc(), 혹은 PostCSS 등을 활용합니다. 하지만 전처리기는 동적으로 조정된 색상에는 작동하지 못하며, 현존하는 모든 솔루션은 sRGB 색영역과 HSL의 지각적 한계(컬러 휠에서 색상이 뭉쳐지고, 노랑과 파랑처럼 시각적으로 매우 다른 명도도 HSL에서는 같은 lightness를 가질 수 있음)에 제한됩니다.
이 요구를 충족하기 위해 color-mix() 함수는 하나 이상의 <color> 명세 리스트를 받아, 지정한 <color-space> 및 지정한 비율로 혼합한 결과를 반환합니다.
color-mix() = color-mix( <color-interpolation-method>? , [ <color> && <percentage [0,100]>? ]#)
테스트
3.1. 혼합 색상 공간
색상 보간법을 지정하지 않으면 Oklab을 사용합니다. 그렇지 않으면, 지정된 색상 공간으로 혼합하십시오.
3.2. 백분율 정규화
백분율(percent)은 0%에서 100% 사이여야 합니다. 음수 백분율은 명시적으로 허용되지 않습니다. 백분율은 혼합 비율 정규화에 따라 정규화됩니다.
color-mix ( in lch, purple50 % , plum50 % ) color-mix ( in lch, purple50 % , plum) color-mix ( in lch, purple, plum50 % ) color-mix ( in lch, purple, plum) color-mix ( in lch, plum, purple) color-mix ( in lch, purple80 % , plum80 % )
모두 purple과 plum을 lch에서 50-50으로 혼합한 결과를 만듭니다: lch(51.51% 52.21 325.8) 또는 rgb(68.51% 36.01% 68.29%).
하지만 알파가 1보다 작아서, 다음 경우는 동일하지 않습니다:
color-mix ( in lch, purple30 % , plum30 % )
이 경우 lch(51.51% 52.21 325.8 / 0.6) 또는 rgb(68.51% 36.01% 68.29% / 0.6)입니다.
3.3. color-mix 결과 계산
-
함수에 전달된 혼합 항(mix item) 리스트로부터, 혼합 비율을 정규화(normalize)합니다. "강제 정규화" 플래그는 true로 하며, 이때 items와 leftover가 그 결과입니다.
-
leftover가 100%이면, 지정한 보간 <color-space>로 변환한 투명 검정(transparent black)을 반환합니다.
-
alpha mult를
1 - leftover(leftover는 0~1의 수 해석)로 설정. -
items의 길이가 1일 경우 그 유일한 항의 색상을 지정된 보간 <color-space>로 변환해 color에 설정합니다.
그렇지 않은 경우:
-
item stack을 스택으로 두고, items를 역순으로 쌓습니다. (첫 번째 항이 스택 맨 위)
-
item stack의 길이가 2 이상일 동안:
-
stack pop을 두 번 하여 a와 b에 저장. combined percentage는 a와 b의 백분율의 합.
-
CSS Color 4 § 13. 색상 보간에 따라, a와 b의 색상을 보간합니다. 진행 퍼센트는
(b의 백분율) / combined percentage. 색상 공간이 원통 극 색상(cylindrical polar color)인 경우 <hue-interpolation-method> 로 hue 보간 방식을 지정함 (CSS Color 4 § 13.4 hue 보간 참조). <hue-interpolation-method>가 없으면 shorter를 사용합니다. -
결과 색상과 combined percentage의 백분율을 가진 mix item을 새로 만들고, push로 item stack에 쌓습니다.
-
-
마지막 1개 항의 색상을 color에 설정합니다.
-
-
color의 알파 컴포넌트에 alpha mult를 곱합니다.
-
color를 반환합니다.
참고: 원통 극 색상(cylindrical polar color) 공간에서는 혼합 순서에 따라 결과가 다릅니다. hue 원(circle)을 "짧게(shorter)" 혹은 "길게(longer)" 도는 방향이 그 전에 어떤 혼합이 이루어졌느냐에 따라 달라질 수 있기 때문입니다. 이 알고리즘은 지정된 순서대로 각각의 색상을 혼합하며, 그 결과를 리스트의 다음 값과 섞습니다. 직교 직사각형 색상 공간에서는 순서와 관계없이 계산할 수 있습니다.
테스트
- color-mix-basic-001.html (실시간 테스트) (소스)
- color-mix-missing-components.html (실시간 테스트) (소스)
- color-mix-non-srgb-001.html (실시간 테스트) (소스)
- color-computed-color-mix-function.html (실시간 테스트) (소스)
- color-invalid-color-mix-function.html (실시간 테스트) (소스)
- color-valid-color-mix-function.html (실시간 테스트) (소스)
- color-mix-out-of-gamut.html (실시간 테스트) (소스)
- 2d.fillStyle.colormix.html (실시간 테스트) (소스)
- 2d.fillStyle.colormix.currentcolor.html (실시간 테스트) (소스)
- 2d.strokeStyle.colormix.html (실시간 테스트) (소스)
color-mix ( in lch, peru40 % , palegoldenrod)
혼합은 lch 색 공간에서 이루어집니다. 아래는 L(명도) 축을 따라 위에서 내려 본 ab 평면 그림입니다:
계산은 다음과 같습니다:
-
peru는 lch(62.253% 54.011 63.677)
-
palegoldenrod는 lch(91.374% 31.406 98.834)
-
혼합 명도(lightness)는 62.253 * 40/100 + 91.374 * (100-40)/100 = 79.7256
-
혼합 chroma는 54.011 * 40/100 + 31.406 * (100-40)/100 = 40.448
-
혼합 hue는 63.677 * 40/100 + 98.834 * (100-40)/100 = 84.771
-
혼합 결과는 lch(79.7256% 40.448 84.771)
참고: hue와 chroma를 보간하면 중간 색상들도 엔드포인트 색상만큼 채도가 보존됩니다.
color-mix ( in lch, teal65 % , olive);
계산은 다음과 같습니다:
-
sRGB teal (#008080)은 lch(47.9855% 31.6903 196.4524)
-
sRGB olive (#808000)은 lch(52.1496% 56.8124 99.5746)
-
혼합 lightness: 47.9855 * 0.65 + 52.1496 * 0.35 = 49.4429
-
혼합 chroma: 31.6903 * 0.65 + 56.8124 * 0.35 = 40.4830
-
혼합 hue: 196.4524 * 0.65 + 99.5746 * 0.35 = 162.5452
-
혼합 결과는 lch(49.4429% 40.4830 162.5452)
-
약간 푸른빛이 도는 초록색: rgb(7.7377% 52.5730% 37.3213%)
color-mix ( in oklch, teal0 % , olive0 % );
따라서 결과는 oklch 색상 공간의 투명 검정입니다:
oklch(0% 0 none / 0)
color-mix ( in oklab, teal, olive, blue);
계산은 다음과 같습니다:
-
teal (#008080)은 oklab(54.31% -0.0896 -0.0236)
-
olive (#808000)은 oklab(58.07% -0.0428 0.1191)
-
blue (#0000FF)는 oklab(45.20% -0.0325 -0.3115)
-
혼합 lightness: (54.31 + 58.07 + 45.20) / 3 = 52.53%
-
혼합 a: (-0.0896 + -0.0428 + -0.0325) / 3 = -0.0550
-
혼합 b: (-0.0236 + 0.1191 + -0.3115) / 3 = -0.0720
-
혼합 결과: oklab(52.53% -0.0550 -0.0720)
3.4. 혼합 색상 공간이 color-mix에 미치는 영향
혼합에 사용하는 색상 공간의 선택은 최종 결과에 큰 영향을 줄 수 있습니다.
color-mix ( in lch, white, black); color-mix ( in xyz, white, black); color-mix ( in srgb, white, black);
계산 과정은 다음과 같습니다:
-
sRGB white (#FFF)는 lch(100% 0 0)입니다
-
sRGB black (#000)는 lch(0% 0 0)입니다
-
LCH에서 혼합: lch(50% 0 0)
-
XYZ에서 혼합: lch(76% 0 0)
-
sRGB에서 혼합: lch(53.4% 0 0)
LCH에서 혼합하면 L값이 50%로, 완벽하게 중간 회색(middle gray)이 되어 예상과 딱 맞게 결과가 나옵니다. (Lab에서 혼합해도 동일하며, LCH와 Lab의 Lightness 축은 동일)
XYZ에서 혼합한 결과는 너무 밝게 나옵니다. XYZ는 선형-광도(linear-light)이지만 지각적으로 균등하지 않습니다. sRGB에서 혼합한 결과도 다소 밝으며, sRGB는 지각적으로 균등하지도 않고 선형-광도도 아닙니다.
color-mix ( in xyz, rgb ( 82.02 % 30.21 % 35.02 % ) 75.23 % , rgb ( 5.64 % 55.94 % 85.31 % ));
계산 과정은 다음과 같습니다:
-
rgb(82.02% 30.21% 35.02%) 는 lch(52% 58.1 22.7)이고 X=0.3214, Y=0.2014, Z=0.0879입니다.
-
rgb(5.64% 55.94% 85.31%) 는 lch(56% 49.1 257.1)이고 X=0.2070, Y=0.2391, Z=0.5249입니다.
-
혼합 결과 X=(0.3214 * 0.7523) + (0.2070 * (1 - 0.7523)) = 0.29306.
-
혼합 결과 Y=(0.2014 * 0.7523) + (0.2391 * (1 - 0.7523)) = 0.21074.
-
혼합 결과 Z=(0.0879 * 0.7523) + (0.5249 * (1 - 0.7523)) = 0.19614.
-
혼합 결과는 lch(53.0304% 38.9346 352.8138), 즉 rgb(72.300% 38.639% 53.557%)
이 예시는 흰색과 파란색을 세 가지 색상 공간에서 50%로 혼합한 결과입니다.
color-mix ( in lch, white, blue); color-mix ( in oklch, white, blue); color-mix ( in srgb, white, blue);
계산 과정은 다음과 같습니다:
-
white 는 rgb(100% 100% 100%) → lch(100% 0 none) → oklch(100% 0 none)
-
blue 는 rgb(0% 0% 100%) → lch(29.5683% 131.201 301.364) → oklch(45.201% 0.31321 264.052)
-
lch에서 혼합: lch(64.7841% 65.6008 301.364), 다소 보라색으로 나타납니다
-
oklch에서 혼합: oklch(72.601% 0.15661 264.052)
-
srgb에서 혼합: rgb(50% 50% 100%), 역시 다소 보라색
color-mix ( in hsl, color ( display-p30 1 0 ) 80 % , yellow);
계산 과정은 다음과 같습니다:
-
color(display-p3 0 1 0) 은 color(srgb -0.5116 1.01827 -0.3107)로 변환되며 이는 sRGB 색역을 벗어남
-
이를 hsl로 변환하면 hsl(127.879 301.946 25.334)
-
yellow는 hsl(60 100% 50%)
-
hue는 127.879 × 0.8 + 60 × 0.2 = 114.3032
-
saturation은 301.946 × 0.8 + 100 × 0.2 = 261.5568
-
lightness는 25.334 × 0.8 + 50 × 0.2 = 30.2672
-
혼합 결과는 hsl(114.3032 261.5568 30.2672), color(srgb -0.3387 1.0943 -0.48899)
color-mix ( in lab, device-cmyk ( 0.091777 0.043303 0.312816 0.000000 ) 100 % , yellow);
첫 번째 색상이 100%이므로, 두 번째 색상은 0%로 혼합 결과에 영향을 주지 않습니다. 따라서 결과는 첫 번째 색상을 CIE Lab에서 계산한 값입니다.
결과 시각화를 위해 device CMYK 값이 실제로 SWOP 2006 coated로 인쇄되는 상황을 상정합니다.
-
device-cmyk(0.091777 0.043303 0.312816 0.000000)은 lab(91.44% 4.142 20.52)
만약 구현이 ICC 프로필을 사용해서 lab() 색상을 얻는다면, 이 예시는 FOGRA39 Coated 프로파일을 사용합니다:
-
device-cmyk(0.091777 0.043303 0.312816 0.000000)은 lab(91.840596 -3.559090 20.449159)
-
이 값과 원래 인쇄 색상 사이의 deltaE 2000은 8.17로 확연히 보입니다.
다른 구현체가 단순 색 변환 알고리즘(naive conversion)으로 sRGB 결과만 반환하는 경우도 상상할 수 있습니다.
-
device-cmyk(0.091777 0.043303 0.312816 0.000000)은 rgb(90.8223% 95.6697% 68.7184%) 즉 lab(94.02% -12.31 31.79)
-
이 값과 원래 인쇄 색상 사이의 deltaE 2000은 14.3으로 매우 도드라집니다.
3.5. 1이 아닌 알파(alpha)가 color-mix에 미치는 영향
지금까지 color-mix() 예시는 모두 완전히 불투명한 색상만 사용했습니다. 예시를 단순화하기 위해, 사전 곱(premultilication) 및 역사전 곱(unpremultiplied) 과정은 생략되었습니다. 이유는 이 경우 알파가 1이어서 단순히 1 곱하고 1로 나누는 셈이 되기 때문입니다.
일반적으로는 색상이 1이 아닌 알파(alpha) 값을 가질 수 있으므로 사전 곱(premultiply), 보간, 역사전 곱 언패킹 과정이 반드시 생략되어서는 안 됩니다.
color-mix ( in srgb, rgb ( 100 % 0 % 0 % /0.7 ) 25 % , rgb ( 0 % 100 % 0 % /0.2 ));
계산 과정은 다음과 같습니다:
-
rgb(100% 0% 0% / 0.7) 사전 곱하면 [0.7, 0, 0]
-
rgb(0% 100% 0% / 0.2) 사전 곱하면 [0, 0.2, 0]
-
사전 곱 후 보간 결과: [0.7 * 0.25 + 0 * (1 - 0.25), 0 * 0.25 + 0.2 * (1 - 0.25), 0 * 0.25 + 0 * (1 - 0.25)] → [0.175, 0.150, 0]
-
보간된 알파: 0.7 * 0.25 + 0.2 * (1 - 0.25) = 0.325
-
역사전 곱 결과: [0.175 / 0.325, 0.150 / 0.325, 0 / 0.325] → [0.53846, 0.46154, 0]
-
따라서 혼합 색상은 color(srgb 0.53846 0.46154 0 / 0.325)
잘못된 계산 방식은 다음과 같습니다:
-
보간 결과: [1 * 0.25 + 0 * (1 - 0.25), 0 * 0.25 + 1 * (1 - 0.25), 0 * 0.25 + 0 * (1 - 0.25)] → [0.25, 0.75, 0]
-
잘못된 혼합 색상은 color(srgb 0.25 0.75 0 / 0.325)
이는 아주 큰 차이입니다. 올바른 결과와 잘못된 결과의 ΔE2000은 30.7!
백분율 정규화에서 알파 승수(alpha multiplier)가 생성되면, 계산은 아래 추가 마지막 단계만 빼고 모두 동일합니다.
여기서는 첫 색상이 20%, 두 번째는 60%로 지정되었습니다. 합이 80%이므로 알파 승수는 0.8입니다.
혼합 비율은 100/80을 곱해 정규화됩니다:
20% * 100/80 = 25%
60% * 100/80 = 75%
최종 혼합 비율은 앞 사례와 동일해집니다.
color-mix ( in srgb, rgb ( 100 % 0 % 0 % /0.7 ) 20 % , rgb ( 0 % 100 % 0 % /0.2 ) 60 % );
계산 과정은 다음과 같습니다:
-
rgb(100% 0% 0% / 0.7) 사전 곱하면 [0.7, 0, 0]
-
rgb(0% 100% 0% / 0.2) 사전 곱하면 [0, 0.2, 0]
-
사전 곱 후 보간 결과: [0.7 * 0.25 + 0 * (1 - 0.25), 0 * 0.25 + 0.2 * (1 - 0.25), 0 * 0.25 + 0 * (1 - 0.25)] → [0.175, 0.150, 0]
-
보간된 알파: 0.7 * 0.25 + 0.2 * (1 - 0.25) = 0.325
-
역사전 곱 결과: [0.175 / 0.325, 0.150 / 0.325, 0 / 0.325] → [0.53846, 0.46154, 0]
-
따라서 혼합 색상은 color(srgb 0.53846 0.46154 0 / 0.325)
-
여기에 0.8 알파 승수가 적용되므로, 혼합 결과의 알파는 0.325 * 0.8 = 0.260 즉 최종 색상은 color(srgb 0.53846 0.46154 0 / 0.260)
참고: 보간된 알파에 알파 승수를 곱한 뒤, 그 값으로 역사전 곱을 하면 안 됩니다. 혼합 비율을 100%로 정규화하지 않는다면 그 방법이 맞지만, 여기서는 정규화하므로 이렇게 하면 혼합 색상이 이중으로 조정돼 버립니다.
4. 상대 색상
4.1. 상대 색상에 대한 처리 모델
이 명세의 이전 레벨에서는 색상 함수를 통해 각 색상 성분을 직접 지정하는 절대적인 방식만 허용되었습니다.
새로운 상대 색상(relative color) 구문은 현대 색상 구문을 확장합니다. 즉, 기존 색상을 색상 함수에서 변경할 수 있게 해줍니다. 원본 색상(origin color)이 지정되면, 각 색상 성분(및 알파 값까지) 직접 지정하거나 원본 색상에서 가져오거나 (그리고 수학 함수로 조정)할 수 있습니다.
원본 색상과 상대 색상은 동일한 색상 함수를 사용하지 않아도 됩니다.
필수 변환(Required conversion): 모든 연산은 상대 색상 함수의 색상 공간에서 수행됩니다. 만일 원래 지정된 색상 공간(originally specified color space) 을 가진 원본 색상이 다른 색상 함수였다면, 반드시 선택한 색상 함수로 변환해야 합니다. 그래야 그 구성 요소 값이 의미를 가지며, 구성 요소 키워드도 원본 색상이 아니라 상대 색상 함수를 기준으로 적용됩니다.
상대 색상의 알파 값이 명시되지 않으면, 원본 색상의 알파가 기본값입니다 (절대 구문과 달리 100%가 아닙니다).
상대 색상 구문을 사용할 때는, 색상 성분 값은 직접 지정하든 색 공간 변환에서 나오든 기준 레인지로 클램프(clamp)하지 않고 그대로 남아 있게 됩니다. 그래서 대상 색상 공간이 표현할 수 있으면, 색역 밖(out of gamut) 값도 보존됩니다.
그러나 상대 색상 구문을 사용할 때, 알파(투명도) 성분 값은 직접 지정됐든 변환됐든 반드시 기준 레인지로 클램프됩니다.
컴포넌트가 빠진 경우는 CSS Color 4 § 13.2 Interpolating with Missing Components와 동일하게 처리합니다: 원본 색상 공간과 상대 함수 색상 공간 모두 유사 성분(analogous components)을 확인해 forward로 넘깁니다.
대부분의 상대 색상 구문 활용은 구성 요소 키워드를 해당 인자(argument) 위치에 쓰지만, 어느 위치에서도 사용할 수 있습니다.
구성 요소를 기본 위치가 아닌 곳에 쓰면 주의해야 합니다. 만일 %값이 숫자로 변환되어 다른 위치에서 쓰일 때에는 "매직 스케일(magic scaling)"이 없어 의도와 달라질 수 있습니다.
device-cmyk()는 상대 구문이 없습니다.
4.2. 상대 색상 구문(Relative Color Syntax)
각 함수가 상대 색상 을 수용하도록 구문이 어떻게 확장되는지의 구체적인 내용은 아래와 같지만, 모두 공통 구조를 따릅니다:
-
원본 색상(origin color)은 함수 시작에 from <color> 값을 넣어서 지정할 수 있습니다. 지정하면 선택적 알파 값도 포함할 수 있습니다.
-
원본 색상을 지정하지 않으면, 해당 함수는 상대 색상이 아닙니다.
-
원본 색상이 지정되면, 나머지 인자는 평소처럼 직접 지정하거나, 구성 요소 키워드(component keyword) 로 원본 색상의 해당 컴포넌트 값을, 상대 색상의 색상 공간으로 변환한 값으로 지정할 수도 있습니다. 수학 함수(Math functions) 역시 이 키워드를 써서 원본 색상 컴포넌트를 동적으로 변형할 수 있습니다.
-
상대 색상 구문은, 인자가 필수인지 옵션인지는 영향을 주지 않습니다.
-
상대 색상 구문은 반드시 현대(Modern) 색상 구문에만 적용됩니다. 절대 레거시 색상 구문에는 사용할 수 없으며, 그렇게 시도하면 오류입니다.
-
단, 원본 색상 지정에는 모던 또는 레거시 구문 모두 사용할 수 있습니다.
구성요소 키워드는 <number> 또는 none을 반환한다; 원래 <percentage> 또는 <angle>로 지정된 경우, 그 <percentage>는 <number>로 해석되고 <angle>는 범위 [0, 360] 안의 도 단위 <number>로 해석된다 (이는 표준 단위이다).
테스트
- relative-color-with-zoom.html (live test) (source)
- relative-currentcolor-a98rgb-01.html (live test) (source)
- relative-currentcolor-lch-01.html (live test) (source)
- relative-currentcolor-rgb-01.html (live test) (source)
- relative-currentcolor-displayp3-01.html (live test) (source)
- relative-currentcolor-oklab-01.html (live test) (source)
- relative-currentcolor-rgb-02.html (live test) (source)
- relative-currentcolor-hsl-01.html (live test) (source)
- relative-currentcolor-oklch-01.html (live test) (source)
- relative-currentcolor-xyzd50-01.html (live test) (source)
- relative-currentcolor-hsl-02.html (live test) (source)
- relative-currentcolor-prophoto-01.html (live test) (source)
- relative-currentcolor-xyzd65-01.html (live test) (source)
- relative-currentcolor-hwb-01.html (live test) (source)
- relative-currentcolor-rec2020-01.html (live test) (source)
- relative-currentcolor-lab-01.html (live test) (source)
- relative-currentcolor-rec2020-02.html (live test) (source)
- relative-currentcolor-visited-getcomputedstyle.html (live test) (source)
- alpha-color-computed.html (live test) (source)
- alpha-color-parsing-invalid.html (live test) (source)
- alpha-color-parsing-valid.html (live test) (source)
- color-computed-relative-color.html (live test) (source)
- color-invalid-relative-color.html (live test) (source)
- color-valid-relative-color.html (live test) (source)
- relative-color-out-of-gamut.html (live test) (source)
html{ --bluegreen : oklab ( 54.3 % -22.5 % -5 % ); } .overlay{ background : oklab ( fromvar ( --bluegreen) calc ( 1.0 - l) calc ( a *0.8 ) b); }
이 예시에서 지정된 %값은 숫자로 변환되어, oklab(0.543 -0.09 -0.02)이 됩니다. RCS 결과색은 l = 1 - 0.543 = 0.457, a = -0.09 * 0.8 = -0.072, b는 -0.02로 그대로: oklab(0.457 -0.072 -0.02)이 됩니다.
html{ --base : oklch ( 52.6 % 0.115 44.6 deg ) } .summary{ background : oklch ( fromvar ( --base) l ccalc ( h +90 )); }
이 예시의 RCS 결과는 oklch(0.526 0.115 134.6)입니다.
만약 원본 색상각 <angle>가 라디안(radian) 또는 turn 등 다른 단위였다 해도, 변환된 <number> 는 각도(degree) 값이 됩니다.
html{ --color : green; } .foo{ --darker-accent : lch ( fromvar ( --color) calc ( l /2 ) c h); }
이 예시에서는 원본 색상의 명도(lightness)만 절반으로 낮춰 색상을 어둡게 했습니다. 나머지 성분은 그대로 유지됩니다.
참고로 원본 색상은 색상 키워드(sRGB)이지만, lch() 함수에서 사용되므로 자동으로 LCH 색상으로 해석됩니다.
html{ --bg-color : blue; } .overlay{ background : rgb ( fromvar ( --bg-color) r g b /80 % ); }
이 예시에서 원본 색상의 r, g, b 성분은 그대로 유지되고, 알파만 80%로 설정되어 약간 투명해집니다. (원본 색상의 알파가 무엇이었든 상관없음)
--vivid-yellow : color ( display-p31 1 0 ); --paler-yellow : color ( fromvar ( --vivid-yellow) srgb r gcalc ( b +0.5 ));
여기서 --vivid-yellow를 sRGB로 변환하면 rgb(100% 100% -34.63%) 이고, blue 성분이 음수여도 클램프되지 않습니다. RCS 계산 결과는 rgb(100% 100% 15.37%)
--tan : oklch ( 78 % 0.06 75 /0.7 ); --deeper-tan : oklch ( fromvar ( --tan) l c h /calc ( alpha *2 ));
--blue-into-gray : rgb ( fromvar ( --color) calc ( r *.3 + g *.59 + b *.11 ) calc ( r *.3 + g *.59 + b *.11 ) calc ( r *.3 + g *.59 + b *.11 ));
이 방법으로 red는 rgb(76.5 76.5 76.5)가 됨, lime은 rgb(150.45 150.45 150.45)가 되고, blue도 rgb(150.45 150.45 150.45)가 됩니다. darkolivegreen (rgb(85 107 47))의 경우는 rgb(93.8 93.8 93.8)이 됩니다.
(비교적 러프한 예: 일단 이것이 명도 계산과 비슷해 보이지만, 실제론 빨강/초록/파랑 성분을 선형광(linear-light)이 아닌 감마 인코딩된 공간(gamma-encoded space)에서 다루기 때문. 또한, 가중치는 구시대 NTSC 색공간용이지 sRGB용이 아님.)
(이것은 문법 설명을 위한 예시일 뿐; 색상 그레이스케일 처리의 더 쉽고 정확한 방법은 oklch() 함수 사용입니다. 이 공간은 인간 시각에 더 가깝기 때문입니다: oklch(from var(--color) l 0 h)는 명도는 그대로 두고, 채도만 0으로 만들어 컬러풀함을 없앰.)
예를 들어,
color : color ( fromcolor ( srgb0 0 0 /60 % ) srgb alpha0.6 0.6 /0.9 );
여기서 alpha 컴포넌트는 <number> 값을 반환하므로 0.6이며, 결과 색상은 color(srgb 0.6 0.6 0.6 / 0.9)이 됨.
아래 예시는 역시 alpha가 0.6으로 해석되지만, rgb() 구문에서 컴포넌트 범위가 0~255이므로 전혀 다른 색상이 나옵니다:
color : rgb ( fromrgb ( 0 0 0 /60 % ) alpha153 153 /0.9 );
결과: rgb(0.6 153 153 / 0.9) (153 153 153 / 0.9 은 아님)
html{ --bg : hsl ( none3 % 50 % ); } .foo{ --darker-bg : oklch ( fromvar ( --bg) calc ( l *0.8 ) c h); } .bar{ background : linear-gradient ( in Oklab to right, var ( --darker-bg), #4C3); }
--bg 값을 OkLCh로 변환하면 oklch(0.592 0.009 17.42)이고, 유사한 hue 컴포넌트는 유지되어 oklch(0.592 0.009 none)이 됩니다. 이 값이 상대 함수에 그대로 쓰여 더 어두운 색상 oklch(0.474 0.009 none)이 나옵니다.
그라데이션 속 연한 초록색 oklch(0.743 0.222 141.6) 과 보간할 때, 다른 색상의 hue도 그 값을 받아 oklch(0.474 0.009 141.6)이 됩니다.
즉, 그라데이션은 일정한 녹색 기운(hue)를 띕니다.
만약 구현이 hue forward 흐름 처리를 하지 않는다면, 회색 --darker-bg는 hue 0이 되고, 그라데이션 앞에는 원치 않는 붉은 색조가 남게 됩니다.
그러나 누락된 값에 대해 계산이 수행되는 경우, none은 0으로 취급된다.
4.3. 상대 sRGB 색상(Relative sRGB Colors)
sRGB 색상의 의미는 CSS Color 4 § 5 sRGB Colors에서 정의됩니다.
현대 색상 구문의 rgb() 및 rgba() 함수 문법은 다음과 같이 확장됩니다:
<modern-rgb-syntax> = rgb( [ from <color> ]?
[ <number> | <percentage> | none]{3}
[ / [<alpha-value> | none] ]? )
<modern-rgba-syntax> = rgba( [ from <color> ]?
[ <number> | <percentage> | none]{3}
[ / [<alpha-value> | none] ]? )
상대 색상 구문의 rgb()/rgba() 함수에서는 허용되는 구성 요소 키워드가 다음과 같습니다:
-
r, g, b : <number> 값이며, 원본 색상의 빨강/초록/파랑 컴포넌트에 해당합니다 (필요하다면 sRGB 변환 후 결과). 255.0은 100%와 같습니다.
-
alpha : <number> 값이며, 원본 색상의 알파 투명도에 해당합니다. 1.0은 100%와 같습니다.
테스트
rgb ( from indianred255 g b)
이 예시는 indianred의 sRGB 값(205 92 92)에서 빨강 컴포넌트만 255로, 나머지는 그대로 두어 rgb(255 92 92)가 됩니다.
상대 sRGB 색상 구문은 반드시 현재(모던) RGB 구문에만 적용할 수 있습니다.
rgb ( from darkblue16 32 b /0.5 )
이 예시는 darkblue의 sRGB 값(0 0 139)에서 빨강, 초록, 알파 컴포넌트만 대체하여 rgb(16 32 139 / 0.5)가 됩니다.
4.4. 상대 HSL 색상
HSL 색상의 의미는 CSS Color 4 § 7 HSL 색상: hsl() 및 hsla() 함수에 정의되어 있습니다.
현대 색상 구문(modern color syntax)의 hsl() 및 hsla() 함수의 문법은 다음과 같이 확장됩니다:
<modern-hsl-syntax> = hsl([from <color>]?
[<hue> | none]
[<percentage> | <number> | none]
[<percentage> | <number> | none]
[ / [<alpha-value> | none] ]? )
<modern-hsla-syntax> = hsla([from <color>]?
[<hue> | none]
[<percentage> | <number> | none]
[<percentage> | <number> | none]
[ / [<alpha-value> | none] ]? )
상대 색상 구문 안의 hsl() 또는 hsla() 함수에서 허용되는 구성 요소 키워드는 다음과 같습니다:
-
h 은 <number>이며, 원본 색상의 HSL 색상각(hue)에 해당합니다(도 단위). sRGB로의 변환이 필요하면 변환 후, [0, 360] 범위로 정규화됩니다. 90은 90deg와 동일합니다.
-
s 및 l 은 <number>로, 원본 색상의 HSL 채도(saturation) 및 명도(lightness)에 해당합니다. sRGB로의 변환이 필요하면 변환 후 취해집니다. 100은 100%와 동일합니다.
테스트
lightseagreen은 hsl(177deg 70% 41%)이므로 --complement는 hsl(357deg 70% 41%)입니다--accent : lightseagreen; --complement : hsl ( fromvar ( --accent) calc ( h +180 ) s l);
상대 HSL 색상 구문은 레거시가 아닌(non-legacy) HSL 문법 형태에만 적용됩니다.
4.5. 상대 HWB 색상
HWB 색상의 의미는 CSS Color 4 § 8 HWB 색상: hwb() 함수에 정의되어 있습니다.
hwb() 함수의 문법은 다음과 같이 확장됩니다:
hwb() = hwb([from <color>]?
[<hue> | none]
[<percentage> | <number> | none]
[<percentage> | <number> | none]
[ / [<alpha-value> | none] ]? )
상대 색상 구문 안의 hwb() 함수에서 허용되는 구성 요소 키워드는 다음과 같습니다:
-
h 은 <number>이며, 원본 색상의 HWB 색상각(hue)에 해당합니다(도 단위). sRGB로의 변환이 필요하면 변환 후, [0, 360] 범위로 정규화됩니다. 90은 90deg와 동일합니다.
-
w 및 b 은 <number>로, 원본 색상의 HWB 화이트니스(whiteness) 및 블랙니스(blackness)에 해당합니다. sRGB로의 변환이 필요하면 변환 후 취해집니다. 100은 100%와 동일합니다.
4.6. 상대 Lab 색상
Lab 색상의 의미는 CSS Color 4 § 9.1 CIE Lab 및 LCH에 정의되어 있습니다.
lab() 함수의 문법은 다음과 같이 확장됩니다:
lab() = lab([from <color>]?
[<percentage> | <number> | none]
[<percentage> | <number> | none]
[<percentage> | <number> | none]
[ / [<alpha-value> | none] ]? )
상대 색상 구문 안의 lab() 함수에서 허용되는 구성 요소 키워드는 다음과 같습니다:
-
l 은 <number>로, 원본 색상의 CIE 명도(Lightness)에 해당합니다. CIE Lab로의 변환이 필요하면 변환 후 취해집니다. 100은 100%와 동일합니다.
-
a 및 b 은 <number>로, 원본 색상의 CIE Lab a, b 축에 해당합니다. CIE Lab로의 변환이 필요하면 변환 후 취해집니다. 125는 100%와 동일하고, -125는 -100%와 동일합니다.
-
lab(from var(--mycolor) l a b / 100%) 은 var(--mycolor)의 알파를 원래 값에 상관없이 1.0으로 설정합니다.
-
lab(from var(--mycolor) l a b / calc(alpha * 0.8)) 은 var(--mycolor)의 알파를 원래 값의 20%만큼 줄입니다.
모든 조정은 래스팅(lossless) 방식으로, gamut 클리핑이 발생하지 않습니다. 이는 lab()이 가시 스펙트럼 전체를 포함하기 때문입니다. 반면 sRGB 기반 함수들('rgb()', 'hsl()', 'hwb()' 등)에서의 알파 조정은 HSL 또는 HWB 계산을 위해 sRGB로의 변환을 필요로 하므로 동일하지 않습니다.
--mycolor : orchid; // orchid islab ( 62.753 52.460 -34.103 ) --mygray:lab ( fromvar ( --mycolor) l0 0 ) // mygray islab ( 62.753 0 0 ) which isrgb ( 59.515 % 59.515 % 59.515 % )
4.7. 상대 Oklab 색상
Oklab 색상의 의미는 CSS Color 4 § 9.2 Oklab 및 OkLCh에 정의되어 있습니다.
oklab() 함수의 문법은 다음과 같이 확장됩니다:
oklab() = oklab([from <color>]?
[<percentage> | <number> | none]
[<percentage> | <number> | none]
[<percentage> | <number> | none]
[ / [<alpha-value> | none] ]? )
상대 색상 구문 안의 oklab() 함수에서 허용되는 구성 요소 키워드는 다음과 같습니다:
-
l 은 <number>로, 원본 색상의 Oklab 명도(Lightness)에 해당합니다. Oklab로의 변환이 필요하면 변환 후 취해집니다. 1.0은 100%와 동일합니다.
-
a 및 b 은 <number>로, 원본 색상의 Oklab a, b 축에 해당합니다. Oklab로의 변환이 필요하면 변환 후 취해집니다. 0.4는 100%와 동일하고, -0.4는 -100%와 동일합니다.
4.8. 상대 LCH 색상
LCH 색상의 의미는 CSS Color 4 § 9.1 CIE Lab 및 LCH에 정의되어 있습니다.
lch() 함수의 문법은 다음과 같이 확장됩니다:
lch() = lch([from <color>]?
[<percentage> | <number> | none]
[<percentage> | <number> | none]
[<hue> | none]
[ / [<alpha-value> | none] ]? )
상대 색상 구문 안의 lch() 함수에서 허용되는 구성 요소 키워드는 다음과 같습니다:
-
l 은 <number>로, 원본 색상의 CIE 명도(Lightness)에 해당합니다. CIE LCH로의 변환이 필요하면 변환 후 취해집니다. 100은 100%와 동일합니다.
-
c 은 <number>로, 원본 색상의 LCH 채도(chroma)에 해당합니다. CIE LCH로의 변환이 필요하면 변환 후 취해집니다. 150은 100%와 동일합니다.
-
h 은 <number>로, 원본 색상의 LCH 색상각(hue)에 해당합니다(도 단위). CIE LCH로의 변환이 필요하면 변환 후 취해지고, [0,360] 범위로 정규화됩니다. 90은 90deg와 동일합니다.
lightseagreen은 lch(65.4937 39.4484 190.1013)이므로 --complement는 lch(65.4937 39.4484 370.1013)입니다--accent : lightseagreen; --complement : lch ( fromvar ( --accent) l ccalc ( h +180 ));
--mycolor : orchid; // orchid islch ( 62.753 62.571 326.973 ) --mygray:lch ( fromvar ( --mycolor) l0 h) // mygray islch ( 62.753 0 326.973 ) which isrgb ( 59.515 % 59.515 % 59.515 % )
하지만 HSL과 달리, 이러한 조작들이 항상 색역 내(in-gamut) 결과를 보장하지는 않습니다.
--mycolor : lch ( 60 % 90 320 ); lch ( fromvar ( --mycolor) l ccalc ( h -120 ));
이 경우 매우 높은 채도의 청록색이 만들어지며, lch(60% 90 200) 는 color(srgb -0.6 0.698 0.772)로 변환되어 sRGB에서 음수의 빨강값을 가지므로 색역 밖입니다. 실제로 display-p3에서도 색역 밖이며: color(display-p3 -0.46 0.68 0.758) 이고 rec2020에서도: color(rec2020 -0.14 0.623 0.729)입니다.
sRGB 색역 내에서 가장 가까운 색상은 lch(60.71% 37.56 201.1)이며, 이는 rgb(0% 64.2% 66.3%)입니다. 채도의 차이(37.5 vs 90)는 매우 큽니다.
CIE CH 평면에서의 상대 색상 조작을 보여주는 다이어그램입니다. a 및 b 축이 표시되어 있으며 중앙에서 교차합니다. 우리는 중앙 명도 축을 따라 내려다보고 있습니다. sRGB 색공간의 최대 색역은 불규칙한 볼록 다각형으로 표시되어 있습니다.
동일한 연산을 HSL에서 수행하면 색역 내 결과를 얻을 수 있습니다. 그러나 다른 면에서 만족스럽지 않습니다:
--mycolor : lch ( 60 % 90 320 ); hsl ( fromvar ( --mycolor) calc ( h -120 ) s l);
HSL에서 --mycolor는 hsl(289.18 93.136% 65.531%) 이므로 120도를 빼면 hsl(169.18 93.136% 65.531%) 가 됩니다. 이를 다시 LCH로 변환하면 lch(89.0345% 49.3503 178.714) 이 되어, HSL에서의 hue 회전으로 인해 명도는 60%에서 89%로 급증하고, 채도는 90에서 49로 떨어지며, 색상각은 실제로 120도가 아닌 141도 정도 변경됩니다.
4.9. 상대 OkLCh 색상
OkLCh 색상의 의미는 CSS Color 4 § 9.2 Oklab 및 OkLCh에 정의되어 있습니다.
The grammar of the oklch() function is extended as follows:
oklch() = oklch([from <color>]?
[<percentage> | <number> | none]
[<percentage> | <number> | none]
[<hue> | none]
[ / [<alpha-value> | none] ]? )
상대 색상(relative color) 구문 안에서 oklch() 함수에서는, 허용되는 구성 요소 키워드들이 다음과 같습니다:
-
l은 <number>이며, 필요하면 변환 후 OkLCh에서의 원본 색상(origin color’s)의 Oklab 명도(Lightness)에 대응합니다. 1.0은 100%와 같습니다.
-
c은 <number>이며, 필요하면 변환 후 OkLCh에서의 원본 색상(origin color’s) 채도(chroma)에 대응합니다. 0.4는 100%와 같습니다.
-
h은 <number>이며, 필요하면 변환 후 OkLCh에서의 원본 색상(origin color’s) 색상각(hue, 도 단위)에 대응하고, [0, 360] 범위로 정규화됩니다. 90은 90deg와 동일합니다.
-
alpha은 <number>이며, 원본 색상(origin color’s)의 알파(투명도)에 대응합니다. 1.0은 100%와 동일합니다.
OkLCh는 지각적으로 균일(perceptually uniform)하고 채도(chroma)를 보존하며, 축(axes)이 색상의 직관적인 속성과 대응하기 때문에, 색상 조작에 적합한 선택입니다.
--mycolor : lch ( 60 % 90 320 ); oklch ( fromvar ( --mycolor) l ccalc ( h -120 ));
--mycolor는 oklch(0.69012 0.25077 319.893)입니다. Hue에서 120을 빼면 매우 높은 채도의 청록색이 되어, oklch(0.69012 0.25077 199.893) 이 되며 sRGB 색역 밖에 있습니다. color(srgb -0.6018 0.7621 0.8448)로 변환되며, 음수인 빨강(red) 성분이 그 점을 보여줍니다. OkLCh 채도를 낮춰 이 색을 색역 내로 가져오면 oklch(0.69012 0.1173 199.893) 이 됩니다. OkLCh 채도는 0.251에서 0.117로 감소했습니다.
4.10. 상대 알파 색상
상대 알파 색상(Relative alpha colors)은 원본 색상을 참조하며 알파 채널만 변경합니다. 알파 채널의 의미는 CSS Color 4 § 4.2 색상에서의 투명도 표현: <alpha-value> 구문에 정의되어 있습니다.
The grammar of the alpha() function, new in this level, is as follows:
alpha() = alpha([from <color>]
[ / [<alpha-value> | none] ]? )
상대 색상(relative color) 구문 안의 alpha() 함수에서, 허용되는 구성 요소 키워드는:
-
alpha은 <number>이며, 원본 색상(origin color’s)의 알파(투명도)에 대응합니다. 1.0은 100%와 동일합니다.
원본 색상(origin color)의 색상 성분들은 변경되지 않으며, 알파 성분만 수정되거나 대체됩니다. 이 함수의 결과는 원본 색상의 색상 공간으로 표현됩니다.
Tests
--mycolor : oklch ( 60 % 0.25 315 /0.3 ); alpha ( fromvar ( --mycolor) /80 % );
--mycolor : oklch ( 60 % 0.25 315 /0.8 ); alpha ( fromvar ( --mycolor) /calc ( alpha *0.5 ));
5. 미리 정의된 및 사용자 정의 색 공간 지정: color() 함수
color() 함수는 색상을 특정 색 공간에서 지정할 수 있도록 해줍니다 (다른 대부분의 색상 함수들이 작동하는 암묵적 sRGB 색 공간이 아닌, 명시적으로 지정된 색 공간).
이 단계에서는 color() 함수가 확장되어 CSS Color 4 § 10. Predefined Color Spaces에 정의된 미리 정의된 색 공간뿐만 아니라, 사용자 정의 색 공간도 허용합니다.
또한, 절대 색상 뿐만 아니라 상대 색상(relative color)도 허용하도록 확장되었습니다.
이 함수의 문법은 이제 다음과 같습니다:
color() = color( [from <color>]? <colorspace-params> [ / [ <alpha-value> | none ] ]? )
<colorspace-params> = [<custom-params> | <predefined-rgb-params> | <xyz-params>]
<custom-params> = <dashed-ident> [ <number> | <percentage> | none ]+
<predefined-rgb-params> = <predefined-rgb> [ <number> | <percentage> | none ]{3}
<predefined-rgb> = srgb | srgb-linear | display-p3 | a98-rgb | prophoto-rgb | rec2020
<xyz-params> = <xyz-space> [ <number> | <percentage> | none ]{3}
color() 함수는 명시된 색상 공간에서 색상을 지정하는 인자들을 받습니다.
이 함수는 아래에 설명된 대로 유효하지 않은 색(invalid color)을 나타내거나, 유효한 색(valid color)을 나타냅니다.
유효하지 않은 색이 아닌 모든 색은 유효한 색입니다.
또한 한 색은 유효한 색일 수 있지만, 출력 장치(화면, 프로젝터, 프린터 등)가 생성할 수 있는 색 범위를 벗어나 있을 수 있습니다. 그럴 경우 해당 색상은 그 색상 공간에 대해 색역 밖(out of gamut)이라고 합니다.
색역 밖 색상은 컴포넌트 값이 0보다 작거나 0% 미만, 또는 1보다 크거나 100% 초과인 값을 가집니다. 이러한 값들은 유효하지 않은 것으로 간주되지 않으며; 표시 시에는 상대 색도법(relative colorimetric intent)을 사용해 계산된 값 시점에 0/0%~1/100% 범위로 가뭇 매핑(gamut-mapped)됩니다.
각각의 유효한 색은 출력 장치(화면 또는 프린터)에 대해 색역 내(in-gamut) 이거나, 색역 밖입니다.
5.1. 상대 색상-함수 색상(Relative Color-Function Colors)
상대 색상(relative color) 구문 안에서 color() 함수를 <custom-params>와 함께 사용할 경우, 허용되는 구성 요소 키워드의 이름과 개수는 다음에 의해 정의됩니다:
-
해당 @color-profile 규칙의 components 디스크립터에 의해 정의됩니다. 만약 존재하지 않으면, 상대 색상 조작은 허용되지 않습니다. 이 값들은 <number>형이며, 필요시 변환 후 색상 프로파일의 색상 공간으로 변환된 원본 색상(origin color’s)의 구성 요소에 대응합니다. 값 1.0은 100%에 해당합니다.
상대 색상 구문에서 color() 함수를 <predefined-rgb-params>와 함께 사용할 경우, 허용되는 구성 요소 키워드는:
-
r, g, 및 b는 모두 <number>이며, 필요하면 변환 후 사전 정의된 RGB 색상 공간으로의 원본 색상(origin color’s)의 빨강/녹색/파랑 성분에 해당합니다. 값 1.0은 100%에 해당합니다.
상대 색상 구문에서 color() 함수를 <xyz-params>와 함께 사용할 경우, 허용되는 구성 요소 키워드는:
-
x, y, z는 모두 <number>이며, 필요하면 변환 후 관련 백색점에 적응된 상대 CIE XYZ 색공간에서의 원본 색상(origin color’s)의 X, Y, Z 성분에 해당합니다. 값 1.0은 100%에 해당합니다.
상대 색상 구문에서 color() 함수를 <predefined-rgb-params> 또는 <xyz-params>와 함께 사용할 경우, 추가로 허용되는 구성 요소 키워드는:
-
alpha은 <number>이며, 원본 색상(origin color’s)의 알파(투명도)에 대응합니다. 1.0은 100%와 동일합니다.
파라미터는 다음 형태를 가집니다:
-
<ident> 또는 <dashed-ident>로 색상 공간을 명시합니다. 만약 이것이 <ident>이면, CSS Color 4 § 10. Predefined Color Spaces에 있는 사전 정의된 색상 공간들(예: display-p3) 중 하나를 의미합니다; 만약 <dashed-ident>이면, 이는 @color-profile 규칙으로 정의된 사용자 지정 색상 공간을 의미합니다. 개별 사전 정의 색상 공간은 <number> 또는 <percentage> 또는 둘 다의 사용을 추가로 제한할 수 있습니다.
만약 <ident>이 존재하지 않는 색상 공간(사전 정의된 색상 공간 중 하나와 일치하지 않는 이름)이나, 사전 정의되었지만 구현에서 지원하지 않는 색상 공간을 가리키면, 이 인수는 유효하지 않은 색을 나타냅니다.
만약 <dashed-ident>이 존재하지 않는 색상 공간(예: 어떤 color profile의 이름과 일치하지 않거나, 일치하지만 해당 프로파일이 아직 로드되지 않았거나, 유효한 프로파일을 나타내지 않는 경우)을 가리키면, 이 인수는 유효하지 않은 색을 나타냅니다.
-
색상 공간이 요구하는 파라미터 값을 제공하는 하나 이상의 <number>들 또는 <percentage>들이 제공됩니다.
사용자 정의 색상 공간의 경우, 지정된 성분 값이 0보다 작거나 0% 미만, 또는 1보다 크거나 100% 초과여도 유효하지 않은 것이 아니며; 계산된 값 시점에 유효 범위로 클램프됩니다. 이는 ICC 프로파일이 보통 범위를 벗어난 입력 값을 허용하지 않기 때문입니다.
사용자 정의 색상 공간에서, 색상 공간이 요구하는 것보다 더 많은 <number>들 또는 <percentage>들이 제공되면, 끝에 있는 초과된 <number>들은 무시됩니다. 이 색은 여전히 유효한 색입니다.
사용자 정의 색상 공간에서, 색상 구성 요소 설명자에 나열된 것보다 더 많은 <number>들 또는 <percentage>들이 제공되면, 끝에 추가된 값들은 여전히 유효하지만, 상대 색상 문법에서는 사용할 수 없습니다. 이 색은 여전히 유효한 색입니다.
사용자 정의 색상 공간에서, 색상 공간이 요구하는 것보다 적은 수의 <number>들 또는 <percentage>들이 제공되면, 누락된 파라미터들은 기본값으로 0을 가집니다. (이는 추가 잉크가 스폿 컬러나 바니시인 다성분 프린터의 경우에 편리합니다.) 이 색은 여전히 유효한 색입니다.
사전 정의된 색상 공간의 경우, 지정된 성분 값이 0보다 작거나 0% 미만, 또는 1보다 크거나 100% 초과여도 유효하지 않은 것은 아니며; 이러한 색역 밖 색상들은 계산된 값 시점에 상대 색도법(relative colorimetric intent)으로 유효 범위 내로 가뭇 매핑됩니다.
-
선택적 슬래시로 구분된 <alpha-value>가 있습니다. 생략되면 기본값은 100%입니다.
--base : color ( display-p30.7 0.5 0.1 ); --dark : color ( fromvar ( --base) xyz-d65calc ( x/2 ) calc ( y/2 ) calc ( z/2 ));
원본 색상은 color(xyz-d65 0.281 0.253 0.044) 이므로, 상대 색상은 color(xyz-d65 0.14 0.126 0.022)입니다.
5.2. 사용자 정의 색상 공간(Custom Color Spaces)
CSS는 색상을 색상 프로파일에 대한 참조로 지정할 수 있게 합니다. 예를 들어 보정된 CMYK 프린터나 RGB 색상 공간, 또는 특성화된 다른 색상/단색 출력 장치 등이 그 예입니다.
color : color ( --swopc0.0134 0.8078 0.7451 0.3019 ); color : color ( --indigo0.0941 0.6274 0.3372 0.1647 0 0.0706 0.1216 ); color : color ( prophoto-rgb0.9137 0.5882 0.4784 ); color : color ( display-p30.3804 0.9921 0.1412 );
사전 정의된 색상 공간을 사용하지 않는 색상은 CSS Color 4 § 10. Predefined Color Spaces와 구별되며, <dashed-ident>을 사용하고, 스타일시트 어딘가에 해당 이름을 프로파일 데이터와 연결하는 @color-profile at-rule이 필요합니다.
@color-profile --swopc{ src : url ( 'http://example.org/swop-coated.icc' );} @color-profile --indigo{ src : url ( 'http://example.org/indigo-seven.icc' );}
5.3. 색상 프로파일 지정: the @color-profile at-rule
The @color-profile rule 색상 프로파일을 정의하고 이름을 부여합니다(color profile). 이 프로파일은 이후 color() 함수에서 색상을 지정하는 데 사용할 수 있습니다.
정의는 다음과 같습니다:
@color-profile = @color-profile [<dashed-ident> | device-cmyk] { <declaration-list> }
The <dashed-ident> gives the color profile’s name, 이 이름으로 CSS 스타일시트에서 사용됩니다. 또는, device-cmyk 키워드는 해당 색상 프로파일이 유효한 경우 device-cmyk로 지정된 색상을 해석하는 데 사용된다는 뜻입니다.
The @color-profile rule 은 이 명세에서 정의한 디스크립터들을 허용합니다.
| 이름: | src |
|---|---|
| 대상: | @color-profile |
| 값: | <url> |
| 초기값: | 해당 없음 |
The src 디스크립터는 색상 프로파일 정보를 가져올 URL을 지정합니다.
If multiple @color-profile 규칙이 동일한 이름으로 여러 개 정의되어 있다면, 문서 상에서 마지막에 있는 규칙이 최종적으로 적용되며, 앞서 정의된 것들은 모두 무시됩니다.
가져온 ICC 프로파일은 다음일 때 유효합니다
-
ICC 프로파일로 파싱될 수 있는 경우
-
입력(Input), 디스플레이(Display), 출력(Output) 또는 색상 공간(color space) ICC 프로파일인 경우입니다. (Abstract, DeviceLink, NamedColor ICC 프로파일은 사용해서는 안 됩니다).
If the profile is not valid, all CSS colors which reference this profile are 유효하지 않은 색입니다.
외부 색상 프로파일을 가져오면(fetch an external color profile), 주어진 @color-profile 규칙 rule에 대해, fetch a style resource를 사용하여 rule의 URL을 가져오되, ruleOrDeclaration을 rule로 설정하고, destination은 "color-profile", CORS 모드는 "cors"로 하며, processResponse는 주어진 response |/res| 및 null, 실패 또는 바이트 스트림 byteStream에 대해 다음 단계들을 수행합니다: 만약 byteStream가 바이트 스트림이라면, |byteStream|에서 파싱한 색상 프로파일을 적용합니다.
참고: ICC 프로파일의 인터넷 미디어 타입("MIME type")은 application/vnd.iccprofile입니다.
| 이름: | rendering-intent |
|---|---|
| 대상: | @color-profile |
| 값: | relative-colorimetric | absolute-colorimetric | perceptual | saturation |
| 초기값: | relative-colorimetric |
색상 프로파일에는 “rendering intents”(렌더링 인텐트)가 포함되며, 이는 그 프로파일의 색을 정의된 색역보다 작은 색역으로 어떻게 가뭇 매핑(gamut-map)할지를 정의합니다. 종종 프로파일은 단일 인텐트만 포함하지만, 여러 인텐트가 있을 경우, rendering-intent 디스크립터가 그들 중 하나를 선택해 사용합니다.
The four possible rendering intents are [ICC]:
- relative-colorimetric
-
매체 관련 상대 색도법(media-relative colorimetric)은,
대상 매체의 색역 내에 있는 소스 색상은 대상의 백색점에 대해 변경하지 않고 그대로 두어야 합니다.
대상 매체 색역 밖에 있는 소스 색상은 다양한 방법을 사용해 색역 경계상의 색으로 매핑됩니다.
미디어-상대(relative) 색도법 렌더링 인텐트는 종종 black point compensation(흑점 보정)과 함께 사용되며, 이 경우 소스 매체의 흑점은 대상 매체의 흑점으로도 매핑됩니다. 이 방식은 소스의 백색점을 대상의 백색점으로 매핑해야 합니다. 흑점 보정이 사용되는 경우 소스의 흑점도 대상의 흑점으로 매핑되어야 합니다. 적응 알고리즘은 백색점 변화에 맞춰 조정하는 데 사용되어야 합니다. 소스와 대상 색역 모두에 속하는 색들 사이의 상대적 관계는 보존되어야 합니다. 대상 색역 밖에 있는 색들의 상대적 관계는 변경될 수 있습니다.
- absolute-colorimetric
-
ICC-absolute colorimetric은,
대상 매체 색역 내에 있는 소스 색상은 채택된 백색(완벽한 반사 디퓨저)에 대해 변경하지 않고 그대로 두어야 합니다.
대상 매체 색역 밖의 소스 색상은 다양한 방법을 사용해 색역 경계상의 색으로 매핑됩니다.
이 방식은 색역 내 색상의 가장 정확한 색 매칭을 제공하지만,
대상 매체의 백색점이 소스 매체의 백색점보다 낮을 경우 하이라이트 클리핑이 발생할 수 있습니다.
이러한 이유로, 정확한 색상 매칭이 필요하고 하이라이트 클리핑이 문제가 되지 않는 응용에만 권장됩니다.
이 방식은 색 변환 시 백색점 매칭과 흑점 매칭을 사용 중지해야 합니다. 일반적으로 이 옵션은 테스트 목적을 제외하고 권장되지 않습니다.
- perceptual
-
이 방법은 특히 소스와 대상 사이에 상당한 차이가 있을 때(예: 화면의 이미지를 반사 인쇄물로 재현할 때)
이미지에 선호되는 선택입니다. 소스 이미지의 색을 가져와 대상 매체에 맞게 외관을 재최적화합니다(프로프라이어터리 방법).
이 재최적화는 소스와 대상 색역 모두 내의 색들을 변경할 수 있지만,
지각적 변환은 원래 재현물의 기본적인 예술적 의도를 유지해야 합니다. 소스 이미지의 오류를 수정하려 시도하지는 않습니다.
참고: v2 ICC 프로파일에는 지정된 지각적 기준 매체(perceptual reference medium)가 없으므로 상호운용성 문제가 발생할 수 있습니다. v2 ICC 프로파일을 사용할 때는, 사용될 소스 및 대상 프로파일 조합이 원하는 결과를 내는지 확인되지 않았다면, 지각적 렌더링 인텐트 대신 black point compensation을 사용하는 media-relative colorimetric 렌더링 인텐트를 사용하는 것이 더 안전할 수 있습니다.
이 방법은 픽셀들이 대상 장치의 색역에 매핑될 때 픽셀들 사이의 상대적 색 값들을 유지해야 합니다. 이 방법은 색상 이동(hue shifts)과 불연속성을 피하고 장면의 전체적인 외관을 최대한 보존하기 위해, 원래 대상 장치 색역 내에 있던 픽셀 값들조차 변경할 수 있습니다.
- saturation
- 이 옵션은 원본의 상대적 채도(chroma)를 보존하고 고색(솔리드 컬러)을 선명하게 유지하도록 만들어졌습니다. 그러나 지각적 인텐트와 유사하게 상호운용성 문제가 있었고, 고색 보존이 참조 매체 솔루션에 적합하지 않으므로 v4 프로파일을 사용해도 문제가 해결되지 않습니다. 이 렌더링 인텐트는 사용될 소스 및 대상 프로파일 조합이 원하는 결과를 내는지 확인된 경우를 제외하고 권장되지 않습니다. 이 옵션은 원본 픽셀들의 상대적 채도(chroma) 값을 보존해야 합니다. 색역 밖 색상은 같은 채도를 갖되 색역 내부로 들어오도록 변환되어야 합니다.
| 이름: | components |
|---|---|
| 대상: | @color-profile |
| 값: | <ident># |
| 초기값: | 해당 없음 |
색상 프로파일은 서로 다른 수의 구성 요소를 포함하는 색 공간을 정의할 수 있습니다. 예를 들어, Cyan, Magenta, Yellow, Black(CMYK) 프로파일은 네 개의 구성 요소(c, m, y, k)를 가집니다. 반면 어떤 4성분 가산 스크린 프로파일은 r, g, y, b 같은 네 이름을 사용할 수 있습니다.
이 디스크립터의 값은 쉼표로 구분된 <ident> 토큰 목록입니다. 각 <ident>는 프로파일에서 사용되는 순서대로 구성요소의 이름을 지정하며, 토큰의 총 개수가 구성 요소의 수를 정의합니다.
components: cyan, magenta, yellow, black반면 다음 디스크립터는 더 간결한 이름을 선택합니다:
components: c,m,y,k
components: cyan, magenta, yellow, black, orange, green, violet
구성요소가 ASCII 대소문자 구분 없는 방식으로 none과 일치하면, 그 descriptor는 유효하지 않다. 이는 누락된 값에 대한 토큰과 충돌하기 때문이다.
만약 구성 요소에 대해 선택한 이름이 CSS Values 4 § 10.7.1 Numeric Constants: e, pi에 정의된 CSS 숫자 상수와 충돌하면, 구성 요소는 여전히 유효하지만, calc() 안에서는 해당 구성 요소가 숫자 상수에 의해 가려져 예기치 않은 결과가 발생할 수 있습니다.
@color-profile --unwise {
src: url(https://example.com/unwise);
components: mi, pi, ni;
}
--base: color(--unwise 35% 20% 8%);
--accent: color(from var(--base) mi calc(pi * 2) calc(ni / 2));
여기서 --accent의 구성 요소 값들은 35%, 3.14159265358979 * 2 = 6.28318530717959, 4% 입니다.
5.4. CSS와 인쇄: 보정된 CMYK 및 기타 인쇄된 색상 공간 사용
The @color-profile at-rule 은 RGB 색공간에만 국한되지 않습니다. 화면은 일반적으로 RGB로 색을 직접 표시하는 반면, 프린터는 종종 색을 CMYK로 표현합니다.
보정된 4도법 인쇄(Cyan, Magenta, Yellow, Black; CMYK)나, 추가 잉크(예: Cyan Magenta Yellow Black Orange Green Violet; CMYKOGV)를 사용하는 고충실도 넓은 색역 인쇄도 ICC 프로파일이 있다면 CSS에서 처리할 수 있습니다. 이 프로파일은 사용하려는 잉크 조합, 용지, 총 잉크 커버리지 및 장비에 대응해야 합니다.
@color-profile --fogra39{ src : url ( 'https://example.org/Coated_Fogra39L_VIGC_300.icc' ); } .header{ background-color : color ( --fogra390 % 70 % 20 % 0 % ); }
여기서 color() 함수는 우선 우리가 프로파일에 부여한 이름을 적고, 이어서 cyan, magenta, yellow, black의 백분율을 제공합니다.
이 프로파일에서 이는 다음 색으로 해석됩니다: lab(63.673303% 51.576902 5.811058) 이는 rgb(93.124, 44.098% 57.491%) 입니다.
주어진 CMYK 조합으로부터 실제로 생성되는 색을 알고 있으므로, 인쇄물의 화면상 시각화(soft-proof)를 만들 수 있습니다.
또한 색을 알아야 하는 절차들(안티앨리어싱, 합성, 그라데이션에서 색 사용 등)은 정상적으로 진행될 수 있습니다.
A color checker, used for ensuring color fidelity in the print and photographic industries. Averaged measured Lab values are available for each patch. The rectangles show the Lab values, converted to sRGB. The circles, which are barely visible, show the Lab values, passed through a FOGRA51 [FOGRA51] ICC profile to convert them to CMYK. The CMYK values are then passed through the same ICC profile in reverse, to yield new Lab values. These are then converted to sRGB for display.
The one patch with a more visible circle (third row, first patch) is because the color is slightly outside the gamut of the FOGRA51 CMYK space used.
The table below shows, for each patch, the DeltaE 2000 between the original Lab and the Lab value after round-tripping through CMYK. A DeltaE 2000 of 1 or more is just visible.
| A | B | C | D | E | F | |
|---|---|---|---|---|---|---|
| 1 | 0.06 | 0.07 | 0.03 | 0.04 | 0.06 | 0.17 |
| 2 | 0.03 | 0.75 | 0.05 | 0.06 | 0.03 | 0.02 |
| 3 | 1.9 | 0.04 | 0.06 | 0.05 | 0.02 | 0.05 |
| 4 | 0.03 | 0.08 | 0.03 | 0.03 | 0.04 | 0.80 |
@color-profile --swop5c{ src : url ( 'https://example.org/SWOP2006_Coated5v2.icc' ); } .header{ background-color : color ( --swop5c0 % 70 % 20 % 0 % ); }
이 프로파일에서 이 CMYK 비율(앞의 예와 동일한 백분율)은 다음 색으로 해석됩니다: lab(64.965217% 52.119710 5.406966) 이는 rgb(94.903% 45.248% 59.104%) 입니다.
예비 색상(fallback colors)은 예를 들어 미디어 쿼리를 사용하여 지정할 수 있으며, 지정된 CMYK 색이 sRGB 색역 밖인 것으로 알려진 경우에 사용됩니다.
@media ( color-gamut: srgb) { .header{ background-color : rgb ( 8.154 % 60.9704 % 37.184 % ); } } @media print, ( color-gamut: p3){ .header{ background-color : color ( --fogra3990 % 0 % 90 % 0 % ); } }
이 CMYK 색은 lab(56.596645% -58.995875 28.072154) 또는 lch(56.596645% 65.33421077211648 154.5533771086801)에 해당합니다. sRGB에서는 rgb(-60.568% 62.558% 32.390%)가 되어, 큰 음수의 red 성분이 나타나듯이 색역 밖입니다.
결과가 색역 내에 들어올 때까지 채도를 줄이면 lch(56.596645% 51 154.5533771086801) 가 되고 이는 rgb(8.154% 60.9704% 37.184%) 입니다. 이 값이 수동으로 폴백 색상으로 지정되었습니다.
넓은 색역 화면에서는 이 색이 display-p3 색역 내에 있습니다 (display-p3(0.1658 0.6147 0.3533) 임).
색상은 네 잉크(CMYK)에 국한되지 않습니다. 예를 들어, 7색 잉크 세트도 사용할 수 있습니다.
- Orange: CIELAB 65 58 88
- Green: CIELAB 60 -75 0
- CIELAB 22 47 -56
측정 조건은 M1이며, 이는 용지의 형광증백제가 고려되고 분광광도계에 UV 컷 필터가 없음을 의미합니다.
@color-profile --fogra55beta{ src : url ( 'https://example.org/2020_13.003_FOGRA55beta_CL_Profile.icc' ); } .dark_skin{ background-color : color ( --fogra55beta0.183596 0.464444 0.461729 0.612490 0.156903 0.000000 0.000000 ); } .light_skin{ background-color : color ( --fogra55beta0.070804 0.334971 0.321802 0.215606 0.103107 0.000000 0.000000 ); } .blue_sky{ background-color : color ( --fogra55beta0.572088 0.229346 0.081708 0.282044 0.000000 0.000000 0.168260 ); } .foliage{ background-color : color ( --fogra55beta0.314566 0.145687 0.661941 0.582879 0.000000 0.234362 0.000000 ); } .blue_flower{ background-color : color ( --fogra55beta0.375515 0.259934 0.034849 0.107161 0.000000 0.000000 0.308200 ); } .bluish_green{ background-color : color ( --fogra55beta0.397575 0.010047 0.223682 0.031140 0.000000 0.317066 0.000000 ); }
5.5. CMYK 색상을 Lab으로 변환
보정된 CMYK 색공간에서 Lab으로의 변환은 보통 ICC 프로파일에서 Lab 값을 조회(lookup)하여 수행됩니다.
5.6. Lab 색상을 CMYK로 변환
인쇄를 위해, Lab 색상은 프린터의 색공간으로 변환되어야 합니다.
이는 일반적으로 ICC 프로파일에서 CMYK 값을 조회하여 수행됩니다.
6. 보정되지 않은 CMYK 색상: device-cmyk() 함수
프린터가 보정되지 않았지만, 특정 잉크 조합의 출력이 실험이나 인쇄된 샘플 색상집을 통해 알려진 경우, CMYK 색상을 디바이스 의존적인 방식으로 표현하는 것이 유용할 수 있습니다.
참고: 실제로 출력되는 색상을 알 수 없기 때문에, CSS 처리기가 근사값을 계산할 수 있습니다. 이 근사값은 실제 인쇄 결과와 시각적으로 매우 다를 가능성이 높습니다.
device-cmyk() 함수는 작성자가 이러한 방식으로 색상을 지정할 수 있게 합니다:
device-cmyk() = <legacy-device-cmyk-syntax> | <modern-device-cmyk-syntax>
<legacy-device-cmyk-syntax> = device-cmyk( <number>#{4} )
<modern-device-cmyk-syntax> = device-cmyk( <cmyk-component>{4} [ / [ <alpha-value> | none ] ]? )
<cmyk-component> = <number> | <percentage> | none
device-cmyk() 함수의 인수는 시안, 마젠타, 옐로, 블랙 성분을 순서대로, 0에서 1 사이의 숫자나, 모던 문법에서는 0%에서 100% 사이의 백분율로 지정합니다. 이 두 방식은 동등하며, 선형적으로 서로 매핑됩니다. 0 또는 0% 미만, 1 또는 100%를 초과하는 값은 무효가 아니며; 대신 계산값 단계에서 0/0% 또는 1/100%로 clamp(클램프) 됩니다.
모던 문법에서는 다섯 번째 인수가 색상의 알파(투명도) 성분을 지정합니다. 이는 rgb() 함수의 네 번째 인수와 동일하게 해석됩니다. 생략되면 기본값은 100%입니다.
역사적 이유로, device-cmyk()는 레거시 색상 문법도 지원합니다.
일반적으로 인쇄 기반 응용 프로그램은 실제 사용된 색을 CMYK로 저장하고, 프린터로 해당 형태로 전송합니다. 하지만 이러한 색상은 색도 해석이 불가능하며, 그러므로 그라디언트, 합성, 블렌딩 등에는 사용할 수 없습니다.
따라서 Device CMYK 색상은 동등한 색상으로 변환되어야 합니다. 이는 HSL 또는 HWB를 RGB로 변환하는 것만큼 간단하지 않습니다; 정확한 변환은 출력 장치의 특성에 따라 달라집니다.
- 사용자, 작성자, 또는 사용자 에이전트 스타일시트에 @color-profile이 device-cmyk로 정의되어 있고, src 디스크립터로 지정한 리소스를 가져올 수 있으며, 해당 리소스가 유효한 CMYK ICC 프로파일이고, 사용자 에이전트가 ICC 프로파일을 처리할 수 있다면, device-cmyk() 함수의 계산값은 해당 CMYK 색상의 Lab 값이어야 합니다.
- 그렇지 않으면, device-cmyk() 함수의 계산값은 아래의 단순 변환 알고리즘을 사용하여 변환된 CMYK 색상의 sRGB 값이어야 합니다.
color : device-cmyk ( 0 81 % 81 % 30 % ); color : rgb ( 178 34 34 ); color : firebrick;
color : device-cmyk ( 0 81 % 81 % 30 % ); color : lab ( 45.060 % 45.477 35.459 ) color:rgb ( 70.690 % 26.851 % 19.724 % );
단순 변환은 필연적으로 근사값일 수밖에 없습니다, 왜냐하면 잉크의 색도, 점 확산(dots gain), RGB 공간의 색도 등에 대한 정보가 없기 때문입니다.
컬러 체크판(color checker)은 인쇄 및 사진 산업에서 색상 정확도를 보장하기 위해 사용됩니다. 각 패치마다 평균 측정된 Lab 값이 제공됩니다. 사각형은 Lab 값을 sRGB로 변환한 결과입니다. 원은 Lab 값을 ICC 프로파일로 CMYK로 변환한 후, 다시 단순 변환을 통해 sRGB로 변환한 결과입니다.
아래 표는 각 패치의 오리지널 Lab과 CMYK를 거쳐 다시 변환한 Lab 값 사이의 DeltaE 2000(색상 차이)을 보여줍니다. DeltaE 2000 값이 1 이상이면 사람이 겨우 구분할 수 있고, 5 이상이면 완전히 다른 색상입니다.
| A | B | C | D | E | F | |
|---|---|---|---|---|---|---|
| 1 | 11.33 | 9.36 | 5.66 | 7.52 | 12.39 | 21.58 |
| 2 | 6.40 | 8.79 | 11.77 | 17.16 | 11.91 | 3.97 |
| 3 | 12.1 | 17.00 | 3.38 | 1.94 | 18.08 | 14.97 |
| 4 | 1.89 | 6.56 | 7.85 | 8.76 | 9.82 | 10.29 |
6.1. 보정되지 않은 CMYK와 sRGB 기반 색상 간의 단순 변환
CMYK를 RGBA로 단순 변환하려면:
red= 1 - min( 1 , cyan* ( 1 - black) + black) green= 1 - min( 1 , magenta* ( 1 - black) + black) blue= 1 - min( 1 , yellow* ( 1 - black) + black) - Alpha는 입력 색상과 동일합니다.
RGBA를 CMYK로 단순 변환하려면:
black= 1 - max( red, green, blue) cyan= ( 1 - red- black) / ( 1 - black), 혹은 black이1 이면0 magenta= ( 1 - green- black) / ( 1 - black), 혹은 black이1 이면0 yellow= ( 1 - blue- black) / ( 1 - black), 혹은 black이1 이면0 - alpha는 입력 색상과 동일합니다
7. 사용된 color-scheme에 반응하기: light-dark() 함수
시스템 색상은 현재 사용 중인 color-scheme 값에 따라 반응할 수 있습니다. light-dark() 함수는 저자(author)가 동일한 기능을 활용할 수 있게 해줍니다.
이 함수는 두 가지 형태가 있습니다: 하나는 색상 쌍을, 다른 하나는 이미지 쌍을 받습니다. 하나는 이미지, 하나는 색상을 전달하려 하면 파싱 시 에러가 발생합니다.
light-dark() = <light-dark-color> | <light-dark-image> <light-dark-color> = light-dark(<color>, <color>) <light-dark-image> = light-dark( [ <image> | none ] , [ <image> | none ] )
색상 형식의 경우, 이 함수는 첫 번째 색상의 계산값으로 계산된다. used color scheme이 light이거나 알 수 없는 경우이며, 또는 두 번째 색상의 계산값으로 계산된다. used color scheme이 dark인 경우이다.
이미지 형식의 경우, 이 함수는 첫 번째 이미지를 반환한다. used color scheme이 light이거나 알 수 없는 경우이며, 또는 두 번째 이미지를 반환한다. used color scheme이 dark인 경우이다.
none 키워드는 image(transparent)로 계산된다 (자연 크기가 없는 완전히 투명한 이미지).
a : link{ color : light-dark ( blue, #81D9FE); background-color : light-dark ( white, black); }
기존의 파란색 링크 텍스트는 흰색 배경에서 가독성이 높으나 (WCAG 대비 8.59:1, AAA 패스) 검정 배경에서는 가독성이 떨어집니다 (WCAG 대비 2.44:1, AA 실패). 대신, dark mode에서는 더 밝은 파란색 #81D9FE를 사용합니다. (WCAG 대비 13.28:1, AAA 패스).
가독성 있는 링크 텍스트
가독성 없는 링크 텍스트
가독성 있는 링크 텍스트
ul.fancy{ list-style-image : light-dark ( url ( "icons/deep-maroon-ball.png" ), url ( "icons/pale-yellow-star.png" ) ); }
background-image : light-dark ( url ( my-light-image.png ), none);
이는 다음과 동등하다:
background-image : light-dark ( url ( my-light-image.png ), image ( transparent));
테스트
- light-dark-basic.html (live test) (source)
- light-dark-currentcolor.html (live test) (source)
- light-dark-image.html (live test) (source)
- light-dark-image-none-interpolation.html (live test) (source)
- light-dark-image-none.html (live test) (source)
- light-dark-inheritance.html (live test) (source)
- light-dark-currentcolor-in-color.html (live test) (source)
- highlight-styling-004.html (live test) (source)
8. 동적으로 적정 명도를 갖는 텍스트 색상 지정: contrast-color() 함수
색상이 동적으로 생성되는 경우, 배경색으로 사용할 때 충분한 대비를 제공하는 텍스트 색상을 지정하기란 쉽지 않습니다. contrast-color() 함수는 명도 대비가 보장되는 색상을 자동으로 제공합니다. 이 함수는 지정한 단색 배경 위에 텍스트 색상으로 사용할 때 항상 충분한 색 대비를 보장합니다.
참고: 가독성은 복잡한 주제이며, 충분한 색상 대비는 그 일부일 뿐입니다. 충분한 대비를 갖췄다 해서 텍스트가 항상 잘 읽히는 것은 아니며, 폰트, 텍스트 크기, 주변 색상 등 다양한 요소에 따라 좌우됩니다.
contrast-color() = contrast-color( <color> )
contrast-color()는 흰색이나 검정색 중, 텍스트로 사용할 때 최대 색상 대비를 제공하는 색상으로 해석됩니다. 흰색과 검정색 모두 대비가 같을 경우, 흰색이 결과로 나옵니다.
어느 쪽이 밝은 색 혹은 어두운 색이 되어야 할지 결정하는 명도 대비 알고리즘은 이 단계에선 UA(유저 에이전트) 정의입니다.
참고: 이 명세의 차후 버전에선 대비 알고리즘, 사용 용도, 반환 색상 모두에 대해 더 많은 제어 기능이 도입될 예정입니다.
UA는 밝은 색/어두운 색 결정에 단순히 WCAG 2.1 섹션 1.4.3 콘트라스트(최소) 명도비 알고리즘만 활용하지 않는 것이 권장됩니다. 이 알고리즘은 여러 문제점이 알려져 있습니다. 하지만, 이 함수가 반환하는 색상은 WCAG 2.1 섹션 1.4.3 콘트라스트(최소) AA(대) 텍스트 기준을 충족해야 하며, 많은 작성자들이 법적 기준 충족이 필요하기 때문입니다.
테스트
- contrast-color-001.html (live test) (source)
- contrast-color-currentcolor-inherited.html (live test) (source)
- contrast-color-interpolation.html (live test) (source)
- color-computed-contrast-color-function.html (live test) (source)
- color-invalid-contrast-color-function.html (live test) (source)
- color-valid-contrast-color-function.html (live test) (source)
- contrast-color-function-calc-container.html (live test) (source)
9. 색상 보간
9.1. 보간을 위한 색 공간
<color-interpolation-method>는 CSS Color 4 § 13.1 보간을 위한 색 공간에서 정의된 대로, 사용자 정의 색 공간의 사용을 허용하도록 확장됩니다:
<color-space> = <rectangular-color-space> | <polar-color-space> | <custom-color-space>
<rectangular-color-space> = srgb | srgb-linear | display-p3 | display-p3-linear | a98-rgb | prophoto-rgb | rec2020 | lab | oklab | <xyz-space>
<polar-color-space> = hsl | hwb | lch | oklch
<custom-color-space> = <dashed-ident>
<hue-interpolation-method> = [ shorter | longer | increasing | decreasing ] hue
<color-interpolation-method> = in [ <rectangular-color-space> | <polar-color-space> <hue-interpolation-method>? | <custom-color-space> ]
<dashed-ident>는 반드시 유효한 @color-profile 규칙 내에 선언되어야 하며, 그렇지 않으면 <color-interpolation-method>는 무효가 됩니다.
10. <color> 값 해석
10.1. color-mix() 값 해석
모든 <color> 매개변수가 각각의 색 공간에서 상응하는 색상으로 해석된다면, 계산값은 혼합 색상이 되며, 지정한 혼합 색 공간에 따라 CSS Color 4 § 15. Resolving <color> Values 기준으로 해석됩니다. 그렇지 않은 경우(함수 내에 currentColor가 쓰인 경우), 계산값은 color-mix() 함수이며 각각의 <color> 매개변수는 CSS Color 4 § 15. Resolving <color> Values에 따라 해석됩니다. 따라서 상속이 자식 요소까지 유지됩니다.
Tests
10.2. 상대 색상 문법 값 해석
모든 <color> 매개변수가 해당 색 공간의 상응 색상으로 해석되면, 계산값은 절대 <color> 값이 되며, 지정된 RCS 색 공간에 따라 CSS Color 4 § 15. Resolving <color> Values 기준으로 해석됩니다.
Tests
그렇지 않은 경우(함수 내에 currentColor가 쓰인 경우), 계산값은 상대 색상 문법 함수가 되며, 원본 <color> 매개변수는 CSS Color 4 § 15. Resolving <color> Values 기준으로 해석됩니다. 따라서 상속이 자식 요소까지 보존됩니다.
Tests
- relative-currentcolor-a98rgb-01.html (live test) (source)
- relative-currentcolor-lch-01.html (live test) (source)
- relative-currentcolor-rgb-01.html (live test) (source)
- relative-currentcolor-displayp3-01.html (live test) (source)
- relative-currentcolor-oklab-01.html (live test) (source)
- relative-currentcolor-rgb-02.html (live test) (source)
- relative-currentcolor-hsl-01.html (live test) (source)
- relative-currentcolor-oklch-01.html (live test) (source)
- relative-currentcolor-xyzd50-01.html (live test) (source)
- relative-currentcolor-hsl-02.html (live test) (source)
- relative-currentcolor-prophoto-01.html (live test) (source)
- relative-currentcolor-xyzd65-01.html (live test) (source)
- relative-currentcolor-hwb-01.html (live test) (source)
- relative-currentcolor-rec2020-01.html (live test) (source)
- relative-currentcolor-lab-01.html (live test) (source)
- relative-currentcolor-rec2020-02.html (live test) (source)
10.3. device-cmyk 값 해석
계산 값과 사용 값은 지정된 디바이스 의존 CMYK 색상이며 (각 성분은 <number>로, <percentage>가 아님) 지정된 알파 성분과 쌍을 이룹니다 (<number>로, <percentage>가 아님; 별도 지정이 없으면 불투명값으로 처리합니다).
실제 값은 조작에 따라 달라질 수 있으며, CMYK를 지원하는 디바이스로 렌더링할 경우 CMYK 색상으로 렌더될 수 있습니다. 하지만 비-CMYK 색상과 혼합하거나 비-CMYK 디바이스로 렌더링할 때에는, 반드시 § 6 Uncalibrated CMYK Colors: the device-cmyk() Function에 지정된 대로 변환되어야 합니다.
device-cmyk ( 0 % 70 % 20 % 0 % )
의 지정값·실제값은
device-cmyk ( 0 0.7 0.2 0 )
이고, 구현체가 ICC 프로파일을 이해하며 적절한 프로파일이 설치되어 있다면, 사용 값은
lab ( 63.673 % 51.577 5.811 )
참고: 모든 색상과 마찬가지로, script에서는 사용 값을 얻을 수 없습니다.
11. 직렬화(Serialization)
본 절에서는 CSS Color 4 § 16. Serializing <color> Values 내용을 확장하여, color-mix(), device-cmyk(), 그리고 상대 색상 함수 결과값의 직렬화를 추가합니다.
이 절에서는 명세에서 사용된 문자열과 대응하는 문자를 아래와 같이 정의합니다.
| String | Character |
|---|---|
| " " | U+0020 SPACE |
| "," | U+002C COMMA |
| "-" | U+002D HYPHEN-MINUS |
| "." | U+002E FULL STOP |
| "/" | U+002F SOLIDUS |
문자열 "."은 로케일에 상관없이 소수점 구분자로 사용되어야 하며, 천 단위 구분자는 없어야 합니다.
관례상, 결과의 알파 값이 정확히 1일 경우, 직렬화에서 생략됩니다. 1(완전 불투명)은 암묵적인 기본값입니다.
11.1. color-mix() 직렬화
선언된 color-mix() 함수의 값이 serialization될 때는 문자열 "color-mix("로 시작하고, <color-space>가 oklab 이 아닌 경우(명시적으로 지정되었는지 기본값인지 상관없이): 문자열 "in "이 이어지고, <color-space>를 소문자로, <hue-interpolation-method>가 지정되어 있고 shorter hue가 아닌 경우, " "와 <hue-interpolation-method>를 소문자로, 그리고 ", " 각 color argument의 serialization(아래 참고)을 ", "으로 구분해서 붙이고, ")"로 마무리한다.
각 color argument는 직렬화된 <color>로 표현되고, 해당 argument에 퍼센트가 직렬화될 경우에는(아래 참고) " "와 직렬화된 퍼센트를 함께 쓴다.
각 color argument는 개별적으로 serialization된다; 특히, 동일한 색상을 갖더라도 하나의 argument로 합쳐지지 않는다.
선언값의 퍼센트는 color-mix() 함수마다 다음과 같이 결정된다. N을 color argument의 수라고 하자.
각 argument마다, 그 effective percentage는 다음과 같다:
-
해당 argument에 대해 명시적으로 지정되고, calc() 표현식이 아닌 <percentage>일 경우 그 값;
-
해당 <percentage>가 생략되었고, 다른 명시적 <percentage> 값들 중 calc() 표현식이 없다면:
(100% − specified sum) / omitted count, 이때 specified sum은 명시적으로 지정된 <percentage>의 합, omitted count는 생략된 <percentage>의 수; -
그 외는 unknown.
모든 effective
percentage가
알려져 있고
100% / N과 같으면,
퍼센트는 직렬화되지 않는다.
그렇지 않으면 각 argument의 퍼센트는 다음과 같이 직렬화된다:
-
<percentage>가 명시적으로 지정되어 있으면, 해당 값 그대로 직렬화된다.
-
<percentage>가 생략되고, 다른 명시적 <percentage> 중에 calc() 표현식이 없다면:
(100% − specified sum) / omitted count의 값을 직렬화하고, specified sum과 omitted count 정의는 위와 같다. -
아니면 (<percentage>는 생략되었고 다른 argument에 calc() <percentage>가 있는 경우): 아무것도 직렬화하지 않는다.
Note: calc() 값은
unknown 취급이며,
절대 100% / N이 될 수 없으므로,
생략된 <percentage>의 계산을 막는다.
color-mix(in oklab, teal, peru 40%)문자열 "color-mix(teal 60%, peru 40%)"가 된다: color space가 기본값(oklab)이므로 생략되고, 모든 퍼센트가 100%/2 = 50%가 아니어서 모두 직렬화된다.
다음 선언값의 serialization은
color-mix(in oklab, teal 50%, peru 50%)문자열 "color-mix(teal, peru)"가 된다: 두 퍼센트가 100%/2 = 50%이므로 직렬화는 모두 생략된다.
다음 선언값의 serialization은
color-mix(in oklab, teal 70%, peru 70%)문자열 "color-mix(teal 70%, peru 70%)"가 된다: 명시된 퍼센트가 70%로, 50%가 아니기 때문에 생략되지 않는다. (계산시에는 각각 50%로 정규화된다 하더라도.)
다음 선언값의 serialization은
color-mix(in oklch longer hue, red, green, blue)문자열 "color-mix(in oklch longer hue, red, green, blue)"가 된다: color space(oklch)가 기본값이 아니고, hue interpolation(longer)가 기본값(shorter)이 아니고, 퍼센트가 모두 100%/3이므로 모두 생략.
다음 선언값의 serialization은
color-mix(red 50%, green, blue)문자열 "color-mix(red 50%, green 25%, blue 25%)"가 된다: 퍼센트가 100%/3과 다르므로 모두 직렬화되며, 생략된 값도 (100%-50%)/2 = 25%로 각각 출력된다.
color-mix() 함수 결과의 serialization은 mix에 currentColor 키워드가 사용되었는지에 따라 달라진다. 사용된 경우, 결과는 선언값을 그대로 serialization한다. 이 덕분에 color 속성 값이 다른 자식 요소에서도 올바른 mixture가 적용된다. 그렇지 않으면, <color>가 되며, CSS Color 4 § 16. Serializing <color> Values 의 정의대로 처리된다. 사용되는 형식은 "in"으로 지정된 color space에 따라 다음과 같다:
| 믹싱 color space | 형식 |
|---|---|
| srgb | color(srgb r g b) |
| srgb-linear | color(srgb-linear r g b) |
| display-p3 | color(display-p3 r g b) |
| a98-rgb | color(a98-rgb r g b) |
| prophoto-rgb | color(prophoto-rgb r g b) |
| rec2020 | color(rec2020 r g b) |
| hsl | color(srgb r g b) |
| hwb | color(srgb r g b) |
| xyz-d65 | color(xyz-d65 x y z) |
| xyz-d50 | color(xyz-d50 x y z) |
| xyz | color(xyz-d65 x y z) ¹ |
| lab | lab(l a b) |
| lch | lch(l c h) |
| oklab | oklab(l a b) |
| oklch | oklch(l c h) |
- ¹
- xyz는 xyz-d65의 별칭일 뿐이기 때문
그러나 hsl 또는 hwb 색 공간에서 혼합한 결과에 적어도 하나의 누락된 색상 구성요소가 있으면 (CSS Color 4 § 13.2 누락된 구성요소로 보간하기에 따라 전달된 누락된 alpha를 포함), 사용되는 형식은 각각 현대적인 hsl(h s l / a) 또는 hwb(h w b / a) 구문이며, 원래의 색상 함수와 각 none 값을 CSS Color 4 § 16.2.2 sRGB 값의 CSS 직렬화에 따라 보존하고, color(srgb r g b)로 저하시키지 않는다(그렇게 하면 hsl/hwb 정체성이 손실된다).
Tests
최소 round-tripping 정밀도는 CSS Color 4 § 16. Serializing <color> Values에 명시된 것과 동일합니다.
color-mix(in lch, peru 40%, palegoldenrod)문자열 "lch(79.7256 40.448 84.771)"로 직렬화됩니다. 반면 다음의 결과는
color-mix(in srgb, peru 40%, palegoldenrod)문자열 "color(srgb 0.8816 0.7545 0.4988)"로 직렬화됩니다.
11.2. 원본 색상의 직렬화
다른 색상 함수 내부에서 원본 색상으로 사용되는 색상의 선언값 직렬화는 아래와 같습니다:
-
정규 색상 함수를 식별하는 문자열, rgb()와 rgba()의 경우 "rgb", hsl() 및 hsla()의 경우 "hsl", 모두 소문자, 다음에 "(", 그 다음 지정된 알파가 아닌 성분들을 공백으로 구분하여 나열 (숫자는 숫자로, 백분율은 백분율로, 각도는 도 단위로 정규화, calc()는 단순화된 형태로) clamp(클램프) 없이 직렬화, 알파 성분이 있으면 " / " 다음에 알파 성분(위와 동일 규칙) 마지막으로 ")"가 붙습니다.
참고: 모던 문법이든 레거시 문법이든 동일하게 직렬화됩니다.
-
색상 함수를 소문자로 식별하는 문자열 다음에 "(", 지정된 알파가 아닌 성분들을 공백으로 구분하여 나열 (숫자, 백분율, 각도(도 단위 정규화), calc()는 단순화, clamp 적용하지 않음), 알파 성분이 있으면 " / " 다음에 알파 성분(색상 성분과 동일 규칙) 마지막으로 ")"가 붙습니다.
-
color()인 경우
-
문자열 "color(" 다음에 정규 색상 공간 ("xyz"의 경우 "xyz-d65")을 소문자로 한 칸 띄우고, 다시 지정된 알파가 아닌 성분들을 공백으로 구분하여 나열 (숫자, 백분율, 각도(도 단위로 정규화), calc()는 단순화됨), clamp 적용하지 않음, 알파 성분이 있으면 " / " 다음에 알파 성분(색상 성분과 동일 규칙) 마지막으로 ")"가 붙습니다.
11.3. 상대 색상 함수 직렬화
상대 색상의 선언값 직렬화는 다음과 같습니다:
-
정규 색상 함수를 소문자로 식별하는 문자열, rgb(), rgba()의 경우 "rgb", hsl(), hsla()의 경우 "hsl", 다음에 "(from ", 원본 색상의 직렬화를 중첩 원본 색상 직렬화 규칙에 따라, 한 칸 띄우고, 지정된 알파가 아닌 채널 인자들을 공백으로 구분하여 나열 (식별자는 식별자로, 숫자/백분율, 각도(도 단위 정규화), calc()는 단순화), 알파 성분이 1이 아닌 경우 " / " 이후에 알파 성분(채널 인자와 동일 규칙, 단 clamp 적용) 마지막으로 ")"가 붙습니다.
-
색상 함수를 소문자로 식별하는 문자열, 다음에 "(from ", 원본 색상 직렬화를 중첩 규칙으로, 한 칸 띄우고, 알파가 아닌 채널 인자들을 공백으로 구분하여 나열 (식별자, 숫자/백분율, 도 단위 각도, calc()는 단순화), 알파가 1이 아니면 " / " 이후 알파(채널 인자와 동일 규칙, clamp 적용) 마지막으로 ")"가 붙습니다.
-
color()인 경우
-
문자열 "color(from ", 원본 색상 직렬화를 중첩 규칙으로, 한 칸 띄우고, 정규 색상 공간("xyz"의 경우 "xyz-d65")을 소문자로, 한 칸 띄우고, 알파가 아닌 채널 인자들을 공백으로 구분하여 나열 (식별자, 숫자/백분율, 도 단위 각도, calc() 단순화), 알파가 1이 아니면 " / " 이후 알파(채널 인자와 동일 규칙, clamp 적용) 마지막으로 ")"가 붙습니다.
rgb ( from redcalc ( r /2 ) gcalc ( 30 % ));
"rgb(from red calc(0.5 * r) g calc(30%))"라는 문자열이 되며, 계산값 직렬화는 "color(srgb 0.5 0 0.3)" 문자열이 됩니다.
hsl ( fromhsl ( none10 % 50 % ) h s l);
"hsl(from hsl(none 10% 50%) h s l)"가 되고, 계산값 직렬화는 "color(srgb 0.55 0.45 0.45)" 문자열입니다.
hsl ( from rebeccapurple none none none / none);
문자열 "hsl(from rebeccapurple none none none / none)"입니다.
계산값은 누락된 alpha를 전달한다 (alpha는 그 자체의 유사 구성요소이다). 이는 hue, saturation, lightness, alpha가 모두 누락된 hsl() 상대 색상을 제공한다. 해결된 값이 누락된 색상 구성요소를 포함하므로, 직렬화는 현대적인 hsl() 형식을 사용하여, color(srgb 0 0 0 / none)이 아니라 문자열 "hsl(none none none / none)"을 산출한다.
hsl ( fromhsl ( 127.9 302 % 25.33 % ) h s l);
"hsl(from hsl(127.9 302% 25.33%) h s l)"가 되고, 계산값 직렬화는 "color(srgb -0.511666 1.018266 -0.310225)"입니다.
< div id = "example" style = "background-color: rgb(from currentcolor r g calc(b / 2)); color: blue;" > </ div >
background-color 선언값 직렬화는 "rgb(from currentcolor r g calc(b / 2))" 문자열이며, 계산값은 "color(srgb 0 0 0.5)"입니다
상대 색상 함수 결과 직렬화는 currentColor 키워드가 원본 색상인지에 따라 달라집니다. 그렇다면 선언값으로 직렬화됩니다. 이를 통해 자식 요소의 color 속성 값이 달라져도 올바른 값이 사용될 수 있습니다. 아니라면 해석된 값, 즉 <color>가 됩니다. CSS Color 4 § 16. Serializing <color> Values을 따릅니다.
실제 적용 형태는 상대 색상의 색상 공간에 따라 달라집니다:
| mixing color space | form |
|---|---|
| srgb | color(srgb r g b) |
| srgb-linear | color(srgb-linear r g b) |
| display-p3 | color(display-p3 r g b) |
| a98-rgb | color(a98-rgb r g b) |
| prophoto-rgb | color(prophoto-rgb r g b) |
| rec2020 | color(rec2020 r g b) |
| hsl | color(srgb r g b) |
| hwb | color(srgb r g b) |
| xyz-d65 | color(xyz-d65 x y z) |
| xyz-d50 | color(xyz-d50 x y z) |
| xyz | color(xyz-d65 x y z) |
| lab | lab(l a b) |
| lch | lch(l c h) |
| oklab | oklab(l a b) |
| oklch | oklch(l c h) |
그러나 hsl() 또는 hwb() 상대 색상의 해결된 값에 적어도 하나의 누락된 색상 구성요소가 있으면 (전달된 누락된 alpha를 포함하며, 이는 원본 색상으로부터 CSS Color 4 § 13.2 누락된 구성요소로 보간하기에 따른 것이다), 사용되는 형식은 각각 현대적인 hsl(h s l / a) 또는 hwb(h w b / a) 구문이며, 원래의 색상 함수와 각 none 값을 보존하고, color(srgb r g b)로 저하시키지 않는다(그렇게 하면 hsl/hwb 정체성이 손실된다). 이는 § 11.2 원본 색상 직렬화하기와 나란한데, 그 절은 원본 색상에 대해 항상 현대적인 슬래시 구문을 내보내며, CSS Color 4 § 16.2.2 sRGB 값의 CSS 직렬화에 있는 일반 sRGB 직렬화 규칙을 따른다.
Tests
최소 round-trip 정밀도는 CSS Color 4 § 16.5 color() 함수 값의 직렬화에 명시된 것과 같습니다.
문자열 "lch(49.80224 37.80819 243.6803)" 입니다.lch ( from perucalc ( l *0.8 ) calc ( c *0.7 ) calc ( h +180 ))
11.4. 사용자 정의 색상 공간 직렬화
color() 성분 값의 정밀도, 즉 직렬화 값의 유효 숫자 자리수는 이 명세에서 정의되어 있지 않습니다. 단, CMYK 색상 공간의 경우 값이 8비트 정밀도로 round-trip(왕복 변환)될 수 있을 만큼 충분해야 하며, 이는 소수점 둘째 자리 이상(단, 끝 0 생략 가능)이어야 합니다.
아래 색상의 직렬화 값은
@color-profile --swop5c{ src : url ( 'https://example.org/SWOP2006_Coated5v2.icc' ); } .header{ background-color : color ( --swop5c0 % 70.0 % 20.00 % .0 % ); }
"color(--swop5c 0 0.7 0.2 0)"로 직렬화됩니다
11.5. device-cmyk 값 직렬화
device-cmyk() 값의 직렬화 형태는 계산값에서 비롯되며, 함수 이름은 소문자로 하여 device-cmyk() 형태를 사용합니다.
각 성분 값은 <number>로, 십진수(base 10)로 직렬화합니다. 컴포넌트 값 사이 분리자는 반드시 ASCII 스페이스 " " 하나여야 합니다.
각 성분 값의 끝 소수점 0은 생략해야 하며; 소수점 이하가 모두 0이라면, 소수점 자체도 생략됩니다.
device-cmyk() 성분 값의 정밀도, 즉 직렬화 값의 유효 숫자 자리수는 이 명세에서 정의되어 있지 않으나, 8비트 정밀도로 왕복 변환이 가능할 만큼 충분해야 하며 소수점 둘째 자리 이상(끝 0 생략 가능)이어야 합니다. 값은 +∞ 쪽으로 반올림해야 하며, 단순히 버려(truncate)서는 안 됩니다.
알파 값이 1일 때는 명시적으로 직렬화하지 않습니다. 1이 아닌 알파 값은 명확히 직렬화해야 하며, 문자열 " / " (스페이스, 슬래시, 스페이스)가 블랙("k")성분 값과 알파 값 사이의 구분자로 사용되어야 합니다.
12. API
12.1.
CSSColorProfileRule 인터페이스
CSSColorProfileRule 인터페이스는 @color-profile 규칙을 나타냅니다.
[Exposed =Window ]interface :CSSColorProfileRule CSSRule {readonly attribute CSSOMString name ;readonly attribute CSSOMString src ;readonly attribute CSSOMString renderingIntent ;readonly attribute CSSOMString components ; };
name, 타입 CSSOMString, 읽기 전용-
name 속성은 다음을 반환해야 합니다:
관련 규칙에 대해 정의된 컬러
프로파일의 name 직렬화를 포함하는
CSSOMString객체 src, 타입 CSSOMString, 읽기 전용renderingIntent, 타입 CSSOMString, 읽기 전용components, 타입 CSSOMString, 읽기 전용-
나머지 속성들은
관련 규칙에 대해 정의된 관련 디스크립터의 직렬화를 포함하는
CSSOMString객체를 반환해야 합니다. 디스크립터가 규칙에 지정되지 않았다면, 속성 값은 빈 문자열을 반환해야 합니다.
13. 기본 스타일 규칙
아래 스타일시트는 참고용이며, 표준 문서가 아닙니다. 구현체가 HTML 패밀리 문서의 기본 스타일링 일부로 사용할 수 있습니다.
/* 데스크탑 사용자 에이전트의 하이퍼링크 전통 색상 */ :link{ color : LinkText; } :visited{ color : VisitedText; } :active{ color : ActiveText; } /* device-cmyk에 대한 합리적이고 보수적인 기본값 */ @color-profile device-cmyk{ src : url ( 'https://drafts.csswg.org/css-color-4/ICCprofiles/Coated_Fogra39L_VIGC_300.icc' ); }
14. 색 변환 샘플 코드
이 부분은 표준이 아닙니다.
device-cmyk의 단순 변환은 매우 쉽습니다:
function naive( cmyk) { // naively convert an array of CMYK values // to sRGB let [ cyan, magenta, yellow, black] = cmyk; let red= 1 - Math. min( 1 , cyan* ( 1 - black) + black); let green= 1 - Math. min( 1 , magenta* ( 1 - black) + black); let blue= 1 - Math. min( 1 , yellow* ( 1 - black) + black); return [ red, green, blue]; }
15. 보안 고려사항
이 명세는 CSS에 온디맨드 ICC 프로파일 다운로드 기능을 추가합니다. ICC 프로파일에는 실행 가능한 코드가 없으므로, 보안 위험이 증가하지 않습니다.
16. 개인정보 보호 고려사항
이 명세와 관련해 신규 개인정보 보호 고려사항이 보고되지 않았습니다.
17. 접근성(Accessibility) 고려사항
이 명세는 사용자가 지정한 색상(동적 색 포함)을 배경으로 쓸 때 텍스트 대비가 충분한지 보장하는 방법을 추가합니다.
18. 변경 이력
18.1. 2026년 1월 13일 워킹 드래프트 이후
- 이 명세의 색 보간(Color Interpolation)에서, 대부분의 내용이 정의된 CSS Color 4의 동일 섹션으로의 역링크를 추가함 (이슈 13788)
- light-dark() 함수의 두 번째 형태가 추가되었습니다. 이제 색상 쌍이 아니라 이미지 쌍을 받을 수 있습니다 (이슈 12513)
- light-dark()의 이미지 형태에 "none" 옵션 추가 (이슈 12513)
- 이제 두 개로만 제한되지 않으므로, 세 가지 색상으로 된 color-mix() 예제가 추가되었습니다.
- color-mix() 직렬화 업데이트: color space가 기본값(oklab)일 때는 생략, hue interpolation method가 기본값이 아니면 직렬화, N개 색상에 대해 퍼센트 규칙 일반화 (모두 100%/N과 같으면 생략, 아니면 모두 직렬화), 동일 색상도 결합(합쳐짐)되지 않음을 명확히 함 (Issue 13320)
18.2. 2025년 3월 18일 워킹 드래프트 이후
- relative colors에서 CSS Color 4 정의로의 백링크 추가 (이슈 13286)
- 여러 개의 @color-profile 규칙 존재 시 마지막 규칙이 적용되도록 정의 (이슈 12980)
- color-mix()의 기본값을 oklab으로, color-interpolation-method는 생략 허용 (이슈 10484)
- color-mix()가 두 색상만 쓸 수 있다는 전제 남은 부분 삭제
- origin colors 직렬화 업데이트 (이슈 10328)
- 보간용 색상 공간에 display-p3-linear 추가
- alpha() RCS 함수 추가
- color-mix가 실질적으로 두 색상 제한이던 설명 업데이트
- 스타일 리소스 외부 URL 가져오기 설명 명확화
- color-mix() 단독 항목이 지정된 색 공간으로 반환되는 것 명시
- 컬러 혼합 알고리즘이 normalization flag를 전달하도록 개선
- color-mix()가 일반적으로 *-mix()와 같이 1개 이상 인자 허용
- “resolve to sRGB” 및 “legacy color syntax” 관련 정의를 CSS Color 4에서 포트
- device-cmyk에서 단순 변환하는 javascript 예시 코드 추가
- device-cmyk fallback color 사용 color-mix() 예시 추가
- device-cmyk()에는 RCS 없음 명확히 표기
- color-mix()에서 퍼센트 합이 0이면 transparent 반환 정의
- color-mix()가 normalization flag를 넘기도록
- color-mix()에 1개 이상 인자 허용을 *-mix()와 일치시키도록
- ...
18.3. 2024년 2월 29일 워킹 드래프트 이후
- 구성요소 키워드가 숫자뿐만 아니라 none도 반환할 수 있음을 명확히 함
- 중첩 색상 함수 직렬화 예시 추가
- wg 결의에 따라 color-mix()에서 calc 사용 예외 처리 정의
- wg 결의에 따라 color-mix() 퍼센트 합 0에서 invalid wording 제거
- color channel/색상 채널 용어 일관 사용 및 “color component”로 단일화
- wg 결의에 따라 contrast-color() 단순화
- premultiplied 용어 연결 일관화
- color profile 컴포넌트 대소문자 무시 검증
- contrast-color()를 color type 정의에 추가
- 접근성 고려사항 섹션 추가
- FOGRA39, 51, 55 관련 참조 추가
- 문법에서 rectangular color spaces에 hue-interpolation-method가 허용되지 않음 강조
- relative color component가 어떤 색 공간 기준인지 명확화
- relative color 개념 설명과 구문상 세부 설명 분리
- deltaE 테이블 텍스트 대비 보장
- relative color component는 clamp하지 않으며 alpha만 clamp한다는 점 명확화
18.4. 2022년 6월 28일 워킹 드래프트 이후
- 선언된 값(declared values) 기준으로 CSSOM 직렬화(serialization) 설명
- contrast-color() 함수 추가
- color-mix()에 대한 보간(interpolation) 섹션 명시적 링크
- HSL로의 gamut mapping 관련 잔여 언급 제거
- 절대 색상(absolute colors)을 문서로 정의, 문법(grammar) 대신
- RCS에서 퍼센트-숫자(percent-to-number) 변환 참조 범위 명시
- origin color가 currentColor인 상대 색상(relative colors) 직렬화 개선. sRGB, hsl() 및 hwb()는 color(srgb ...) 사용하여 라운드 트립 가능
- 요약(abstract) 업데이트: light-dark() 함수 언급
- CSS Color 4에서 직사각형 색상 공간(rectangular color spaces) 목록 이관
- 커스텀 파라미터 문법 수정(공백 구분, 쉼표 아님)
- device-cmyk() 문법에서 누락되었던 none 및 CSS GCPM의 이전(legacy) 구문에 대한 수정
- color-mix()를 color 타입 문법에 추가
- 지정된 RCS 값 직렬화 명확화
- light-dark() 함수 추가
- color-mix 퍼센트 정규화 알고리즘 수정: 50% 경계 케이스 포함
- HSL 예제 업데이트: sRGB → HSL 변환 전 gamut mapping 제거
- 몇몇 예제 구문 하이라이트 수정
- RCS origin color가 선택적 알파 가능함 명확화
- 잘못된 powerless component 사용 수정
- 퍼센트 → 숫자 변환 참조 범위 사용
- hsl() 및 hwb() 구성 요소 값을 숫자로 변경, 모든 색상 각도(hue)도 숫자(도 단위)로 변경
- CIE XYZ D65 색공간 예제 추가
- 읽기 혼동되는 CSS Color 4 섹션 불필요 복사본 제거
- 섹션 제목 수정: "Specifying Predefined and Custom Color Spaces: the color() Function"
- HWB가 이제 숫자 허용, 이전에는 퍼센트만 가능
- RCS 구성 요소 비정상 위치 사용 시 "마법 스케일링" 없음, 필요 시 calc() 사용, 예제 추가
- CIE Lightness와 Oklab lightness 구분 명확화
- color-mix() 결과 직렬화 명확화, currentColor 사용 예제 추가
- color-mix 예제 오타 수정
- powerless components에서 0 대신 none 사용 예제 수정
- color-mix 지정 값(serialized specified value) 직렬화 정의: 정규화되지 않은 퍼센트 사용
- alpha-value 정의 불변, Color 4 링크로 대체
- 현대(modern) 및 레거시(legacy) rgb, rgba, hsl, hsla 문법 분리
- origin color 제한 없음, 현대/레거시 구문 모두 가능
- 새 color 생산법(color production) 추가, RCS 중첩 가능 명시
- RGB/HSL 퍼센트와 숫자 혼합 자유화, RCS 제한 없음
- RCS는 현대 색상 구문에만 적용됨
- 필수 색상 공간 변환 정의, 불필요한 변환 생략 가능
- 올바른/잘못된 그라디언트 렌더링 이미지 추가
- 커스텀 색상 공간에서 이름 없는 구성 요소 유효함 명확화
- 예제 개선
- 누락된 구성 요소가 있는 RCS 정의
- color-interpolation method에 dashed-ident 추가, 커스텀 색상 공간에서 보간 가능
- RCS hue 구성 요소는 숫자(도 단위)로 해결됨 명확화
- origin color가 currentColor인 RCS 결과 명시
- 채널 키워드는 단일 타입만 가능
- 레거시 구문 RCS 예제 수정, 실제 레거시 구문 사용
- 예제 직렬화 일관성 유지
- device-cmyk() 직렬화 정의 존재 명시
- CSSColorProfileRule 인터페이스 추가
- Oklab와 OkLCh 표기 일관성
- 색상 견본(color swatch) 접근성 개선
- 다이어그램 접근성 개선
- 일부 색상 견본 잘림(clipping) 수정
- 몇몇 그림의 대체 텍스트 개선
- 누락된 색상 견본 추가
- MacBeth 이미지 및 deltaE 표에 행/열 레이블 추가
- hue-rotate 다이어그램 레이블 개선
- 다이어그램 색상 설명 개선, 접근성 향상
- 모든 다이어그램과 그림에 ID 및 self-link 추가
18.5. 2022년 4월 28일 워킹 드래프트 이후
- rgb() 정의의 오타를 수정함
- 편집상 개선(대소문자, 철자, 명확성)
- 다른 규격에서 사용할 수 있도록 정의를 export함
- none이 누락된 것을 color() 문법의 alpha에 추가
- color-contrast() 함수를 6단계로 이동함
18.6. 2021년 12월 15일 워킹 드래프트 이후
- color() 인자 과다/부족 forgiving은 사용자정의 색 공간에 한정
- RCS 전체에서 percent/number 혼용 허용
- PI 등 상수와 컴포넌트명 충돌 가능성 명확화
- Relative Color Syntax에서 legacy(콤마) 구문 미사용 명확화
- rgb() 함수의 문법 수정, none이 alpha의 옵션으로 나열되어 있지 않았음
- color-mix()에서 hsl, hwb 사용 시 정밀도 극대화 직렬화로 변경
- gamut 밖 색상 color-mix 예시 추가
- HSL, HWB가 색상 확장(out of gamut) 못 한다 설명에 "cannot express the color" 용어 일관 사용
- 맞춤법, 문법, 포맷 오타 교정 일부
18.7. 2021년 6월 1일 워킹 드래프트
- rectangular 공간에서 <hue-interpolation-method> 사용 시 오류로 간주
- 구문 <hue-adjuster>를 <hue-interpolation-method>로 교체
- @color-profile, device-cmyk를 level 5로 이동 (CSSWG 결의)
- none을 컴포넌트 이름으로 제외
- OkLCh 상대 색상 문법 예시 추가
- 보간 색상 공간 정의
- color profile 로딩을 fetch로 명확화
- contrast는 D65-adapted CIE XYZ 기준으로 계산 명확화
- color-mix(), color-contrast, 상대 색상 구문의 결과 직렬화 규칙 정의 추가
18.8. 2020년 6월 10일 FPWD 이후
- color() 함수용 상대 색상 문법 추가
- color-adjuster는 선택사항이 아님을 명확화
- color-mix에서 퍼센트는 필수 명확화
- hue-adjuster를 color-mix 쪽으로 이동
- 다른 색 공간 예시 추가
- color-mix() 퍼센트 정규화 예시 추가
- color-mix()에 음수 퍼센트 명시적 배제
- 퍼센트 합이 100% 미만이면 알파가 100% 미만 투명도 제공
- color space 용어 일관적 사용, <color-space> 토큰 정의
- color-contrast 문법 오류 수정
- color-contrast()에 optional target contrast ratio 추가
- adjuster 문법 오류 수정
- 퍼센트 합이 0인 경우 corner case 처리 명시
- color-mix() 연산 순서 명확화
- 예시를 최신 문법과 일치시킴
- 퍼센트 정규화 알고리즘 명확화
- color-mix()의 0%, 100% 의미 명확화
- adjuster 정의를 color-mix()에서 color-adjust()로 이동
- color-mix() 인자 순서 임의 허용
- color-mix() 색상 공간 명시 필수화
- 퍼센트가 color-mix() 값 앞에 와도 허용
- color-mix()의 명시적 알고리즘 추가
- color-mix(), color-adjust()의 adjuster 제거 및 문법 단순화
- 혼합에 사용할 색상 공간 명시 "in" 키워드 추가
- color-contrast() 항목 2개 이상 필수 명시
- relative color 문법 안내 보강
- CSS 4 정의 색상 직렬화 링크 추가
- 색상 공간 섹션 분리
- color-adjust 예시 업데이트
- 설명 다이어그램 추가
- unresolved percent 처리
- adjuster에 percent 허용
- 링크 수정
- color-mix 문법, adjuster+alpha 허용 업데이트
- 성문 예시 일부 교정
- 색상 혼합 퍼센트 정규화 알고리즘 설명
- 0%와 100% 의미 명확화
- color-adjuster, 색상 공간 정의
- color-mix 인자 정렬 알고리즘 명확화
- 작동 예 및 그림 추가
- 맞춤법, 문법, 형식 수정
- color-contrast() 해석 방식 정의
18.9. CSS Color 4와의 차이점
CSS Color 4와 비교해 주요 변경점 중 하나는, CSS 색상이 더는 사전에 정의된 sRGB, display-p3 등 RGB 색 공간에 한정되지 않는다는 것입니다.
이를 위해, 다음과 같은 새로운 기능이 추가되었습니다:
- color() 함수가 @color-profile at-rule로 확장되어, 보정된 CMYK 등 프로파일 장치 의존 색상도 지원
- device-cmyk() 함수로 출력 장치 특화 비보정 CMYK 색 지정
또한, color-mix() 함수가 두 색상을 지정한 색상 공간에서 혼합해 새로운 색을 만들어낼 수 있습니다.