1. 소개
이 섹션은 규범적이지 않습니다.
테스트
이 섹션은 규범적이지 않으며, 테스트가 필요하지 않습니다.
이 모듈은 작성자가 요소의 텍스트 콘텐츠의 전경색과 불투명도를 지정할 수 있도록 하는 CSS 속성을 설명합니다. 또한 CSS <color> 값 유형을 자세히 설명합니다.
이 모듈은 CSS1, CSS2, 및 CSS Color 3에 이미 존재하는 색상 관련 속성과 값을 정의할 뿐만 아니라, 새로운 속성과 값도 정의합니다.
특히, sRGB 이외의 색상 공간에서 색상을 지정할 수 있도록 합니다. 이전에는 sRGB 색역 외부의 더 포화된 색상을 CSS에서 사용할 수 없었으며, 디스플레이 장치가 이를 지원하더라도 사용할 수 없었습니다.
초안 구현 보고서를 사용할 수 있습니다.
1.1. 값 정의
이 명세는 CSS 속성 정의 규칙을 따르며, [CSS2]에서, 값 정의 구문을 사용하여 [CSS-VALUES-3]에서 가져옵니다. 이 명세에서 정의되지 않은 값 유형은 CSS Values & Units [CSS-VALUES-3]에서 정의됩니다. 다른 CSS 모듈과의 조합은 이러한 값 유형의 정의를 확장할 수 있습니다.
정의에 나열된 속성별 값 외에도, 이 명세에서 정의된 모든 속성은 CSS-wide 키워드를 속성 값으로 허용합니다. 가독성을 위해 이를 명시적으로 반복하지 않았습니다.
2. 색상 용어
테스트
이 섹션은 이후에 사용될 정의를 제공합니다. 테스트는 필요하지 않습니다.
색상은 빛이나 빛으로 조명된 물체에 대한 인간의 시각적 인식에 대한 정의(숫자 또는 텍스트)입니다. 인간 색각에 대한 객관적 연구는 색채학이라고 합니다.
물리적 물체의 색상은 각 가시 파장에서 반사되는 빛의 양과 (동일하게, 각 파장에서의 빛의 양) 조명을 제공하는 빛의 실제 색상에 따라 달라집니다. 분광광도계에 의해 측정됩니다.
빛을 방출하는 물체의 색상 (컴퓨터 화면의 색상을 포함)은 각 가시 파장에서 방출되는 빛의 양에 따라 달라집니다. 분광복사계에 의해 측정됩니다.
두 물체가 스펙트럼이 다르지만, 여전히 동일한 물리적 감각을 만들어내는 경우, 우리는 그것들이 동일한 색상을 가지고 있다고 말합니다. 스펙트럼을 CIE XYZ (세 숫자)로 변환하여 두 색상이 동일한지 계산할 수 있습니다.
색상 공간은 기본 색채학적 모델과 관련하여 색상을 체계적으로 조직하는 것입니다. 이를 통해 해당 색상 공간 내의 모든 색상에 대해 명확하고 객관적으로 측정 가능한 의미를 제공합니다. 이는 동일한 색상이 여러 색상 공간에서 표현되거나, 한 색상 공간에서 다른 색상 공간으로 변환되더라도 여전히 동일하게 보일 수 있음을 의미합니다.
한 잎을 분광광도계로 측정한 결과, lch(51.2345% 21.2 130) 색상이며, 이는 lab(51.2345% -13.6271 16.2401)으로 표현됩니다.
이 동일한 색상은 여러 색상 공간에서 다음과 같이 표현될 수 있습니다:
color ( sRGB0.41587 0.503670 0.36664 ); color ( display-p30.43313 0.50108 0.37950 ); color ( a98-rgb0.44091 0.49971 0.37408 ); color ( prophoto-rgb0.36589 0.41717 0.31333 ); color ( rec20200.42210 0.47580 0.35605 );
가산 색상 공간은 좌표계가 광 강도에 대해 선형인 공간을 의미합니다. CIE XYZ 색상 공간은 가산 색상 공간입니다. XYZ의 Y 구성 요소는 휘도이며, 단위 면적당 광 강도, 즉 '얼마나 밝은지'를 나타냅니다. 휘도는 cd/m²(칸델라 매 제곱미터)로 측정되며, 흔히 니트(nits)라고도 합니다.
가산 색상 공간에서는 색상 혼합을 정확히 예측할 수 있는 계산이 가능합니다. 대부분의 RGB 공간은 가산적이지 않은데, 이는 구성 요소들이 감마로 인코딩되었기 때문입니다. 이 감마 인코딩을 해제하면 선형 조명 값이 생성됩니다.
두 개의 서로 다른 색상의 스포트라이트가 무대 위를 비춘다고 가정하면, 하나는 측정된 값이 color(xyz 0.15 0.24 0.17) 이고, 다른 하나는 color(xyz 0.11 0.06 0.06)인 경우, 두 색상의 광선이 겹칠 때 혼합된 색상은 XYZ 구성 값의 합계, 즉 color(xyz 0.26 0.30 0.23)이 될 것이라고 정확히 예측할 수 있습니다.
색도는 밝기 요소가 제거된 색상 측정입니다. 위에서 언급된 동일한 조명 예에서, 하나의 조명이 가진 u',v' 색도는 (0.2537, 0.5268)이며, 두 조명이 있을 때에도 색도는 동일합니다 (같은 색상이지만, 더 밝아졌을 뿐입니다).
색도는 가산적이므로, 혼합의 색도(그러나 결과 밝기는 제외)를 정확하게 예측할 수 있습니다. 색도는 2차원이기 때문에, 색도 혼합을 예측하기 위해 색도 다이어그램에 쉽게 표현할 수 있습니다. 임의의 두 색상을 혼합할 수 있으며, 결과 색상은 다이어그램에서 두 색상을 연결하는 선 위에 위치하게 됩니다. 세 가지 색상은 평면을 형성하며, 결과 색상은 다이어그램에서 이들이 형성하는 삼각형 내부에 위치하게 됩니다.
따라서 RGB 색상 공간이 선형화되면 가산적이 되며, 빨강, 초록, 파랑 기본 색상의 색도와 백색점 (모든 기본 색상이 최대 강도로 결합될 때 형성되는 색상)의 색도로 색역이 정의됩니다.
대부분의 색상 공간은 몇 가지 주광을 모사한 백색점 중 하나를 사용하며, 이는 해당 블랙바디 라디에이터의 상관 색온도(CCT) [Understanding_CCT]로 명명됩니다. 예를 들어, D65는 상관 색온도가 6500 켈빈 (실제로는 6504, 플랑크 상수 값이 색상이 처음 정의된 이후 변경되었기 때문)인 주광 백색점입니다.
누적 왕복 오류를 방지하기 위해, 동일한 색도 값이 계산의 모든 곳에서 일관되게 사용되는 것이 중요합니다. 따라서, 최대 호환성을 위해, 이 명세에서는 다음 두 가지 표준 주광 모사 백색점이 정의됩니다:
이름 | x | y | CCT |
---|---|---|---|
D50 | 0.345700 | 0.358500 | 5003K |
D65 | 0.312700 | 0.329000 | 6504K |
측정된 물리적 특성 (사용된 기본 색상의 색도와, 주어진 입력 세트에 대한 반응으로 생성된 색상 등)이 색상 공간 또는 색상 생성 장치에 대해 알려진 경우, 이를 특성화(characterized)되었다고 합니다.
추가로 장치가 백색점, 회색의 중립성, 톤 응답의 예측 가능성과 일관성 같은 보정 목표를 충족하도록 조정된 경우, 이를 보정(calibrated)되었다고 합니다.
실제 물리적 장치는 아직 인간 눈이 볼 수 있는 모든 색상을 생성할 수 없습니다. 특정 장치가 생성할 수 있는 색상의 범위를 색역(gamut)이라 하며, (감마와 혼동하지 마십시오). 색역이 제한된 장치는 무지개에서 볼 수 있는 것과 같은 매우 포화된 색상을 생성할 수 없습니다.
다른 색상 공간의 색역은 표현할 수 있는 색상의 부피(큐빅 Lab 단위)를 비교하여 확인할 수 있습니다. 다음 표는 CSS에서 사용할 수 있는 미리 정의된 색상 공간을 조사합니다.
색상 공간 | 부피 (백만 Lab 단위) |
---|---|
sRGB | 0.820 |
display-p3 | 1.233 |
a98-rgb | 1.310 |
prophoto-rgb | 2.896 |
rec2020 | 2.042 |
CSS의 색상은 유효하지 않은 색상이거나, 각 구문 형식에 대해 아래에 설명된 대로, 유효한 색상입니다.
유효하지 않은 색상이 아닌 모든 색상은 유효한 색상입니다.
유효한 색상은 여전히 출력 장치 (화면, 프로젝터, 프린터 등)가 생성할 수 있는 색상 범위를 벗어날 수 있습니다.
이를 색역 외(out of gamut)라고 합니다.
각 유효한 색상은 특정 출력 장치(화면 또는 프린터)에 대해 색역 내(in-gamut)이거나, 색역 외(out of gamut)입니다.
color ( prophoto-rgb0.88 0.45 0.10 )
이는 display-p3로 표현했을 때, 하나 이상의 좌표가 1.0보다 크거나 0.0보다 작기 때문입니다:
color ( display-p31.0844 0.43 0.1 )
이 색상은 유효하며, 예를 들어 그라디언트 정지점으로 사용할 수 있지만, 표시를 위해 CSS 색역 매핑이 필요하며, 비슷하게 보이지만 채도가 낮은(덜 포화된) 색상을 생성합니다.
3. CSS에서 색상 적용
3.1. 접근성과 색상으로 정보 전달
테스트
이 섹션은 작성 지침을 제공합니다. 테스트는 필요하지 않습니다.
색상은 문서에 중요한 정보를 추가하고 가독성을 높일 수 있지만, 색상만으로 중요한 정보를 전달해서는 안 됩니다. 작성자는 문서에서 색상을 사용할 때 W3C 웹 콘텐츠 접근성 가이드라인 [WCAG21]을 고려해야 합니다.
1.4.1 색상 사용: 색상은 정보를 전달하거나, 작업을 나타내거나, 반응을 유도하거나, 시각적 요소를 구별하는 데 유일한 시각적 수단으로 사용되지 않습니다
3.2. 전경색: color 속성
이름: | color |
---|---|
값: | <color> |
초기값: | CanvasText |
적용 대상: | 모든 요소 및 텍스트 |
상속 여부: | 예 |
퍼센트: | N/A |
계산된 값: | 계산된 색상, 색상 값 해결 참조 |
정규 순서: | 문법에 따름 |
애니메이션 유형: | 계산된 값 유형에 따라 |
테스트
이 속성은 요소의 주요 전경색을 지정합니다. 이는 텍스트 콘텐츠의 채우기 색상으로 사용되며, 추가적으로 사용된 값을 지정하여 currentcolor로 해석됩니다. 이는 이 전경색에 대한 간접 참조를 허용하며, border-color 및 text-emphasis-color와 같은 다양한 다른 색상 속성의 초기값에 영향을 미칩니다.
- <color>
- 지정된 <color>로 주요 전경색을 설정합니다.
em{ color : lime; } /* 색상 키워드 */ em{ color : rgb ( 0 255 0 ); } /* RGB 범위 0-255 */ em{ color : rgb ( 0 % 100 % 0 % ); } /* RGB 범위 0%-100% */ em{ color : color ( sRGB0 1 0 ); } /* sRGB 범위 0.0-1.0 */
이 속성이 텍스트에 적용될 때, 알파 구성 요소를 포함하여,
"색상 글리프"(일부 글꼴의 이모지 등)에는 영향을 미치지 않습니다.
이러한 글리프는 내장 팔레트로 색상이 지정됩니다.
그러나 일부 색상 글꼴은 컨텍스트 "전경색"을 참조할 수 있으며,
예를 들어 OpenType의 COLR
테이블에서 0xFFFF 팔레트 항목
또는 SVG-in-OpenType의 context-fill 값을 통해 가능합니다.
이러한 경우, 전경색은 이 속성에 의해 설정되며,
currentcolor 값 설정과 동일합니다.
3.3. 투명도: opacity 속성
Opacity는 후처리 작업으로 볼 수 있습니다. 개념적으로, 요소(자식 요소 포함)가 RGBA 오프스크린 이미지로 렌더링된 후, opacity 설정은 오프스크린 렌더링을 현재 합성 렌더링에 어떻게 혼합할지 지정합니다. 자세한 내용은 단순 알파 합성을 참고하세요.
이름: | opacity |
---|---|
값: | <opacity-value> |
초기값: | 1 |
적용 대상: | 모든 요소 |
상속: | 아님 |
백분율: | [0,1] 범위로 매핑 |
계산값: | 지정된 숫자, [0,1] 범위로 클램핑 |
정식 순서: | 문법에 따라 |
애니메이션 유형: | 계산값 유형 기준 |
테스트
- clip-opacity-out-of-flow.html (실시간 테스트) (소스)
- t32-opacity-basic-0.0-a.xht (실시간 테스트) (소스)
- t32-opacity-basic-0.6-a.xht (실시간 테스트) (소스)
- t32-opacity-basic-1.0-a.xht (실시간 테스트) (소스)
- t32-opacity-clamping-0.0-b.xht (실시간 테스트) (소스)
- t32-opacity-clamping-1.0-b.xht (실시간 테스트) (소스)
- t32-opacity-offscreen-b.xht (실시간 테스트) (소스)
- t32-opacity-offscreen-multiple-boxes-1-c.xht (실시간 테스트) (소스)
- t32-opacity-offscreen-multiple-boxes-2-c.xht (실시간 테스트) (소스)
- t32-opacity-offscreen-with-alpha-c.xht (실시간 테스트) (소스)
- t32-opacity-zorder-c.xht (실시간 테스트) (소스)
- opacity-computed.html (실시간 테스트) (소스)
- opacity-valid.html (실시간 테스트) (소스)
- opacity-invalid.html (실시간 테스트) (소스)
- composited-filters-under-opacity.html (실시간 테스트) (소스)
- filters-under-will-change-opacity.html (실시간 테스트) (소스)
- color-composition.html (실시간 테스트) (소스)
- opacity-interpolation.html (실시간 테스트) (소스)
- canvas-change-opacity.html (실시간 테스트) (소스)
- opacity-animation-ending-correctly-001.html (실시간 테스트) (소스)
- opacity-animation-ending-correctly-002.html (실시간 테스트) (소스)
- <opacity-value>
-
요소에 적용될 투명도입니다.
결과 투명도는 특정 색상이 아니라
전체 요소에 적용됩니다.
[0,1] 범위를 벗어나는 opacity 값도 잘못된 것은 아니며, 지정된 값으로는 보존되지만 계산 값에서는 [0, 1] 범위로 클램핑됩니다.
CSS에서 opacity는 <opacity-value> 문법으로 표시되며, 예를 들어 opacity 속성에서 사용됩니다.
<opacity-value> = <number> | <percentage>
<number>로 표현될 때, 값의 유효 범위는 0(완전 투명)을 나타내며 1(완전 불투명)을 나타냅니다. 또한 <percentage>로도 작성할 수 있으며, 이는 동일한 <number>로 계산됩니다(0%는 0, 100%는 1).
opacity 속성은 지정된 투명도를 요소 전체에 적용하며, 내용도 포함하고, 각 자손 요소에 개별적으로 적용하는 것이 아닙니다. 예를 들어, 불투명한 자식이 요소의 배경 일부를 가리는 경우 opacity가 1보다 작아도 계속 가리지만, 요소와 자식 전체는 아래 페이지를 투명하게 보여줍니다.
또한 요소의 모든 문자에 대응하는 글리프도 전체로 처리되며, 겹치는 부분이 있어도 투명도가 더 높아지지 않습니다.
각 글리프마다 개별 투명도가 필요하다면, opacity 속성 대신 알파값이 포함된 색상 값을 사용하면 됩니다.
박스의 opacity가 1보다 작으면 자식 요소에 대해 스태킹 컨텍스트가 생성됩니다. (이는 자식 내용이 z축에서 박스 외부 내용과 섞이지 않도록 방지합니다.)
또한 z-index 속성이 박스에 적용될 경우 auto 값은 해당 요소에서 0으로 처리되고, 그렇지 않으면 부모 스태킹 컨텍스트 내에서 스택 레벨 0인 포지셔닝된 요소와 동일한 레이어에 그려집니다 (즉, z-index:0인 포지셔닝된 요소처럼).
스태킹 컨텍스트에 대한 자세한 내용은 9.9절과 부록 E, [CSS2] 를 참고하세요.
SVG 요소에는 이러한 z-순서 규칙이 적용되지 않습니다. SVG는 자체 렌더링 모델([SVG11], 3장)을 따르기 때문입니다.
3.4. 태그된 이미지의 색 공간
태그된 이미지란 이미지 포맷에 따라 명시적으로 색상 프로파일이 지정된 이미지를 말합니다. 이는 보통 International Color Consortium (ICC) 프로파일 [ICC]을 포함하여 이루어집니다.
예를 들어 JPEG [JPEG], PNG [PNG], TIFF [TIFF] 모두 ICC 프로파일을 내장하는 방법을 명시합니다.
이미지 포맷은 간결함을 위해 다른 동등한 방식도 사용할 수 있습니다.
예를 들어, PNG는 sRGB 청크를 통해, sRGB 색 공간에 있음을 명시적으로 태그할 수 있으며, sRGB ICC 프로파일을 포함하지 않아도 됩니다.
마찬가지로, PNG는 cICP 청크를 통해 Display P3, BT.2100 HLG 등 다양한 SDR 또는 HDR 색 공간에 속함을 명시적으로 태그하는 간결한 방법을 제공합니다. 이때 ICC 프로파일을 포함하지 않아도 됩니다.
태그된 RGB 이미지와, RGB 변환 방식(예: YCbCr)을 사용하는 태그된 이미지의 경우 색상 프로파일 또는 기타 식별 정보가 유효하다면, 지정된 색 공간에 있는 것으로 간주해야 합니다.
테스트
예를 들어, Display P3 모니터가 있는 시스템에서 실행되는 브라우저가 ITU Rec BT.2020 [Rec.2020] 색 공간으로 태그된 JPEG 이미지를 표시할 때, 색상을 ITU Rec BT.2020에서 Display P3로 변환하여 올바르게 표시해야 합니다. ITU Rec BT.2020 값을 Display P3 값으로 간주해서는 안 되며, 그렇게 하면 잘못된 색상이 출력됩니다.
색상 프로파일이나 기타 식별 정보가 잘못된 경우, 이미지는 태그되지 않은 이미지에 대해 설명된 대로 처리됩니다.
3.5. 태그되지 않은 색상의 색 공간
호환성을 위해 HTML에서 지정한 색상과 태그되지 않은 이미지는 별도로 지정하지 않는 한 sRGB 색 공간([SRGB])에 있는 것으로 간주해야 합니다.
태그되지 않은 이미지란 이미지 포맷에 따라 명시적으로 색상 프로파일이 지정되지 않은 이미지를 말합니다.
이 규칙은 태그되지 않은 비디오에는 적용되지 않습니다. 태그되지 않은 비디오는 ITU가 정의한 색 공간에 있는 것으로 추정해야 합니다.
-
720p 미만에서는 Recommendation ITU-R BT.601 [ITU-R-BT.601]
-
720p에서는 SMPTE ST 296(709와 동일한 색도) [SMPTE296]
-
1080p에서는 Recommendation ITU-R BT.709 [ITU-R-BT.709]
-
4k(UHDTV) 이상에서는 SDR 비디오에 대해 ITU-R BT.2020 [Rec.2020]을 사용합니다.
4. 색상 표현: <color> 타입
테스트
이 절에서는 타입을 설명하며, 해당 타입이 사용되는 부분에서 주로 테스트됩니다.
CSS에서 색상은 색상 공간의 축을 나타내는 색상 컴포넌트(채널) 목록으로 표현됩니다. 각 컴포넌트는 최소값과 최대값을 가지며, 그 사이의 어떤 값도 가질 수 있습니다. 또한 모든 색상에는 얼마나 투명한지, 즉 배경이 얼마나 비치는지를 나타내는 알파 컴포넌트가 동반됩니다.
CSS에서는 색상 값을 지정하기 위한 여러 가지 문법이 있습니다:
-
RGB 및 알파 컴포넌트를 16진수로 표현하는 sRGB 16진수 색상 표기법
-
다양한 색상 공간과 좌표계를 사용할 수 있는 색상 함수
-
상수 이름이 지정된 색상 키워드
-
변수 <system-color> 키워드와 currentColor 키워드.
색상 함수는 CSS 함수형 표기법을 사용하여 다양한 색상 공간에서 색상을 컴포넌트 좌표로 표현합니다. 일부는 실린더 극 좌표 색상 모델을 사용하며, 색상을 <hue> 각도, 중심축(밝기, 즉 검정~흰색), 반지름(채도 또는 크로마, 중성 회색에서의 거리)으로 지정합니다. 나머지는 직교 좌표 색상 모델을 사용하며, 색상을 세 개의 직교 축으로 지정합니다.
Level 4에서 제공되는 색상 함수는 다음과 같습니다.
-
rgb() 및 rgba() 별칭, (16진수 색상 표기법과 같이) 적, 녹, 청, 알파 컴포넌트로 sRGB 색상을 직접 지정합니다.
-
hsl() 및 hsla() 별칭, HSL 실린더 좌표 모델을 사용하여 색상, 채도, 명도(Hue, Saturation, Lightness)로 sRGB 색상을 지정합니다.
-
lab(), CIE LAB 직교 좌표 모델을 사용해 CIE 밝기와 a축, b축(적/녹, 황/청)으로 CIELAB 색상을 지정합니다.
-
lch() , CIE LCH 실린더 좌표 모델을 사용해 CIE 밝기, 크로마, 색상으로 CIELAB 색상을 지정합니다.
-
oklab(), Oklab 직교 좌표 모델을 사용해 Oklab 밝기와 a축, b축(적/녹, 황/청)으로 Oklab 색상을 지정합니다.
-
oklch() , OKLCh 실린더 좌표 모델을 사용해 Oklab 밝기, 크로마, 색상으로 Oklab 색상을 지정합니다.
-
color(), 다양한 색상 공간에서 색상을 지정할 수 있습니다. 예: sRGB, 선형 sRGB, Display P3, A98 RGB, ProPhoto RGB, ITU-R BT.2020-2, CIE XYZ 등.
다른 명세에서 참고하기 쉽도록 불투명 검정은 rgb(0 0 0 / 100%)으로 정의합니다. 투명 검정은 같은 색상이지만 완전 투명—즉 rgb(0 0 0 / 0%)입니다.
테스트
4.1. <color> 문법
테스트
이 절은 이후에 사용되는 정의를 제공하므로 테스트가 필요하지 않습니다.
CSS의 색상은 <color> 타입으로 표현됩니다:
<color> = <color-base> | currentColor | <system-color> <color-base> = <hex-color> | <color-function> | <named-color> | transparent <color-function> = <rgb () > | <rgba () > | <hsl () > | <hsla () > | <hwb () > | <lab () > | <lch () > | <oklab () > | <oklch () > | <color () >
절대 색상은 <color> 중 계산된 값이 절대 색도 해석을 가지는 경우를 의미합니다. 즉, 값이 다음에 해당하지 않습니다:
-
currentColor (이는 color 속성 값에 따라 달라짐)
-
<system-color> (이는 색상 모드에 따라 달라짐)
sRGB로 해석되는 색상은 다음과 같습니다:
레거시 색상 문법을 지원하는 함수는 다음과 같습니다:
<hsl()>, <hsla()>, <hwb()>, <lch()>, <oklch()> 색상 함수는 실린더 극 좌표 색상 표현방식이며 <hue> 각도를 사용합니다; 그 외의 색상 함수는 직교 좌표 색상 표현방식을 사용합니다.
4.1.1. 모던(공백 구분) 색상 함수 문법
이 명세에서 처음 정의된 모든 절대 색상 함수형 형식은 모던 색상 문법을 사용합니다. 즉:
-
색상 컴포넌트는 공백으로 구분됨
-
선택적 알파 항목은 슬래시("/")로 구분됨
-
직렬화 시 최소 요구 정밀도가 정의되며, 컴포넌트당 8비트보다 높을 수 있음
-
<percentage>와 <number>를 자유롭게 혼합해서 사용할 수 있음
4.1.2. 레거시(쉼표 구분) 색상 함수 문법
웹 호환성을 위해, rgb(), rgba(), hsl(), hsla()의 문법(이전 명세에서 정의된)은 레거시 색상 문법도 지원하며, 차이점은 다음과 같습니다:
-
색상 컴포넌트가 쉼표로 구분됨(공백이 앞뒤에 올 수 있음)
-
불투명하지 않은 경우 별도 표기법 사용 (예: hsla()는 hsl() 대신 사용) 알파 항목도 쉼표로 구분됨(앞뒤에 공백이 올 수 있음)
-
최소 요구 정밀도가 더 낮으며, 컴포넌트당 8비트
-
none 값은 허용되지 않음
-
색상 컴포넌트는 모두 <percentage> 또는 모두 <number>로 지정해야 하며, 혼합할 수 없음.
이 명세 및 이후 레벨에서 도입된 색상 함수에는 웹 호환성 문제가 없는 경우 레거시 색상 문법은 유효하지 않습니다.
4.2. 색상에서 투명도 표현: <alpha-value> 문법
테스트
이 절은 이후에 사용되는 정의를 제공하므로 테스트가 필요하지 않습니다.
<alpha-value> = <number> | <percentage>
별도로 지정하지 않는 한, 색상의 <alpha-value> 컴포넌트는 생략 시 100%로 기본 설정됩니다. [0,1] 범위를 벗어난 값도 잘못된 것은 아니지만, 파싱된 값 단계에서 해당 범위로 클램핑됩니다.
4.3. 실린더 좌표 색상각 표현: <hue> 문법
테스트
이 절은 이후에 사용되는 정의를 제공하므로 테스트가 필요하지 않습니다.
색상각(hue)은 색상 원의 각도로 표현됩니다 (무지개를 원으로 휘어놓고, 보라색을 보라~빨강 사이에 추가한 것).
<hue> = <number> | <angle>
이 값은 매우 자주 도 단위(degree)로 주어지므로, 인자(argument)를 숫자로도 지정할 수 있는데, 이 경우 숫자는 도(degree) 단위로 해석되며 정규 단위입니다.
이 숫자는 [0,360) 범위로 정규화(normalize)됩니다.
hsl(360 0 0)에서는 <hue> 컴포넌트가 0도(degree)로 정규화됩니다.
hsl(calc(-infinity) 0 0) 또는 hsl(calc(infinity) 0 0)의 경우, <hue> 컴포넌트 역시 0도(degree)로 정규화됩니다.
참고: 특정 색상에 대응하는 각도와 간격은 색상 공간에 따라 달라집니다. 예를 들어, sRGB 색상 공간을 사용하는 HSL 및 HWB에서는 sRGB 녹색이 120도입니다. LCH에서는 sRGB 녹색이 134.39도, display-p3 녹색은 136.01도, a98-rgb 녹색은 145.97도, prophoto-rgb 녹색은 141.04도입니다 (각 색상 공간마다 녹색의 색조가 다르기 때문입니다).
<hue> 컴포넌트는 무효(powerless)가 되는 경우가 가장 많습니다; 색상이 중심 무채색 축에 충분히 가까우면 무효인 hue 컴포넌트가 됩니다.
4.4. “누락된” 색상 컴포넌트와 none 키워드
특정 경우에는, 색상이 하나 이상의 누락된 색상 컴포넌트를 가질 수 있습니다.
이 명세에서는 일부 색상(hue 기반 보간으로 인한 white 등)에서 자동으로 발생합니다; 다른 명세에서는 추가적인 상황에서 컴포넌트가 자동으로 누락될 수 있음을 정의할 수 있습니다.
명시적으로 지정할 수도 있는데, 색상 함수의 컴포넌트에 none 키워드를 지정하면 됩니다. 모든 색상 함수는 (레거시 색상 문법을 사용하는 함수를 제외하고) 어떤 컴포넌트라도 none으로 지정할 수 있습니다.
이 기능은 신중하게 사용해야 하며, 원하는 효과가 있을 때만 사용하는 것이 좋습니다.
테스트
- color-computed-color-function.html (실시간 테스트) (소스)
- color-computed-hsl.html (실시간 테스트) (소스)
- color-computed-hwb.html (실시간 테스트) (소스)
- color-computed-lab.html (실시간 테스트) (소스)
- color-computed-relative-color.html (실시간 테스트) (소스)
- color-computed-rgb.html (실시간 테스트) (소스)
- color-invalid-hsl.html (실시간 테스트) (소스)
- color-invalid-rgb.html (실시간 테스트) (소스)
- color-valid-color-function.html (실시간 테스트) (소스)
- color-valid-color-mix-function.html (실시간 테스트) (소스)
- color-valid-hsl.html (실시간 테스트) (소스)
- color-valid-hwb.html (실시간 테스트) (소스)
- color-valid-lab.html (실시간 테스트) (소스)
- color-valid-relative-color.html (실시간 테스트) (소스)
- color-valid-rgb.html (실시간 테스트) (소스)
누락된 컴포넌트가 두 색상을 합치는 상황(예: 색상 보간)에서 어떻게 처리되는지는 § 12.2 누락된 컴포넌트와의 보간를 참고하세요.
그 외의 모든 경우에는 누락된 컴포넌트는 해당 컴포넌트의 단위에 맞는 0값으로 동작합니다: 0, 0%, 0deg. 이는 색상을 직접 렌더링하거나, 다른 색상 공간으로 변환하거나, 색상 컴포넌트 값을 연산할 때 등 모두 포함됩니다.
누락된 컴포넌트가 있는 색상을 직렬화하거나 저자(author)에게 직접 보여줄 경우, 레거시 색상 문법에서는 해당 컴포넌트를 0값으로 표현하고, 그렇지 않은 경우에는 none 키워드로 표현합니다.
결과는 초록과 흰색이 실제로 섞인 것처럼 보이게 되며, 만약 white의 hue가 0deg로 기본 처리된다면 붉게 보일 수도 있습니다.
예를 들어 어떤 색이든 "그레이스케일"로 애니메이션하려면, oklch(none 0 none)과 보간하면 됩니다. 이렇게 하면 시작 색상의 hue와 밝기는 그대로 두고, chroma만 0으로 애니메이션되어 일정 밝기의 회색으로, 애니메이션 내내 hue가 일정하게 유지됩니다.
이걸 수동으로 하려면 시작 색상의 hue와 밝기를 일일이 맞춰야 합니다.
4.4.1. “무효” 색상 컴포넌트
개별 색상 문법에서는, 특정 상황에서 해당 문법의 컴포넌트가 무효 색상 컴포넌트가 될 수 있다고 규정할 수 있습니다. 이는 해당 컴포넌트의 값이 렌더링된 색상에 영향을 주지 않음을 의미합니다; 어떤 값을 주더라도 화면에 표시되는 색상은 동일합니다.
예를 들어, hsl()에서, 채도(saturation) 컴포넌트가 0%일 때 hue 컴포넌트는 무효가 됩니다; 0% 채도는 회색조를 의미하며, hue가 전혀 없는 색상이므로, 0deg든 180deg든, 또는 어떤 각도든 결과는 완전히 동일합니다.
무효 컴포넌트를 수동으로 지정하면, 평소처럼 동작하며; 무효라는 사실이 동작에 영향을 주지 않습니다.
하지만 색상 공간 변환으로 색상이 자동 생성되는 경우, 변환 결과의 무효 컴포넌트는 변환 과정에서 나온 값 대신 누락됨으로 설정해야 합니다.
색상 공간 변환을 실린더 극 좌표 색상 공간으로 할 때, 사용자 에이전트는 chroma(또는 hsl에서의 채도 등 색상도 측정치)가 해당 색상 공간에서 규정된 epsilon(ε)보다 작으면 hue 컴포넌트를 무효로 처리해야 합니다. 예를 들어, 회색을 oklch()로 변환하면 수치 오차로 인해 chroma가 정확히 0%가 아니라 매우 작게 나올 수 있는데, 이 경우 hue 컴포넌트는 무효가 됩니다.
4.5. <color> 값 파싱하기
테스트
이 절은 다른 곳에서 참조되는 정의를 제공하므로 테스트가 필요하지 않습니다.
참고: 이 알고리즘은 CSS <color> 값을 CSS 스타일시트나 CSSOM 인터페이스에서 파싱하기 위한 것이 아니라, HTML 속성이나 Canvas 인터페이스 등 다른 곳에서 사용하기 위한 것입니다.
5. sRGB 색상
CSS에서 sRGB 색상 공간의 색상은 빨강, 초록, 파랑 값의 삼중값(triplet)으로 표현되며, sRGB 색상 공간의 한 점을 식별합니다 [SRGB]. 이 색상 공간은 국제적으로 인정받는 장치 독립적 색상 공간으로, 컴퓨터 화면에 표시될 색상을 지정할 때 유용하며, 프린터와 같은 다른 종류의 장치에 색상을 지정할 때도 유용합니다.
CSS는 또한 sRGB가 아닌 색상 공간도 사용할 수 있도록 허용합니다. 자세한 내용은 § 10 미리 정의된 색상 공간을 참고하세요.
CSS에서는 sRGB 색상을 직접 지정하는 여러 방법을 제공합니다: 16진수 색상, rgb()/rgba() 색상 함수, hsl()/hsla() 색상 함수, hwb() 색상 함수, 이름이 지정된 색상, 그리고 transparent 키워드입니다.
5.1. RGB 함수: rgb() 및 rgba()
rgb() 및 rgba() 함수는 r, g, b(빨강, 초록, 파랑) 컴포넌트를 직접 지정하여 sRGB 색상을 정의합니다. 문법은 다음과 같습니다:
rgb () =[ <legacy-rgb-syntax> | <modern-rgb-syntax>] rgba () =[ <legacy-rgba-syntax> | <modern-rgba-syntax>] <legacy-rgb-syntax> =rgb ( <percentage>#{ 3 } , <alpha-value>?) |rgb ( <number>#{ 3 } , <alpha-value>?) <legacy-rgba-syntax> =rgba ( <percentage>#{ 3 } , <alpha-value>?) |rgba ( <number>#{ 3 } , <alpha-value>?) <modern-rgb-syntax> =rgb ( [ <number> | <percentage> | none] { 3 } [ /[ <alpha-value> | none] ] ?) <modern-rgba-syntax> =rgba ( [ <number> | <percentage> | none] { 3 } [ /[ <alpha-value> | none] ] ?)
백분율 | r, g, b 값에 허용됨 |
---|---|
백분율 기준 범위 | r, g, b: 0% = 0.0, 100% = 255.0 alpha: 0% = 0.0, 100% = 1.0 |
테스트
- rgb-001.html (실시간 테스트) (소스)
- rgb-002.html (실시간 테스트) (소스)
- rgb-003.html (실시간 테스트) (소스)
- rgb-004.html (실시간 테스트) (소스)
- rgb-005.html (실시간 테스트) (소스)
- rgb-006.html (실시간 테스트) (소스)
- rgb-007.html (실시간 테스트) (소스)
- rgb-008.html (실시간 테스트) (소스)
- out-of-gamut-legacy-rgb.html (실시간 테스트) (소스)
- color-valid.html (실시간 테스트) (소스)
- color-computed-rgb.html (실시간 테스트) (소스)
- color-invalid-rgb.html (실시간 테스트) (소스)
- color-valid-rgb.html (실시간 테스트) (소스)
처음 세 인자는 각각 r, g, b(빨강, 초록, 파랑) 색상 컴포넌트를 지정합니다. 0%는 해당 sRGB 색상 컴포넌트의 최소값을, 100%는 최대값을 나타냅니다.
색상 컴포넌트의 백분율 기준 범위는 많은 그래픽 엔진이 색상 컴포넌트를 내부적으로 한 바이트(0~255 정수)로 저장했던 역사적 사실에서 유래했습니다. 구현체는 저자가 작성하거나 계산한 컴포넌트의 정밀도를 최대한 존중해야 합니다. 만약 불가능하다면, 컴포넌트는 +∞ 방향으로 반올림되어야 합니다.
마지막 인자인 <alpha-value>는 색상의 알파값을 지정합니다. 생략 시 기본값은 100%입니다.
테스트
이 범위를 벗어난 값도 잘못된 것은 아니지만, 파싱 시점에 여기 정의된 범위로 클램핑됩니다.
역사적 이유로 rgb() 및 rgba()는 레거시 색상 문법도 지원합니다.
테스트
5.2. RGB 16진수 표기법: #RRGGBB
CSS 16진수 색상 표기법은 sRGB 색상을 각 컴포넌트를 16진수 숫자로 지정할 수 있게 해줍니다. 이는 색상을 컴퓨터 코드에서 직접 쓸 때 자주 사용하는 방식과 유사합니다. rgb() 표기법보다 더 짧게 쓸 수 있습니다.
<hex-color>의 문법은 3, 4, 6, 8자리 16진수로 이루어진 <hash-token> 토큰입니다. 즉, 16진수 색상은 해시 문자 "#" 뒤에 0~9 또는 a~f(대소문자 구분 없음, #00ff00과 #00FF00은 동일)를 나열해 작성합니다.
16진수 자릿수에 따라 RGB 색상으로 해석하는 방법이 달라집니다:
- 6자리
- 첫 두 자리는 16진수로 해석해 빨강 컴포넌트를 지정합니다. 00은 최소값, ff(10진수 255)는 최대값입니다. 다음 두 자리는 초록, 마지막 두 자리는 파랑 컴포넌트를 지정하며, 알파값은 완전히 불투명입니다.
- 8자리
- 첫 6자리는 6자리 표기법과 동일하게 해석합니다. 마지막 두 자리는 16진수로 해석해 알파값을 지정하며, 00은 완전 투명, ff는 완전 불투명입니다.
- 3자리
- 6자리 표기법을 짧게 만든 방식입니다. 첫 자리는 빨강 컴포넌트, 0은 최소, f는 최대값입니다. 다음 두 자리는 초록, 파랑을 같은 방식으로 지정하며, 알파값은 완전히 불투명입니다.
- 4자리
- 8자리 표기법을 짧게 만든 것으로, 3자리 표기법과 마찬가지로 "확장"됩니다. 첫 자리는 빨강 컴포넌트, 0은 최소, f는 최대값, 다음 세 자리는 초록, 파랑, 알파 컴포넌트를 각각 지정합니다.
테스트
- hex-001.html (실시간 테스트) (소스)
- hex-002.html (실시간 테스트) (소스)
- hex-003.html (실시간 테스트) (소스)
- hex-004.html (실시간 테스트) (소스)
- border-bottom-color.xht (실시간 테스트) (소스)
- border-left-color.xht (실시간 테스트) (소스)
- border-right-color.xht (실시간 테스트) (소스)
- border-top-color.xht (실시간 테스트) (소스)
- color-valid.html (실시간 테스트) (소스)
- color-computed-hex-color.html (실시간 테스트) (소스)
- color-invalid-hex-color.html (실시간 테스트) (소스)
6. 색상 키워드
다양한 숫자 문법 <color> 외에도, CSS는 여러 색상 키워드 집합을 정의하며, 상황에 따라 쓰일 수 있습니다—각각 장점과 용도가 있습니다.
6.1. 이름이 지정된 색상
CSS는 이름이 지정된 색상을 다수 정의하여, 자주 쓰이는 색상을 더 쉽게 작성하고 읽을 수 있도록 합니다. <named-color>는 <ident>로 작성되며, <color>가 허용되는 모든 곳에서 사용할 수 있습니다. CSS에서 정의한 <ident>처럼, 모든 키워드는 ASCII 대소문자 구분 없이 인식됩니다.
이 이름들은 sRGB 색상으로 해석됩니다.
CSS의 이름이 지정된 색상 중 16개는 원래 VGA 팔레트에서 비롯되었고, HTML에도 채택되었습니다: aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, white, yellow. 나머지 대부분은 Unix 계열 시스템에서 콘솔 색상을 지정할 때 사용된 X11 색상 시스템의 한 버전에서 유래했고, 이후 SVG로 채택되었습니다.
참고: 이들 색상 이름이 여기에서 표준화된 것은 좋아서가 아니라, 수십 년간 널리 쓰이고 구현되어왔기 때문이며, 표준은 현실을 반영해야 합니다. 실제로 각 이름이 어떤 색상일지 상상하기 어려운 경우가 많으므로(아래 목록 참고), sRGB 색상 볼륨 전체에 이름이 고르게 분포되어 있지 않고, 이름 간에도 일관성이 없습니다 ( darkgray는 gray보다 더 밝고, lightpink는 pink보다 더 어둡습니다), 그리고 일부 이름( indianred 등)은 논란이 있는 경우도 있습니다. 따라서 사용을 권장하지 않습니다.
(transparent, currentcolor는 별도 섹션에서 정의되어 있습니다.)
아래 표는 모든 불투명 이름 색상을, 다른 색상 표기법으로 동등하게 지정한 값을 제시합니다.
이름 | 숫자 표기 | 색상 이름 | 16진수 rgb | 10진수 |
---|---|---|---|---|
aliceblue | #f0f8ff | 240 248 255 | ||
antiquewhite | #faebd7 | 250 235 215 | ||
aqua | #00ffff | 0 255 255 | ||
aquamarine | #7fffd4 | 127 255 212 | ||
azure | #f0ffff | 240 255 255 | ||
beige | #f5f5dc | 245 245 220 | ||
bisque | #ffe4c4 | 255 228 196 | ||
black | #000000 | 0 0 0 | ||
blanchedalmond | #ffebcd | 255 235 205 | ||
blue | #0000ff | 0 0 255 | ||
blueviolet | #8a2be2 | 138 43 226 | ||
brown | #a52a2a | 165 42 42 | ||
burlywood | #deb887 | 222 184 135 | ||
cadetblue | #5f9ea0 | 95 158 160 | ||
chartreuse | #7fff00 | 127 255 0 | ||
chocolate | #d2691e | 210 105 30 | ||
coral | #ff7f50 | 255 127 80 | ||
cornflowerblue | #6495ed | 100 149 237 | ||
cornsilk | #fff8dc | 255 248 220 | ||
crimson | #dc143c | 220 20 60 | ||
cyan | #00ffff | 0 255 255 | ||
darkblue | #00008b | 0 0 139 | ||
darkcyan | #008b8b | 0 139 139 | ||
darkgoldenrod | #b8860b | 184 134 11 | ||
darkgray | #a9a9a9 | 169 169 169 | ||
darkgreen | #006400 | 0 100 0 | ||
darkgrey | #a9a9a9 | 169 169 169 | ||
darkkhaki | #bdb76b | 189 183 107 | ||
darkmagenta | #8b008b | 139 0 139 | ||
darkolivegreen | #556b2f | 85 107 47 | ||
darkorange | #ff8c00 | 255 140 0 | ||
darkorchid | #9932cc | 153 50 204 | ||
darkred | #8b0000 | 139 0 0 | ||
darksalmon | #e9967a | 233 150 122 | ||
darkseagreen | #8fbc8f | 143 188 143 | ||
darkslateblue | #483d8b | 72 61 139 | ||
darkslategray | #2f4f4f | 47 79 79 | ||
darkslategrey | #2f4f4f | 47 79 79 | ||
darkturquoise | #00ced1 | 0 206 209 | ||
darkviolet | #9400d3 | 148 0 211 | ||
deeppink | #ff1493 | 255 20 147 | ||
deepskyblue | #00bfff | 0 191 255 | ||
dimgray | #696969 | 105 105 105 | ||
dimgrey | #696969 | 105 105 105 | ||
dodgerblue | #1e90ff | 30 144 255 | ||
firebrick | #b22222 | 178 34 34 | ||
floralwhite | #fffaf0 | 255 250 240 | ||
forestgreen | #228b22 | 34 139 34 | ||
fuchsia | #ff00ff | 255 0 255 | ||
gainsboro | #dcdcdc | 220 220 220 | ||
ghostwhite | #f8f8ff | 248 248 255 | ||
gold | #ffd700 | 255 215 0 | ||
goldenrod | #daa520 | 218 165 32 | ||
gray | #808080 | 128 128 128 | ||
green | #008000 | 0 128 0 | ||
greenyellow | #adff2f | 173 255 47 | ||
grey | #808080 | 128 128 128 | ||
honeydew | #f0fff0 | 240 255 240 | ||
hotpink | #ff69b4 | 255 105 180 | ||
indianred | #cd5c5c | 205 92 92 | ||
indigo | #4b0082 | 75 0 130 | ||
ivory | #fffff0 | 255 255 240 | ||
khaki | #f0e68c | 240 230 140 | ||
lavender | #e6e6fa | 230 230 250 | ||
lavenderblush | #fff0f5 | 255 240 245 | ||
lawngreen | #7cfc00 | 124 252 0 | ||
lemonchiffon | #fffacd | 255 250 205 | ||
lightblue | #add8e6 | 173 216 230 | ||
lightcoral | #f08080 | 240 128 128 | ||
lightcyan | #e0ffff | 224 255 255 | ||
lightgoldenrodyellow | #fafad2 | 250 250 210 | ||
lightgray | #d3d3d3 | 211 211 211 | ||
lightgreen | #90ee90 | 144 238 144 | ||
lightgrey | #d3d3d3 | 211 211 211 | ||
lightpink | #ffb6c1 | 255 182 193 | ||
lightsalmon | #ffa07a | 255 160 122 | ||
lightseagreen | #20b2aa | 32 178 170 | ||
lightskyblue | #87cefa | 135 206 250 | ||
lightslategray | #778899 | 119 136 153 | ||
lightslategrey | #778899 | 119 136 153 | ||
lightsteelblue | #b0c4de | 176 196 222 | ||
lightyellow | #ffffe0 | 255 255 224 | ||
lime | #00ff00 | 0 255 0 | ||
limegreen | #32cd32 | 50 205 50 | ||
linen | #faf0e6 | 250 240 230 | ||
magenta | #ff00ff | 255 0 255 | ||
maroon | #800000 | 128 0 0 | ||
mediumaquamarine | #66cdaa | 102 205 170 | ||
mediumblue | #0000cd | 0 0 205 | ||
mediumorchid | #ba55d3 | 186 85 211 | ||
mediumpurple | #9370db | 147 112 219 | ||
mediumseagreen | #3cb371 | 60 179 113 | ||
mediumslateblue | #7b68ee | 123 104 238 | ||
mediumspringgreen | #00fa9a | 0 250 154 | ||
mediumturquoise | #48d1cc | 72 209 204 | ||
mediumvioletred | #c71585 | 199 21 133 | ||
midnightblue | #191970 | 25 25 112 | ||
mintcream | #f5fffa | 245 255 250 | ||
mistyrose | #ffe4e1 | 255 228 225 | ||
moccasin | #ffe4b5 | 255 228 181 | ||
navajowhite | #ffdead | 255 222 173 | ||
navy | #000080 | 0 0 128 | ||
oldlace | #fdf5e6 | 253 245 230 | ||
olive | #808000 | 128 128 0 | ||
olivedrab | #6b8e23 | 107 142 35 | ||
orange | #ffa500 | 255 165 0 | ||
orangered | #ff4500 | 255 69 0 | ||
orchid | #da70d6 | 218 112 214 | ||
palegoldenrod | #eee8aa | 238 232 170 | ||
palegreen | #98fb98 | 152 251 152 | ||
paleturquoise | #afeeee | 175 238 238 | ||
palevioletred | #db7093 | 219 112 147 | ||
papayawhip | #ffefd5 | 255 239 213 | ||
peachpuff | #ffdab9 | 255 218 185 | ||
peru | #cd853f | 205 133 63 | ||
pink | #ffc0cb | 255 192 203 | ||
plum | #dda0dd | 221 160 221 | ||
powderblue | #b0e0e6 | 176 224 230 | ||
purple | #800080 | 128 0 128 | ||
rebeccapurple | #663399 | 102 51 153 | ||
red | #ff0000 | 255 0 0 | ||
rosybrown | #bc8f8f | 188 143 143 | ||
royalblue | #4169e1 | 65 105 225 | ||
saddlebrown | #8b4513 | 139 69 19 | ||
salmon | #fa8072 | 250 128 114 | ||
sandybrown | #f4a460 | 244 164 96 | ||
seagreen | #2e8b57 | 46 139 87 | ||
seashell | #fff5ee | 255 245 238 | ||
sienna | #a0522d | 160 82 45 | ||
silver | #c0c0c0 | 192 192 192 | ||
skyblue | #87ceeb | 135 206 235 | ||
slateblue | #6a5acd | 106 90 205 | ||
slategray | #708090 | 112 128 144 | ||
slategrey | #708090 | 112 128 144 | ||
snow | #fffafa | 255 250 250 | ||
springgreen | #00ff7f | 0 255 127 | ||
steelblue | #4682b4 | 70 130 180 | ||
tan | #d2b48c | 210 180 140 | ||
teal | #008080 | 0 128 128 | ||
thistle | #d8bfd8 | 216 191 216 | ||
tomato | #ff6347 | 255 99 71 | ||
turquoise | #40e0d0 | 64 224 208 | ||
violet | #ee82ee | 238 130 238 | ||
wheat | #f5deb3 | 245 222 179 | ||
white | #ffffff | 255 255 255 | ||
whitesmoke | #f5f5f5 | 245 245 245 | ||
yellow | #ffff00 | 255 255 0 | ||
yellowgreen | #9acd32 | 154 205 50 |
참고: 이 색상 목록과 정의는 SVG 1.1에 정의된 이름이 지정된 색상 목록의 상위 집합입니다.
역사적 이유로, 이를 X11 색상 집합이라고도 합니다.참고: X11 색상 시스템의 역사는 흥미롭고, Alex Sexton의 “Peachpuffs and Lemonchiffons” 강연에서 훌륭하게 요약되었습니다.
테스트
6.2. 시스템 색상
일반적으로 <system-color> 키워드는 사용자, 브라우저, 또는 운영체제가 기본적으로 선택한 색상 옵션을 반영합니다. 이러한 이유로, 브라우저 기본 스타일시트에서 주로 사용됩니다.
가독성을 유지하기 위해, <system-color> 키워드는 라이트 모드 또는 다크 모드 변경에도 반응합니다.
읽기 쉬운 링크 텍스트
읽기 어려운 링크 텍스트
읽기 쉬운 링크 텍스트
하지만 강제 색상 모드에서는 페이지의 대부분 색상이 제한된, 사용자가 선택한 팔레트로 강제됩니다. <system-color> 키워드는 이러한 사용자 선택 색상을 노출하여 페이지 나머지가 제한된 팔레트와 통합될 수 있게 해줍니다.
forced-colors 미디어 특성이 활성일 때, 저자는 <system-color> 키워드를 색상 값으로 CSS Color Adjustment 1 § 3.1 강제 색상 모드에 영향을 받는 속성에 명시된 속성 외의 속성에서 사용해야 하며, 페이지 전체의 가독성과 일관성을 보장하고 사용자가 강제한 색상과 페이지에서 선택한 색상이 뒤섞이는 상황을 피해야 합니다.
테스트
<system-color> 키워드의 값이 브라우저에서 제공되는 경우 (OS 기본값이나 사용자 선택이 아닌 경우) 브라우저는 일치하는 전경/배경 쌍이 최소한 WCAG AA 명도비를 가지도록 해야 합니다. 다만, 사용자의 명도비 선호(더 높거나 더 낮은 명도비)는 브라우저 환경설정, 사용자 스타일시트, 운영체제 기본값 변경 등으로 설정된 경우 항상 이 요구사항보다 우선합니다.
저자는 언제든지 이러한 키워드를 사용할 수 있지만, 일치하는 배경-전경 쌍으로 색상을 사용하여 적절한 명도비를 확보하는 것이 바람직하며, 일치하지 않는 쌍(예: Canvas와 ButtonText) 사이의 명도비는 보장되지 않습니다.
<system-color> 키워드는 다음과 같이 정의됩니다:
- AccentColor
- 강조된 사용자 인터페이스 컨트롤의 배경색.
- AccentColorText
- 강조된 사용자 인터페이스 컨트롤의 텍스트 색상.
- ActiveText
- 활성 링크의 텍스트. 밝은 배경에서는 전통적으로 빨강.
- ButtonBorder
- 푸시 버튼의 기본 테두리 색상.
- ButtonFace
- 푸시 버튼의 면 배경색.
- ButtonText
- 푸시 버튼의 텍스트 색상.
- Canvas
- 응용 프로그램 콘텐츠 또는 문서의 배경색.
- CanvasText
- 응용 프로그램 콘텐츠 또는 문서의 텍스트 색상.
- Field
- 입력 필드의 배경색.
- FieldText
- 입력 필드의 텍스트 색상.
- GrayText
- 비활성화된 텍스트. (대부분, 반드시 회색은 아님.)
- Highlight
- 선택된 텍스트의 배경색, 예를 들어 ::selection.
- HighlightText
- 선택된 텍스트의 글자색.
- LinkText
- 활성/방문하지 않은 링크의 텍스트. 밝은 배경에서는 전통적으로 파랑.
- Mark
- 특별히 마킹된 텍스트(예: HTML
mark
요소)의 배경색. - MarkText
- 특별히 마킹된 텍스트(예: HTML
mark
요소)의 글자색. - SelectedItem
- 선택된 항목의 배경색, 예를 들어 선택된 체크박스.
- SelectedItemText
- 선택된 항목의 글자색.
- VisitedText
- 방문한 링크의 텍스트. 밝은 배경에서는 전통적으로 보라색.
테스트
참고: 다른 키워드처럼, 이 이름들은 ASCII 대소문자 구분 없이 인식됩니다. 가독성을 위해 혼합 대소문자로 표기합니다.
특정 시스템 UI 개념이 없는 시스템에서는, 지정된 값은 존재하는 가장 비슷한 시스템 색상 값으로 매핑되어야 합니다. 다음 시스템 색상 쌍은 읽기 쉬운 배경-전경 색상 조합을 형성해야 합니다:
-
Canvas 배경과 CanvasText, LinkText, VisitedText, ActiveText 전경.
-
Canvas 배경과 ButtonBorder 테두리 및 인접 색상 Canvas
-
ButtonFace 배경과 ButtonText 전경.
-
ButtonFace 또는 Field 배경과 ButtonBorder 테두리, 인접 색상 Canvas
-
Highlight 배경과 HighlightText 전경.
-
SelectedItem 배경과 SelectedItemText 전경.
-
AccentColor 배경과 AccentColorText 전경.
또한, GrayText는 어떤 배경에서도 읽을 수 있어야 하지만, 명도비 평가는 낮을 수 있습니다.
Canvas와 CanvasText: CanvasText
Canvas와 LinkText: LinkText
Canvas와 VisitedText: VisitedText
Canvas와 ActiveText: ActiveText
Canvas와 GrayText: GrayText
Canvas와 ButtonBorder 및 인접 Canvas: CanvasTextAdjacent
ButtonFace와 ButtonText: ButtonText
ButtonFace와 ButtonText 및 ButtonBorder: ButtonText
ButtonFace와 GrayText: GrayText
Field와 FieldText: FieldText
Field와 GrayText: GrayText
Mark와 MarkText: MarkText
Mark와 GrayText: GrayText
Highlight와 HighlightText: HighlightText
Highlight와 GrayText: GrayText
SelectedItem과 SelectedItemText: SelectedItemText
AccentColor와 AccentColorText: AccentColorText
AccentColor와 GrayText: GrayText
이전 CSS 버전에서는 추가 <system-color>도 정의했으나, 현재는 폐지되었습니다. 자세한 내용은 부록 A: 폐지된 CSS 시스템 색상을 참고하세요.
참고: <system-color>는 § 21 개인정보 보호 고려사항 및 § 20 보안 고려사항에서 설명한 바와 같이 개인정보 및 보안 위험이 있습니다.
사용자 에이전트는, 지문 채취 등 개인정보·보안 위험을 완화하기 위해, 시스템 색상 사용 값에 대해 사용자의 맞춤화나 테마 선택을 반영하지 않는 고정 값을 반환하도록 선택할 수 있습니다.
6.3. transparent 키워드
transparent 키워드는 투명한 검정을 지정합니다. 이는 <named-color>의 일종입니다.
테스트
6.4. currentcolor 키워드
currentcolor 키워드는 같은 요소의 color 속성 값을 나타냅니다. <named-color>와 달리, sRGB에만 제한되지 않습니다; 값은 어떤 <color>여도 됩니다. 사용된 값은 색상값 해석에 의해 결정됩니다.
테스트
- border-color-currentcolor.html (실시간 테스트) (소스)
- color-mix-currentcolor-nested-for-color-property.html (실시간 테스트) (소스)
- currentcolor-001.html (실시간 테스트) (소스)
- currentcolor-002.html (실시간 테스트) (소스)
- currentcolor-003.html (실시간 테스트) (소스)
- currentcolor-004.html (실시간 테스트) (소스)
- currentcolor-visited-fallback.html (실시간 테스트) (소스)
- color-valid.html (실시간 테스트) (소스)
.foo{ color : 빨강; background-color : currentcolor; }
이는 다음과 동일합니다:
.foo{ color : 빨강; background-color : 빨강; }
< p >< em > Some< strong > really</ strong > emphasized text.</ em > < style > p { color : black ; } em { text-emphasis : dot ; } strong { color : red ; } </ style >
위 예시에서는 강조 마크가 "Some"과 "emphasized text"에는 검정색, "really"에는 빨강입니다.
참고: CSS의 다단어 키워드는 보통 하이픈으로 단어를 구분합니다. currentcolor는 예외인데, 그 이유는 원래 SVG에서 "current-color"라는 속성값으로 도입됐기 때문입니다. 이후 XSLT 생성의 편의를 위해 속성 및 값이 프리젠테이션 속성/값이 되었고, DOM에서 하이픈이 "마이너스"로 해석되는 문제 때문에 모두 camelCase로 바뀌었습니다. 그 후 CSS의 기존 속성과 값들은 다시 하이픈 표기로 돌아갔지만, currentcolor는 당시 CSS에 포함되어 있지 않아 camelCase로 남았습니다. 이후 CSS에서 도입되어 대소문자 구분이 사라지고 CSS 키워드는 ASCII 대소문자 구분 없이 인식됩니다.
7. HSL 색상: hsl() 및 hsla() 함수
색상을 지정하는 RGB 시스템은 기계와 그래픽 라이브러리에는 편리하지만, 사람이 직관적으로 이해하기에는 매우 어렵다고 여겨집니다. 예를 들어, RGB 색상을 어떻게 조정해야 같은 색상의 더 밝은 변형이 나오는지 쉽게 알 수 없습니다.
다른 색상 체계도 여러 가지가 있습니다. 그 중 하나가 HSL [HSL] 색상 체계이며, 더 직관적으로 사용할 수 있지만, 여전히 RGB 색상으로 쉽게 변환됩니다.
HSL 색상은 색상각(hue), 채도(saturation), 명도(lightness) 삼중값으로 지정됩니다. hsl() 및 hsla() 함수의 문법은 다음과 같습니다:
hsl () =[ <legacy-hsl-syntax> | <modern-hsl-syntax>] hsla () =[ <legacy-hsla-syntax> | <modern-hsla-syntax>] <modern-hsl-syntax> =hsl ( [ <hue> | none] [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ /[ <alpha-value> | none] ] ?) <modern-hsla-syntax> =hsla ( [ <hue> | none] [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ /[ <alpha-value> | none] ] ?) <legacy-hsl-syntax> =hsl ( <hue>, <percentage>, <percentage>, <alpha-value>?) <legacy-hsla-syntax> =hsla ( <hue>, <percentage>, <percentage>, <alpha-value>?)
백분율 | S와 L에 허용됨 |
---|---|
백분율 기준 범위 | S와 L: 0% = 0.0, 100% = 100.0 |
무효(hue) ε | S <= 0.001 |
테스트
- hsl-001.html (실시간 테스트) (소스)
- hsl-002.html (실시간 테스트) (소스)
- hsl-003.html (실시간 테스트) (소스)
- hsl-004.html (실시간 테스트) (소스)
- hsl-005.html (실시간 테스트) (소스)
- hsl-006.html (실시간 테스트) (소스)
- hsl-007.html (실시간 테스트) (소스)
- hsl-008.html (실시간 테스트) (소스)
- hsl-clamp-negative-saturation.html (실시간 테스트) (소스)
- background-color-hsl-001.html (실시간 테스트) (소스)
- background-color-hsl-002.html (실시간 테스트) (소스)
- background-color-hsl-003.html (실시간 테스트) (소스)
- background-color-hsl-004.html (실시간 테스트) (소스)
- color-computed-hsl.html (실시간 테스트) (소스)
- color-invalid-hsl.html (실시간 테스트) (소스)
- color-valid-hsl.html (실시간 테스트) (소스)
첫 번째 인자는 색상각(hue)을 지정합니다.
HSL(HWB도 동일)에서 0deg는 sRGB 원색 빨강을 나타내며 (360deg, 720deg 등도 마찬가지), 나머지 hue들은 원을 따라 분포합니다. 120deg는 sRGB 원색 초록, 240deg는 sRGB 원색 파랑 등입니다.
다음 두 인자는 각각 채도(saturation)와 명도(lightness)입니다. 채도의 경우 100% 또는 100이 완전히 채도된 밝은 색이고, 0% 또는 0이 완전히 무채색의 회색입니다. 명도의 경우 50% 또는 50이 "일반적인" 색, 100% 또는 100이 흰색, 0% 또는 0이 검정입니다.
역사적 이유로, 채도가 0% 미만이면 파싱 시점에 0%로 클램핑되어, sRGB 색상 변환 전에 적용됩니다.
마지막 인자는 색상의 알파 컴포넌트입니다. rgb() 함수의 네 번째 인자와 동일하게 해석됩니다. 생략 시 기본값은 100%입니다.
HSL 색상은 sRGB로 해석됩니다.
HSL 색상의 채도가 0% 또는 0이면, hue 컴포넌트는 무효(powerless)가 됩니다.
HSL의 장점은 RGB보다 직관적이라는 점입니다: 사람들이 원하는 색상을 대략적으로 예측하여 쉽게 조정할 수 있습니다.
hsl ( 120 deg 100 % 50 % ) lime greenhsl ( 120 deg 100 % 25 % ) dark greenhsl ( 120 deg 100 % 75 % ) light greenhsl ( 120 deg 75 % 85 % ) pastel green
HSL의 단점은 OKLCh에 비해 hue 조작 시 시각적 명도가 달라지고, hue 간 간격이 고르지 않다는 점입니다.
따라서 HSL에서는 hue를 고정하고 채도와 명도만 바꿔서 색상 세트를 만들기가 sRGB 컴포넌트 값을 직접 조작하는 것보다 쉽지만, 명도(lightness)는 감마 보정된 빨강, 초록, 파랑 컴포넌트의 평균이기 때문에 hue에 따라 시각적으로 느끼는 명도와 일치하지 않습니다.
OKLCh에서는 sRGB 파랑이 oklch(0.452 0.313 264.1)이고, sRGB 노랑은 oklch(0.968 0.211 109.8)입니다. OKLCh의 명도값(0.452와 0.968)이 실제 시각적 밝기를 잘 반영합니다.
HSL의 hue 각도는 시각적으로 균일하지 않습니다; 색상들이 어떤 영역에서는 몰려 있고 다른 영역에서는 넓게 퍼져 보입니다.
OKLCh에서는 oklch(0.533 0.26 262.6)와 oklch(0.462 0.306 268.9) 두 색상은 hue 차이가 268.9 - 262.6 = 6.3deg이고, 두 번째 쌍 oklch(0.882 0.181 94.24)와 oklch(0.91 0.245 129.9)는 hue 차이가 129.9 - 94.24 = 35.66deg로, 시각적 색상차를 잘 반영합니다.
역사적 이유로 hsl() 및 hsla()는 레거시 색상 문법도 지원합니다.
테스트
- hsla-001.html (실시간 테스트) (소스)
- hsla-002.html (실시간 테스트) (소스)
- hsla-003.html (실시간 테스트) (소스)
- hsla-004.html (실시간 테스트) (소스)
- hsla-005.html (실시간 테스트) (소스)
- hsla-006.html (실시간 테스트) (소스)
- hsla-007.html (실시간 테스트) (소스)
- hsla-008.html (실시간 테스트) (소스)
- hsla-clamp-negative-saturation.html (실시간 테스트) (소스)
- color-valid.html (실시간 테스트) (소스)
7.1. HSL 색상을 sRGB로 변환하기
HSL 색상을 sRGB로 변환하는 것은 수학적으로 간단합니다. 아래는 변환 알고리즘의 자바스크립트 샘플 구현입니다. 색상의 빨강, 초록, 파랑 컴포넌트를 나타내는 세 숫자 배열을 반환하며, sRGB 영역 내의 색상일 경우 값은 [0, 1] 범위입니다.
이 코드에서는 음수 채도에 대한 파싱 시점 클램핑이 이미 적용되었다고 가정합니다.
/** * @param {number} hue - Hue as degrees 0..360 * @param {number} sat - Saturation in reference range [0,100] * @param {number} light - Lightness in reference range [0,100] * @return {number[]} Array of sRGB components; in-gamut colors in range [0..1] */ function hslToRgb( hue, sat, light) { sat/= 100 ; light/= 100 ; function f( n) { let k= ( n+ hue/ 30 ) % 12 ; let a= sat* Math. min( light, 1 - light); return light- a* Math. max( - 1 , Math. min( k- 3 , 9 - k, 1 )); } return [ f( 0 ), f( 8 ), f( 4 )]; }
7.2. sRGB 색상을 HSL로 변환하기
반대로 변환하는 과정도 비슷하게 진행됩니다.
sRGB 영역을 벗어난 색상에서 중간 단계에서 음수 채도가 나올 수 있는데, 이를 처리하기 위해 특별한 주의를 기울입니다.
/** * @param {number} red - Red component 0..1 * @param {number} green - Green component 0..1 * @param {number} blue - Blue component 0..1 * @return {number[]} Array of HSL values: Hue as degrees 0..360, Saturation and Lightness in reference range [0,100] */ function rgbToHsl( red, green, blue) { let max= Math. max( red, green, blue); let min= Math. min( red, green, blue); let [ hue, sat, light] = [ NaN , 0 , ( min+ max) / 2 ]; let d= max- min; let epsilon= 1 / 100000 ; // max Sat is 1, in this code if ( d!== 0 ) { sat= ( light=== 0 || light=== 1 ) ? 0 : ( max- light) / Math. min( light, 1 - light); switch ( max) { case red: hue= ( green- blue) / d+ ( green< blue? 6 : 0 ); break ; case green: hue= ( blue- red) / d+ 2 ; break ; case blue: hue= ( red- green) / d+ 4 ; } hue= hue* 60 ; } // 아주 sRGB 영역을 벗어난 색상은 음수 채도를 만들 수 있음 // 이 경우 hue에 180을 더하고 양수 채도를 사용함 // 참고: https://github.com/w3c/csswg-drafts/issues/9222 if ( sat< 0 ) { hue+= 180 ; sat= Math. abs( sat); } if ( hue>= 360 ) { hue-= 360 ; } if ( sat<= epsilon) { hue= NaN ; } return [ hue, sat* 100 , light* 100 ]; }
7.3. HSL 색상 예시
이 절은 규범적이지 않습니다.
테스트
이 절은 규범적이지 않으므로, 테스트가 필요하지 않습니다.
아래 표는 다양한 HSL 색상을 보여줍니다. 각 표는 한 가지 색상각(hue)을 대표하며, 30° 간격으로 선택된 대표적인 "핵심" 색상: 빨강, 노랑, 초록, 시안, 파랑, 마젠타, 그리고 그 사이의 6가지 중간색을 나타냅니다.
각 표에서 X축은 채도(saturation), Y축은 명도(lightness)를 나타냅니다.
0° 빨강 | ||||||
---|---|---|---|---|---|---|
100% | 80% | 60% | 40% | 20% | 0% | |
100% | ||||||
90% | ||||||
80% | ||||||
70% | ||||||
60% | ||||||
50% | ||||||
40% | ||||||
30% | ||||||
20% | ||||||
10% | ||||||
0% |
30° 빨강-노랑(=오렌지) | ||||||
---|---|---|---|---|---|---|
100% | 80% | 60% | 40% | 20% | 0% | |
100% | ||||||
90% | ||||||
80% | ||||||
70% | ||||||
60% | ||||||
50% | ||||||
40% | ||||||
30% | ||||||
20% | ||||||
10% | ||||||
0% |
60° 노랑 | ||||||
---|---|---|---|---|---|---|
100% | 80% | 60% | 40% | 20% | 0% | |
100% | ||||||
90% | ||||||
80% | ||||||
70% | ||||||
60% | ||||||
50% | ||||||
40% | ||||||
30% | ||||||
20% | ||||||
10% | ||||||
0% |
90° 노랑-초록 | ||||||
---|---|---|---|---|---|---|
100% | 80% | 60% | 40% | 20% | 0% | |
100% | ||||||
90% | ||||||
80% | ||||||
70% | ||||||
60% | ||||||
50% | ||||||
40% | ||||||
30% | ||||||
20% | ||||||
10% | ||||||
0% |
120° 초록 | ||||||
---|---|---|---|---|---|---|
100% | 80% | 60% | 40% | 20% | 0% | |
100% | ||||||
90% | ||||||
80% | ||||||
70% | ||||||
60% | ||||||
50% | ||||||
40% | ||||||
30% | ||||||
20% | ||||||
10% | ||||||
0% |
150° 초록-시안 | ||||||
---|---|---|---|---|---|---|
100% | 80% | 60% | 40% | 20% | 0% | |
100% | ||||||
90% | ||||||
80% | ||||||
70% | ||||||
60% | ||||||
50% | ||||||
40% | ||||||
30% | ||||||
20% | ||||||
10% | ||||||
0% |
180° 시안 | ||||||
---|---|---|---|---|---|---|
100% | 80% | 60% | 40% | 20% | 0% | |
100% | ||||||
90% | ||||||
80% | ||||||
70% | ||||||
60% | ||||||
50% | ||||||
40% | ||||||
30% | ||||||
20% | ||||||
10% | ||||||
0% |
210° 시안-파랑 | ||||||
---|---|---|---|---|---|---|
100% | 80% | 60% | 40% | 20% | 0% | |
100% | ||||||
90% | ||||||
80% | ||||||
70% | ||||||
60% | ||||||
50% | ||||||
40% | ||||||
30% | ||||||
20% | ||||||
10% | ||||||
0% |
240° 파랑 | ||||||
---|---|---|---|---|---|---|
100% | 80% | 60% | 40% | 20% | 0% | |
100% | ||||||
90% | ||||||
80% | ||||||
70% | ||||||
60% | ||||||
50% | ||||||
40% | ||||||
30% | ||||||
20% | ||||||
10% | ||||||
0% |
270° 파랑-마젠타 | ||||||
---|---|---|---|---|---|---|
100% | 80% | 60% | 40% | 20% | 0% | |
100% | ||||||
90% | ||||||
80% | ||||||
70% | ||||||
60% | ||||||
50% | ||||||
40% | ||||||
30% | ||||||
20% | ||||||
10% | ||||||
0% |
300° 마젠타 | ||||||
---|---|---|---|---|---|---|
100% | 80% | 60% | 40% | 20% | 0% | |
100% | ||||||
90% | ||||||
80% | ||||||
70% | ||||||
60% | ||||||
50% | ||||||
40% | ||||||
30% | ||||||
20% | ||||||
10% | ||||||
0% |
330° 마젠타-빨강 | ||||||
---|---|---|---|---|---|---|
100% | 80% | 60% | 40% | 20% | 0% | |
100% | ||||||
90% | ||||||
80% | ||||||
70% | ||||||
60% | ||||||
50% | ||||||
40% | ||||||
30% | ||||||
20% | ||||||
10% | ||||||
0% |
8. HWB 색상: hwb() 함수
HWB(Hue-Whiteness-Blackness의 약자) [HWB]는 sRGB 색상을 지정하는 또 다른 방법으로, HSL과 비슷하지만, 사람에게 더 직관적으로 다가오는 경우가 많습니다. 색상을 기준이 되는 hue로 시작해서, 그에 혼합할 하양(whiteness)과 검정(blackness)의 정도를 지정하여 색을 만듭니다.
많은 컬러 피커가 HWB 색상 시스템을 기반으로 하는데, 그만큼 직관적이기 때문입니다.
HWB 색상은 sRGB로 해석됩니다.

< input type = "color" >
를
활성화할 때 나타납니다.
바깥쪽 휠로 hue를 선택하고,
안쪽 삼각형을 클릭하여 백색(whiteness)과 흑색(blackness)의 상대적 비율을 선택합니다.
hwb() 함수의 문법은 다음과 같습니다:
hwb () =hwb ( [ <hue> | none] [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ /[ <alpha-value> | none] ] ?)
백분율 | W와 B에 허용됨 |
---|---|
백분율 기준 범위 | W와 B: 0% = 0.0, 100% = 100.0 |
무효(hue) ε | W + B >= 99.999 |
첫 번째 인자는 hue(색상각)를 지정하며, hsl()과 완전히 동일하게 정의됩니다; 즉, 동일한 단점(hue 균일성 등)이 있습니다.
두 번째 인자는 혼합할 백색의 양을, 0%(백색 없음)부터 100%(전부 백색)까지 백분율로 지정합니다. 세 번째 인자는 혼합할 흑색의 양을, 0%(흑색 없음)부터 100%(전부 흑색)까지 백분율로 지정합니다.
이 범위를 벗어나는 값도 잘못된 것은 아닙니다; hue가 [0,360) 범위를 벗어나면 그 범위로 정규화되고, 백색과 흑색의 합이 100% 이상이면 아래 설명처럼 무채색(achromatic) 색상이 생성됩니다.
결과 색상은 개념적으로 선택한 hue의 페인트, 백색 페인트, 흑색 페인트를 각 백분율만큼 혼합한 것이라 생각하면 됩니다.
white+black의 합이 100% 이상이면, 이는 무채색(achromatic) 색상, 즉 회색의 한 종류를 의미합니다; sRGB로 변환될 때 R, G, B 값이 모두 같으며 그 값은 white / (white + black)입니다.
무채색 HWB 색상은 선택한 hue의 흔적이 남아 있지 않습니다. 이 경우 hue 컴포넌트는 무효(powerless)입니다.
네 번째 인자는 색상의 알파 컴포넌트입니다. rgb() 함수의 네 번째 인자와 동일하게 해석됩니다. 생략 시 기본값은 100%입니다.
hwb는 이 명세에서 새로 도입된 것이므로 Web 호환성 문제가 없으며, hwb()는 레거시 색상 문법(모든 인자를 쉼표로 구분하는 방식)을 지원하지 않습니다. hwb() 안에 쉼표를 사용하면 오류입니다.
테스트
8.1. HWB 색상을 sRGB로 변환하기
HWB 색상을 sRGB로 변환하는 것은 간단하며, HSL을 RGB로 변환하는 방법과 유사합니다. 아래 Javascript 구현은 먼저 백색과 흑색 컴포넌트를 정규화하여 합이 100%를 넘지 않도록 처리합니다.
/** * @param {number} hue - Hue as degrees 0..360 * @param {number} white - Whiteness in reference range [0,100] * @param {number} black - Blackness in reference range [0,100] * @return {number[]} Array of RGB components 0..1 */ function hwbToRgb( hue, white, black) { white/= 100 ; black/= 100 ; if ( white+ black>= 1 ) { let gray= white/ ( white+ black); return [ gray, gray, gray]; } let rgb= hslToRgb( hue, 100 , 50 ); for ( let i= 0 ; i< 3 ; i++ ) { rgb[ i] *= ( 1 - white- black); rgb[ i] += white; } return rgb; }
8.2. sRGB 색상을 HWB로 변환하기
반대로 변환하는 과정도 비슷하게 진행됩니다.
/** * @param {number} red - Red component 0..1 * @param {number} green - Green component 0..1 * @param {number} blue - Blue component 0..1 * @return {number} Hue as degrees 0..360 */ function rgbToHue( red, green, blue) { // rgbToHsl과 유사하지만, 채도와 명도는 계산하지 않고, // 음수 채도 가능성은 무시함. let max= Math. max( red, green, blue); let min= Math. min( red, green, blue); let hue= NaN ; let d= max- min; if ( d!== 0 ) { switch ( max) { case red: hue= ( green- blue) / d+ ( green< blue? 6 : 0 ); break ; case green: hue= ( blue- red) / d+ 2 ; break ; case blue: hue= ( red- green) / d+ 4 ; } hue*= 60 ; } if ( hue>= 360 ) { hue-= 360 ; } return hue; } /** * @param {number} red - Red component 0..1 * @param {number} green - Green component 0..1 * @param {number} blue - Blue component 0..1 * @return {number[]} Array of HWB values: Hue as degrees 0..360, Whiteness and Blackness in reference range [0,100] */ function rgbToHwb( red, green, blue) { let epsilon= 1 / 100000 ; // 100 곱셈에 대한 오차 보정 var hue= rgbToHue( red, green, blue); var white= Math. min( red, green, blue); var black= 1 - Math. max( red, green, blue); if ( white+ black>= 1 - epsilon) { hue= NaN ; } return ([ hue, white* 100 , black* 100 ]); }
8.3. HWB 색상 예시
이 절은 규범적이지 않습니다.
테스트
이 절은 규범적이지 않으므로, 테스트가 필요하지 않습니다.
0° 빨강 | ||||||
---|---|---|---|---|---|---|
W\B | 0% | 20% | 40% | 60% | 80% | 100% |
0% | ||||||
20% | ||||||
40% | ||||||
60% | ||||||
80% | ||||||
100% |
30° 빨강-노랑(오렌지) | ||||||
---|---|---|---|---|---|---|
W\B | 0% | 20% | 40% | 60% | 80% | 100% |
0% | ||||||
20% | ||||||
40% | ||||||
60% | ||||||
80% | ||||||
100% |
60° 노랑 | ||||||
---|---|---|---|---|---|---|
W\B | 0% | 20% | 40% | 60% | 80% | 100% |
0% | ||||||
20% | ||||||
40% | ||||||
60% | ||||||
80% | ||||||
100% |
90° 노랑-초록 | ||||||
---|---|---|---|---|---|---|
W\B | 0% | 20% | 40% | 60% | 80% | 100% |
0% | ||||||
20% | ||||||
40% | ||||||
60% | ||||||
80% | ||||||
100% |
120° 초록 | ||||||
---|---|---|---|---|---|---|
W\B | 0% | 20% | 40% | 60% | 80% | 100% |
0% | ||||||
20% | ||||||
40% | ||||||
60% | ||||||
80% | ||||||
100% |
150° 초록-시안 | ||||||
---|---|---|---|---|---|---|
W\B | 0% | 20% | 40% | 60% | 80% | 100% |
0% | ||||||
20% | ||||||
40% | ||||||
60% | ||||||
80% | ||||||
100% |
180° 시안 | ||||||
---|---|---|---|---|---|---|
W\B | 0% | 20% | 40% | 60% | 80% | 100% |
0% | ||||||
20% | ||||||
40% | ||||||
60% | ||||||
80% | ||||||
100% |
210° 시안-파랑 | ||||||
---|---|---|---|---|---|---|
W\B | 0% | 20% | 40% | 60% | 80% | 100% |
0% | ||||||
20% | ||||||
40% | ||||||
60% | ||||||
80% | ||||||
100% |
240° 파랑 | ||||||
---|---|---|---|---|---|---|
W\B | 0% | 20% | 40% | 60% | 80% | 100% |
0% | ||||||
20% | ||||||
40% | ||||||
60% | ||||||
80% | ||||||
100% |
270° 파랑-마젠타 | ||||||
---|---|---|---|---|---|---|
W\B | 0% | 20% | 40% | 60% | 80% | 100% |
0% | ||||||
20% | ||||||
40% | ||||||
60% | ||||||
80% | ||||||
100% |
300° 마젠타 | ||||||
---|---|---|---|---|---|---|
W\B | 0% | 20% | 40% | 60% | 80% | 100% |
0% | ||||||
20% | ||||||
40% | ||||||
60% | ||||||
80% | ||||||
100% |
330° 마젠타-빨강 | ||||||
---|---|---|---|---|---|---|
W\B | 0% | 20% | 40% | 60% | 80% | 100% |
0% | ||||||
20% | ||||||
40% | ||||||
60% | ||||||
80% | ||||||
100% |
9. 디바이스 독립 색상: CIE Lab 및 LCH, Oklab 및 OKLCh
9.1. CIE Lab 및 LCH
이 절은 규범적이지 않습니다.
테스트
이 절은 규범적이지 않으므로, 테스트가 필요하지 않습니다.
물리적 색상 측정값은 일반적으로 CIE L*a*b* [CIELAB] 색상 공간으로 표현합니다. 1976년 CIE에서 만든 것으로, 흔히 Lab이라고 부릅니다. 디바이스 간 색상 변환에서도 중간 단계로 Lab을 사용할 수 있습니다. 인간 시각 실험을 바탕으로 만들어졌으며, Lab은 사람이 볼 수 있는 전체 색 영역을 나타냅니다.
Lab은 중심에 명도(Lightness, L) 축이 있는 직교 좌표계입니다. 이 값은 보통 단위 없는 숫자로 기록되며, CSS와의 호환성을 위해 백분율로도 쓸 수 있습니다. 100%는 L 값 100, 1.0이 아닙니다. L=0% 또는 0은 깊은 검정(빛 없음), L=100% 또는 100은 확산된 흰색입니다.
편리하게도 L=50% 또는 50은 중간 회색이고, L 값의 증가가 시각적으로 고르게 분포됩니다: Lab 색상 공간은 시각적으로 균등하도록 설계되었습니다.
a, b 축은 색상(hue)을 나타냅니다; a 축 양수는 보라빛이 도는 빨강, 음수는 보색인 초록입니다. b 축 양수는 노랑, 음수는 보색인 파랑/보라입니다. 채도가 낮은 색은 a, b 값이 작고 L 축에 가까우며, 채도가 높은 색은 L 축에서 멀리 떨어집니다.
조명(illuminant)은 D50 흰색이며, 표준화된 주광 스펙트럼(색온도 5000K)입니다. 완전 확산 반사체에 반사된 빛을 기준으로 하며, 맑은 날 햇빛 색상과 비슷합니다. D50은 ICC 색상 변환의 프로파일 접속 공간, Lab 편집을 지원하는 이미지 편집기의 기준, 측색기나 분광방사계의 Lab 측정에서도 사용됩니다.
다른 기준점에서 지정된 색상을 변환하는 것은 색상 적응 변환(chromatic adaptation transform)이라고 하며, 새로운 조명 환경에 눈이 적응할 때의 변화를 모델링합니다. 선형 브래드포드 알고리즘 [ICC](원래 브래드포드 알고리즘 [Bradford-CAT]의 단순화 버전)는 업계 표준 색상 적응 변환으로, 행렬 곱셈만으로 쉽게 계산할 수 있습니다.
CIE LCH는 Lab과 동일한 L 축을 가지며, 극좌표계 C(채도, chroma)와 H(색상각, hue)를 사용합니다. 즉, 원통 좌표계입니다. C는 L 축에서의 거리이며, H는 a 축 양수에서 b 축 양수 방향으로의 각도입니다.
참고: Lab 및 LCH의 L 축은 HSL의 L 축과 혼동하면 안 됩니다. 예를 들어, HSL에서는 sRGB 파랑(#00F)과 노랑(#FF0)이 L 값 50%로 같지만, 실제로 파란색이 훨씬 더 어둡습니다. Lab에서는 더 명확하게 구별됩니다: sRGB 파랑은 lab(29.567% 68.298 -112.0294), sRGB 노랑은 lab(97.607% -15.753 93.388)입니다. Lab과 LCH에서 두 색의 L 값이 같으면, 시각적으로도 밝기가 동일합니다. HSL 및 관련 RGB 극좌표 모델은 LCH가 Lab에 준 혜택을 RGB에 적용하려고 만들어졌지만, 정확도는 많이 떨어집니다.
CIE Lab 및 LCH는 널리 사용되지만, 몇 가지 문제가 알려져 있습니다. 특히:
- 색상선(hue linearity)
- 파란색 영역(LCH Hue 270°~330°)에서 실제 색상선이 예측과 다릅니다. 같은 hue, 다른 채도의 파란색을 그리면 중성축에서 직선이 아니라 곡선이 됩니다. 즉, 채도가 낮아질수록 보랏빛이 나타납니다.
- 색상 균등(hue uniformity)
- LCH의 hue는 대체로 고르게 분포하지만, (HSL, HWB보다 훨씬 우수) 완벽하지는 않습니다.
- 높은 채도에서의 과예측(over-prediction of high Chroma differences)
- 높은 채도 색상에서 채도 변화가 중성색보다 덜 눈에 띕니다.
이러한 문제는 균등한 색상 그라데이션, 색상 공간 간 영역 매핑, 두 색상 간 시각적 차이 계산 등에 영향을 미칩니다.
이를 보완하기 위해, 두 색상 간 시각적 차이를 계산하는 공식(ΔE)이 점점 더 정확해지고(복잡해짐) 있습니다. 현행 업계 표준 공식인 ΔE 2000은 Lab과 LCH의 일부 문제를 잘 완화합니다. 샘플 구현은 § 19.1 ΔE2000에 있습니다.
하지만 색상선 곡률 문제까지 해결되진 않습니다.
9.2. Oklab 및 OKLCh
이 절은 규범적이지 않습니다.
테스트
이 절은 규범적이지 않으므로, 테스트가 필요하지 않습니다.
최근 Oklab이라는 개선된 Lab 계열 색상 공간이 개발되었습니다 [Oklab]. 극좌표 버전은 OKLCh라고 부릅니다. 방대한 데이터셋에서 시각적으로 유사한 색상을 수치적으로 최적화하여 만들어졌으며, 기존 CIE LCH보다 색상선, 색상 균등성, 채도 균등성이 개선되었습니다.
CIE Lab과 마찬가지로 중심 명도 L 축이 있으며, 보통 [0,1] 범위의 단위 없는 숫자로 표기합니다; CSS와의 호환성을 위해 백분율로도 쓸 수 있습니다. 100%는 L 값 1.0입니다. L=0% 또는 0.0은 깊은 검정, L=100% 또는 1.0은 확산된 흰색입니다.
참고: CIE Lab이 확산 흰색 적응을 전제로 하는 것과 달리, Oklab은 정의된 색상에 적응한다고 가정하여 스케일 불변성을 지향합니다.
CIE Lab과 같이 a, b 축은 색상(hue)을 나타냅니다; a 축 양수는 보라빛이 도는 빨강, 음수는 보색인 초록, b 축 양수는 노랑, 음수는 보색인 파랑/보라입니다.
조명은 D65로, 대부분의 RGB 색상 공간과 동일한 기준점입니다.
OKLCh는 Oklab과 같은 L 축을 가지며, 극좌표계 C(채도)와 H(색상각)를 사용합니다.
참고: CIE LCH에서 Chroma가 200 이상까지 갈 수 있는 것과 달리, OKLCh의 Chroma 값은 보통 0.5 정도까지입니다. 색상각(hue angle)은 두 모델 간 대체로 비슷하지만, 정확히 일치하진 않습니다.


Oklab이 CIE Lab보다 시각적으로 더 균등하므로, 색상 차이 계산이 3차원 공간 거리(루트의 제곱 합)로 간단합니다. 매우 단순하지만, 샘플 구현은 § 19.2 ΔEOK에 있습니다.
9.3. Lab 및 LCH 지정: lab() 및 lch() 함수 표기법
CSS에서는 색상을 Lab 및 LCH로 직접 표현할 수 있습니다.
lab () =lab ( [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ /[ <alpha-value> | none] ] ?)
백분율 | L, a, b에 허용됨 |
---|---|
백분율 기준 범위 | L: 0% = 0.0, 100% = 100.0 a, b: -100% = -125, 100% = 125 |
테스트
- lab-001.html (실시간 테스트) (소스)
- lab-002.html (실시간 테스트) (소스)
- lab-003.html (실시간 테스트) (소스)
- lab-004.html (실시간 테스트) (소스)
- lab-005.html (실시간 테스트) (소스)
- lab-006.html (실시간 테스트) (소스)
- lab-007.html (실시간 테스트) (소스)
- lab-008.html (실시간 테스트) (소스)
- lab-l-over-100-1.html (실시간 테스트) (소스)
- lab-l-over-100-2.html (실시간 테스트) (소스)
- color-valid.html (실시간 테스트) (소스)
- color-computed-lab.html (실시간 테스트) (소스)
- color-invalid-lab.html (실시간 테스트) (소스)
- color-valid-lab.html (실시간 테스트) (소스)
Lab에서는 첫 번째 인자가 CIE 명도(Lightness, L)를 지정합니다. 이 값은 0% 또는 0에서 100% 또는 100까지의 숫자입니다. 0% 또는 0 미만 값은 파싱 시점에 0%로 클램핑되어야 하며, 100% 또는 100 초과 값도 파싱 시점에 100%로 클램핑됩니다.
두 번째, 세 번째 인자는 Lab 색상 공간의 "a", "b" 축 방향 거리이며, 앞 절에서 설명한 바와 같습니다. 이 값들은 부호 있는 값(양수, 음수 모두 허용)이고, 이론적으로 제한이 없지만(실제로는 ±160을 넘지 않음) 실무에서는 범위 내에서 사용됩니다.
옵션으로 네 번째 <alpha-value> 컴포넌트가 있으며, 슬래시로 구분되며, 알파 컴포넌트를 나타냅니다.
Lab 색상의 명도(L)가 클램핑 후 0% 또는 100%이면, 색상은 검정 또는 흰색으로 표시됩니다(디스플레이 영역 매핑 결과).
lab ( 29.2345 % 39.3825 20.0664 ); lab ( 52.2345 40.1645 59.9971 ); lab ( 60.2345 -5.3654 58.956 ); lab ( 62.2345 % -34.9638 47.7721 ); lab ( 67.5345 -8.6911 -41.6019 ); lab ( 29.69 % 44.888 % -29.04 % )
lch () =lch ( [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ <hue> | none] [ /[ <alpha-value> | none] ] ?)
백분율 | L, C에 허용됨 |
---|---|
백분율 기준 범위 | L: 0% = 0.0, 100% = 100.0 C: 0% = 0, 100% = 150 |
무효(hue) ε | C <= 0.0015 |
테스트
- lch-001.html (실시간 테스트) (소스)
- lch-002.html (실시간 테스트) (소스)
- lch-003.html (실시간 테스트) (소스)
- lch-004.html (실시간 테스트) (소스)
- lch-005.html (실시간 테스트) (소스)
- lch-006.html (실시간 테스트) (소스)
- lch-007.html (실시간 테스트) (소스)
- lch-008.html (실시간 테스트) (소스)
- lch-009.html (실시간 테스트) (소스)
- lch-010.html (실시간 테스트) (소스)
- lch-l-over-100-1.html (실시간 테스트) (소스)
- lch-l-over-100-2.html (실시간 테스트) (소스)
- color-valid.html (실시간 테스트) (소스)
CIE LCH에서 첫 번째 인자는 CIE 명도 L을 지정하며, lab()의 명도 인자와 동일하게 해석됩니다.
두 번째 인자는 채도 C이며, ("색의 양"을 대략적으로 나타냄). 최소 유효값은 0이고, 최대값은 이론적으로 무제한이지만 실제로는 230을 넘지 않습니다. 음수 값이 제공되면 파싱 시점에 0으로 클램핑됩니다.
세 번째 인자는 색상각 H입니다. <hue> 인자와 유사하게 해석되지만, hsl()처럼 각도와 색상 매핑이 동일하지는 않고, 시각적으로 고르게 분포됩니다. 0deg는 a 축 양(보라빛 빨강)을 가리키며, (360deg, 720deg 등도 같음) 90deg는 b 축 양(겨자 노랑), 180deg는 a 축 음(초록빛 시안), 270deg는 b 축 음(하늘 파랑)입니다.
옵션으로 네 번째 <alpha-value> 컴포넌트가 있으며, 슬래시로 구분되어, 알파 컴포넌트를 나타냅니다.
LCH 색상의 채도(C)가 0%이면 hue 컴포넌트는 무효(powerless)입니다. LCH 색상의 명도(L)가 클램핑 후 0% 또는 100%이면, 색상은 검정 또는 흰색으로 표시됩니다(디스플레이 영역 매핑 결과).
lch ( 29.2345 % 44.2 27 ); lch ( 52.2345 % 72.2 56.2 ); lch ( 60.2345 59.2 95.2 ); lch ( 62.2345 % 59.2 126.2 ); lch ( 67.5345 % 42.5 258.2 ); lch ( 29.69 % 45.553 % 327.1 )
lab 및 lch는 이 명세에서 새로 도입된 것이므로 Web 호환성 문제가 없으며, lab() 및 lch()는 레거시 색상 문법(모든 인자를 쉼표로 구분하는 방식)을 지원하지 않습니다. 이 함수들에서 쉼표를 사용하면 오류입니다.
9.4. Oklab 및 OKLCh 지정: oklab() 및 oklch() 함수 표기법
CSS에서는 색상을 Oklab 및 OKLCh로 직접 표현할 수 있습니다.
oklab () =oklab ( [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ /[ <alpha-value> | none] ] ?)
백분율 | L, a, b에 허용됨 |
---|---|
백분율 기준 범위 | L: 0% = 0.0, 100% = 1.0 a, b: -100% = -0.4, 100% = 0.4 |
테스트
- oklab-001.html (실시간 테스트) (소스)
- oklab-002.html (실시간 테스트) (소스)
- oklab-003.html (실시간 테스트) (소스)
- oklab-004.html (실시간 테스트) (소스)
- oklab-005.html (실시간 테스트) (소스)
- oklab-006.html (실시간 테스트) (소스)
- oklab-007.html (실시간 테스트) (소스)
- oklab-008.html (실시간 테스트) (소스)
- oklab-009.html (실시간 테스트) (소스)
- oklab-l-almost-0.html (실시간 테스트) (소스)
- oklab-l-almost-1.html (실시간 테스트) (소스)
- oklab-l-over-1-1.html (실시간 테스트) (소스)
- oklab-l-over-1-2.html (실시간 테스트) (소스)
- color-valid.html (실시간 테스트) (소스)
Oklab에서 첫 번째 인자는 Oklab 명도를 지정합니다. 이 값은 0% 또는 0에서 100% 또는 1.0 범위입니다.
0% 또는 0.0 미만 값은 파싱 시점에 0%로 클램핑되어야 하며, 100% 또는 1.0 초과 값은 파싱 시점에 100%로 클램핑됩니다.
두 번째, 세 번째 인자는 Oklab 색상 공간의 "a", "b" 축 방향 거리이며, 앞 절에서 설명한 바와 같습니다. 이 값들은 부호 있는 값(양수, 음수 모두 허용)이고, 이론적으로 제한이 없지만(실제로는 ±0.5를 넘지 않음) 실무에서는 범위 내에서 사용됩니다.
슬래시(/)로 구분되는 선택적 네 번째 <alpha-value> 컴포넌트가 있으며, 이는 알파 컴포넌트를 나타냅니다.
Oklab 색상의 명도가 0% 또는 0, 혹은 100% 또는 1.0인 경우, 색상은 각각 검정 또는 흰색으로 표시됩니다. 이는 디스플레이 색역 매핑(gamut mapping)에 의해 결정됩니다.
oklab ( 40.101 % 0.1147 0.0453 ); oklab ( 59.686 % 0.1009 0.1192 ); oklab ( 0.65125 -0.0320 0.1274 ); oklab ( 66.016 % -0.1084 0.1114 ); oklab ( 72.322 % -0.0465 -0.1150 ); oklab ( 42.1 % 41 % -25 % )
oklch () =oklch ( [ <percentage> | <number> | none] [ <percentage> | <number> | none] [ <hue> | none] [ /[ <alpha-value> | none] ] ?)
퍼센트 값 허용 | L 및 C에 허용됨 |
---|---|
퍼센트 기준 범위 | L: 0% = 0.0, 100% = 1.0 C: 0% = 0.0, 100% = 0.4 |
Powerless hue ε | C <= 0.000004 |
테스트
- oklch-001.html (실시간 테스트) (소스)
- oklch-002.html (실시간 테스트) (소스)
- oklch-003.html (실시간 테스트) (소스)
- oklch-004.html (실시간 테스트) (소스)
- oklch-005.html (실시간 테스트) (소스)
- oklch-006.html (실시간 테스트) (소스)
- oklch-007.html (실시간 테스트) (소스)
- oklch-008.html (실시간 테스트) (소스)
- oklch-009.html (실시간 테스트) (소스)
- oklch-010.html (실시간 테스트) (소스)
- oklch-011.html (실시간 테스트) (소스)
- oklch-l-almost-0.html (실시간 테스트) (소스)
- oklch-l-almost-1.html (실시간 테스트) (소스)
- oklch-l-over-1-1.html (실시간 테스트) (소스)
- oklch-l-over-1-2.html (실시간 테스트) (소스)
- color-valid.html (실시간 테스트) (소스)
OKLCh에서 첫 번째 인자는 OKLCh 명도 L을 지정하며, oklab()의 명도 인자와 동일하게 해석합니다.
두 번째 인자는 채도(C)입니다. 최소 유효 값은 0이고, 최대값은 이론적으로 제한이 없지만 실제로는 0.5를 넘지 않습니다. 음수 값이 제공되면 파싱 시점에 0으로 클램핑됩니다.
세 번째 인자는 색상 각도(H)입니다. 이는 <hue> 인자와 비슷하게 해석되지만, hsl() 및 lch()와는 각도 해석 방식이 다릅니다. 0deg는 양의 "a" 축(적자색 방향)을 가리키며, (360deg, 720deg 등도 동일), 90deg는 양의 "b" 축(겨자 노랑 방향), 180deg는 음의 "a" 축(청록 방향), 270deg는 음의 "b" 축(하늘색 방향)을 가리킵니다.
슬래시(/)로 구분되는 선택적 네 번째 <alpha-value> 컴포넌트가 있으며, 이는 알파 컴포넌트를 나타냅니다.
OKLCh 색상의 채도(C)가 0% 또는 0인 경우, 색상(hue) 컴포넌트는 무력(powerless)합니다. OKLCh 색상의 명도가 0% 또는 0, 혹은 100% 또는 1.0인 경우, 색상은 각각 검정 또는 흰색으로 표시됩니다. 이는 디스플레이 색역 매핑(gamut mapping)에 의해 결정됩니다.
oklch ( 40.101 % 0.12332 21.555 ); oklch ( 59.686 % 0.15619 49.7694 ); oklch ( 0.65125 0.13138 104.097 ); oklch ( 0.66016 0.15546 134.231 ); oklch ( 72.322 % 0.12403 247.996 ); oklch ( 42.1 % 48.25 % 328.4 )
oklab 및 oklch는 이 명세 레벨에서 새로 추가된 것이므로, oklab() 및 oklch()는 레거시 색상 구문(모든 인자를 쉼표로 구분하는 방식)을 지원하지 않습니다. 이 함수 내부에서 쉼표를 사용하는 것은 오류입니다.
9.5. Lab 또는 Oklab 색상을 LCH 또는 OKLCh 색상으로 변환
극좌표 형태로 변환하는 것은 매우 간단합니다:
- C = sqrt(a^2 + b^2)
- if (C > epsilon) H = atan2(b, a) else H는 존재하지 않음
- L은 동일함
a, b 값이 아주 작을 때(채도가 거의 0인 경우), 시각적으로는 중성축과 다를 바 없으나, 값이 조금만 바뀌어도 hue 각도가 크게 요동칠 수 있고, 사실상 랜덤이 됩니다. CSS에서는 이 경우 hue가 무효로 간주되며, LCH 또는 OKLCh로 변환시 missing으로 처리됩니다; CSS 외 환경에서는 NaN 등으로 표시될 수 있습니다.
9.6. LCH 또는 OKLCh 색상을 Lab 또는 Oklab 색상으로 변환
직교 좌표 형태로 변환하는 것도 매우 간단합니다:
- H가 존재하지 않으면 a = b = 0
-
그렇지 않으면,
- a = C cos(H)
- b = C sin(H)
- L은 동일함
10. 미리 정의된 색상 공간
CSS는 여러 미리 정의된 색상 공간을 제공합니다. 대표적으로 display-p3 [Display-P3]가 있으며, 이는 최신 광색역 모니터에서 일반적인 넓은 색상 영역입니다. prophoto-rgb는 사진가들이 널리 사용하며, rec2020 [Rec.2020]는 방송 산업 표준으로, 실세계의 거의 모든 색상을 표현할 수 있는 초광색역 공간입니다.
10.1. 미리 정의된 색상 지정: color() 함수
color() 함수는 색상을 특정 명시된 색상 공간에서 지정할 수 있게 해줍니다(대부분의 다른 색상 함수가 암묵적으로 sRGB를 사용하는 것과 달리). 문법은 다음과 같습니다:
color () =color ( <colorspace-params>[ /[ <alpha-value> | none] ] ?) <colorspace-params> =[ <predefined-rgb-params> | <xyz-params>] <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 } <xyz-space> = xyz | xyz-d50 | xyz-d65
테스트
color 함수는 특정 명시적 색상 공간에서 색상 파라미터를 받습니다.
아래 설명된 대로 잘못된 색상이거나, 유효한 색상일 수 있습니다.
파라미터 형식은 다음과 같습니다:
-
<ident>는 미리 정의된 색상 공간 중 하나입니다(예: display-p3). 개별 미리 정의된 색상 공간은 <number> 또는 <percentage> 또는 두 가지 모두 사용 가능 여부를 제한할 수 있습니다.
<ident>가 존재하지 않는 색상 공간을 지정하면(미리 정의된 색상 공간과 일치하지 않으면) 해당 인자는 잘못된 색상으로 처리됩니다.
-
해당 색상 공간의 3개 파라미터(RGB 또는 XYZ 값).
색상 영역을 벗어난(out of gamut) 색상의 컴포넌트 값은 0 혹은 0% 미만, 1 혹은 100% 초과일 수 있습니다. 이런 값은 잘못된 것이 아니라, 중간 연산에서 유지됩니다; 디스플레이에서는 css gamut mapping(상대적 컬러리메트릭 방식)으로 실제 값이 0/0%~1/100% 범위로 맞춰집니다.
-
옵션으로 슬래시로 구분된 <alpha-value>.
color()는 이번 현행 표준 단계에서 새로 도입된 것이므로 웹 호환성 문제가 없으며, color()는 모든 인자를 쉼표로 구분하는 레거시 색상 문법(legacy color syntax)을 지원하지 않습니다. 이 함수에서 쉼표를 사용하면 오류입니다.
색상이 잘못된 색상이거나 색상 영역을 벗어난(out of gamut) 색상인 경우 표시할 수 없습니다.
지정한 색상이 표시할 수 있습니다라면, (즉 잘못된 색상도 아니고 색상 영역을 벗어난 색상도 아니면) 이것이 color() 함수의 실제 값(actual value)입니다.
지정한 색상이 유효한 색상이지만 표시할 수 없는 색상이면, 실제 값은 지정한 색상을 css gamut mapping을 거쳐 디스플레이에 맞게 변환한 값입니다.
색상이 잘못된 색상이면, 사용 값(used value)은 불투명 검정입니다.
color ( rec20200.42053 0.979780 0.00579 );
LCH에서는 이 색상이 다음과 같습니다.
lch ( 86.6146 % 160.0000 136.0088 );
display-p3에서는 이 색상이 다음과 같습니다.
color ( display-p3-0.6112 1.0079 -0.2192 );
그리고 display-p3에서는 색상 영역을 벗어납니다 (red, blue가 음수이고 green은 1 초과). 만약 display-p3 화면이 있다면 이 색상은:
- 유효함
- 영역 내 (rec.2020에서는)
- 영역 밖 (현재 디스플레이에서는)
- 따라서 표시할 수 없음
color ( profoto-rgb0.4835 0.9167 0.2188 )
10.2. 미리 정의된 sRGB 색상 공간: sRGB 키워드
아래에서 정의하는 sRGB 미리 정의된 색상 공간은 레거시 sRGB 색상(예: rgb())에 사용되는 것과 동일합니다.
- srgb
-
srgb
[SRGB]
색상 공간은 숫자 3개 파라미터를 받으며,
각각 빨강, 초록, 파랑 컴포넌트입니다.
영역 내 색상은 세 컴포넌트 모두 [0, 1] 범위에 있습니다.
기준백색점은 D65입니다.
[SRGB] 에서는 인코딩(encoding)과 일반(typical) 두 가지 시청 조건을 규정하는데, [ICC]에서는 색상 변환 및 최적 시청에 인코딩 조건(아래 표)을 사용할 것을 권장합니다.
sRGB는 CSS의 기본 색상 공간이며, 모든 레거시 색상 함수에서 사용됩니다.
주요 특성은 다음과 같습니다:
x y 빨강 색도 0.640 0.330 초록 색도 0.300 0.600 파랑 색도 0.150 0.060 백색 색도 D65 전달 함수 아래 참고 백색 휘도 80.0 cd/m2 검정 휘도 0.20 cd/m2 이미지 상태 디스플레이 기준(display-referred) 백분율 R, G, B에 허용됨 백분율 기준 범위 R,G,B: 0% = 0.0, 100% = 1.0 let sign= c< 0 ? - 1 : 1 ; let abs= Math. abs( c); if ( abs<= 0.04045 ) { cl= c/ 12.92 ; } else { cl= sign* ( Math. pow(( abs+ 0.055 ) / 1.055 , 2.4 )); } c는 감마 인코딩된 빨강, 초록, 파랑 컴포넌트입니다. cl은 해당 선형광(linear-light) 컴포넌트입니다.
LCH에서 sRGB 색상 공간의 시각화. 원색(primary)과 2차색(secondary)을 표시.
테스트
10.3. 미리 정의된 선형광 sRGB 색상 공간: srgb-linear 키워드
sRGB-linear 미리 정의된 색상 공간은 srgb와 동일하나 전달 함수가 선형광(linear-light, 감마 인코딩 없음)이라는 점만 다릅니다.
- srgb-linear
-
srgb-linear [SRGB]
색상 공간은 숫자 3개 파라미터를 받으며,
각각 빨강, 초록, 파랑 컴포넌트입니다.
영역 내 색상은 세 컴포넌트 모두 [0, 1] 범위에 있습니다.
기준백색점은 D65입니다.
주요 특성은 다음과 같습니다:
x y 빨강 색도 0.640 0.330 초록 색도 0.300 0.600 파랑 색도 0.150 0.060 백색 색도 D65 전달 함수 단순히 입력값(cl=c), 아래 참고 백색 휘도 80.0 cd/m2 검정 휘도 0.20 cd/m2 이미지 상태 디스플레이 기준(display-referred) 백분율 R, G, B에 허용됨 백분율 기준 범위 R,G,B: 0% = 0.0, 100% = 1.0 cl
= c; c는 빨강, 초록, 파랑 컴포넌트입니다. cl은 해당 선형광 컴포넌트(동일값)입니다.
밴딩(banding) 현상을 방지하려면 더 높은 정밀도가 srgb-linear에 필요하며, srgb보다 더 높아야 합니다.
테스트
10.4. 미리 정의된 Display P3 색상 공간: display-p3 키워드
- display-p3
-
display-p3 [Display-P3] 색상 공간은 숫자 3개 파라미터를 받으며,
각각 빨강, 초록, 파랑 컴포넌트입니다.
영역 내 색상은 세 컴포넌트 모두 [0, 1] 범위에 있습니다.
[DCI-P3]와
동일한 주요 색도(primary chromaticities)를 사용하지만,
D65 기준백색점과 sRGB와 동일한 전달 곡선을 사용합니다.
최신 디스플레이, TV, 노트북과 스마트폰 화면은 display-p3 영역의 모든 색상 또는 거의 모든 색상을 표시할 수 있습니다.
주요 특성은 다음과 같습니다:
x y 빨강 색도 0.680 0.320 초록 색도 0.265 0.690 파랑 색도 0.150 0.060 백색 색도 D65 전달 함수 srgb와 동일 백색 휘도 80.0 cd/m2 검정 휘도 0.80 cd/m2 이미지 상태 디스플레이 기준(display-referred) 백분율 R, G, B에 허용됨 백분율 기준 범위 R,G,B: 0% = 0.0, 100% = 1.0 LCH에서 P3 색상 공간의 시각화. 원색(primary)과 2차색(secondary)을 표시. (표시된 색상은 sRGB로 표시되어 정확한 색상은 아님) 비교를 위해 sRGB의 원색과 2차색도 점선 원으로 함께 표시. P3 원색은 더 높은 채도를 가짐.
테스트
- predefined-005.html (실시간 테스트) (소스)
- predefined-006.html (실시간 테스트) (소스)
- display-p3-001.html (실시간 테스트) (소스)
- display-p3-002.html (실시간 테스트) (소스)
- display-p3-003.html (실시간 테스트) (소스)
- display-p3-004.html (실시간 테스트) (소스)
- display-p3-005.html (실시간 테스트) (소스)
- display-p3-006.html (실시간 테스트) (소스)
- 2d.color.space.p3.fillText.html (실시간 테스트) (소스)
- 2d.color.space.p3.fillText.shadow.html (실시간 테스트) (소스)
- 2d.color.space.p3.strokeText.html (실시간 테스트) (소스)
- 2d.color.space.p3.to.p3.html (실시간 테스트) (소스)
- 2d.color.space.p3.to.srgb.html (실시간 테스트) (소스)
- 2d.color.space.p3.toBlob.p3.canvas.html (실시간 테스트) (소스)
- 2d.color.space.p3.toBlob.with.putImageData.html (실시간 테스트) (소스)
- 2d.color.space.p3.toDataURL.jpeg.p3.canvas.html (실시간 테스트) (소스)
- 2d.color.space.p3.toDataURL.p3.canvas.html (실시간 테스트) (소스)
- 2d.color.space.p3.toDataURL.with.putImageData.html (실시간 테스트) (소스)
10.5. 미리 정의된 A98 RGB 색상 공간: a98-rgb 키워드
- a98-rgb
-
a98-rgb 색상 공간은 숫자 3개 파라미터를 받으며,
각각 빨강, 초록, 파랑 컴포넌트입니다.
영역 내 색상은 세 컴포넌트 모두 [0, 1] 범위에 있습니다.
전달 곡선은 감마 함수이며, 1/2.2와 거의 같으나 정확히 일치하지는 않습니다.
주요 특성은 다음과 같습니다:
x y 빨강 색도 0.6400 0.3300 초록 색도 0.2100 0.7100 파랑 색도 0.1500 0.0600 백색 색도 D65 전달 함수 256/563 백색 휘도 160.0 cd/m2 검정 휘도 0.5557 cd/m2 이미지 상태 디스플레이 기준(display-referred) 백분율 R, G, B에 허용됨 백분율 기준 범위 R,G,B: 0% = 0.0, 100% = 1.0 LCH에서 A98 색상 공간의 시각화. 원색(primary)과 2차색(secondary)을 표시. (표시된 색상은 sRGB로 표시되어 정확한 색상은 아님) 비교를 위해 sRGB의 원색과 2차색도 점선 원으로 함께 표시. a98 원색은 더 높은 채도를 가짐, 특히 노랑, 초록, 시안 계열에서 두드러짐.
테스트
10.6. 미리 정의된 ProPhoto RGB 색상 공간: prophoto-rgb 키워드
- prophoto-rgb
-
prophoto-rgb 색상 공간은 숫자 3개 파라미터를 받으며,
각각 빨강, 초록, 파랑 컴포넌트입니다.
영역 내 색상은 세 컴포넌트 모두 [0, 1] 범위에 있습니다.
전달 곡선은
감마 함수(지수 1/1.8)이며,
검정 근처에서는 선형 구간이 있습니다.
기준백색점은 D50로, CIE Lab과 동일합니다. 따라서,
CIE Lab 변환 시 색상 적응 변환 단계가 필요 없습니다.
ProPhoto RGB 공간은 초포화(hyper-saturated)로, 실제로 구현 불가능한 원색(primary)을 사용합니다. 넓은 색상 영역을 허용하고, 특히 톤 조정 시 색상 변화(hue shift)를 최소화하기 위해 이런 선택이 이루어졌습니다. 디지털 사진에서 원본 이미지의 넓은 색역 보관(archival)용으로 자주 쓰이는 색상 공간입니다. prophoto-rgb 색상 공간을 사용하면 CSS에서 해당 RGB값을 가진 이미지와 정확히 일치하는 색상을 지정할 수 있습니다.
ProPhoto RGB 공간은 원래 코닥(Kodak)에서 개발되었으며, [Wolfe]에 설명되어 있습니다. ISO에서 [ROMM],[ROMM-RGB]로 표준화되었습니다.
백색 휘도(white luminance)는 범위로 주어지며, 플레어(화면 반사)로 인해 검정 휘도(black luminance)는 전체의 0.5%~1.0%입니다.
주요 특성은 다음과 같습니다:
x y 빨강 색도 0.734699 0.265301 초록 색도 0.159597 0.840403 파랑 색도 0.036598 0.000105 백색 색도 D50 전달 함수 아래 참고 백색 휘도 160.0~640.0 cd/m2 검정 휘도 본문 참고 이미지 상태 디스플레이 기준(display-referred) 백분율 R, G, B에 허용됨 백분율 기준 범위 R,G,B: 0% = 0.0, 100% = 1.0 const E= 16 / 512 ; let sign= c< 0 ? - 1 : 1 ; let abs= Math. abs( c); if ( abs<= E) { cl= c/ 16 ; } else { cl= sign* Math. pow( c, 1.8 ); } c는 감마 인코딩된 빨강, 초록, 파랑 컴포넌트입니다. cl은 해당 선형광(linear-light) 컴포넌트입니다.
LCH에서 prophoto-rgb 색상 공간의 시각화. 원색(primary)과 2차색(secondary)을 표시. (표시된 색상은 sRGB로 표시되어 정확한 색상은 아님) 비교를 위해 sRGB의 원색과 2차색도 점선 원으로 함께 표시. prophoto-rgb 원색과 2차색은 훨씬 높은 채도를 가지나, 이 초광색역의 많은 부분은 물리적으로 실현 불가능한 색상입니다.
테스트
10.7. 미리 정의된 ITU-R BT.2020-2 색상 공간: rec2020 키워드
- rec2020
-
rec2020 [Rec.2020]
색상 공간은 숫자 3개 파라미터를 받으며,
각각 빨강, 초록, 파랑 컴포넌트입니다.
영역 내 색상은 세 컴포넌트 모두 [0, 1] 범위에 있습니다.
(영상 용어로 "full-range")
ITU Reference 2020은
UHD, 4K, 8K TV에 사용됩니다.
원색(primary)은 물리적으로 실현 가능하지만, 실제로 구현하기는 어렵고, 스펙트럼 경계(spectral locus) 가까이에 위치합니다.
현재 디스플레이는 rec2020의 전체 영역을 구현할 수 없으며, 앞으로 기술 발전에 따라 점차 구현 범위가 넓어질 것으로 예상됩니다.
주요 특성은 다음과 같습니다:
x y 빨강 색도 0.708 0.292 초록 색도 0.170 0.797 파랑 색도 0.131 0.046 백색 색도 D65 전달 함수 아래 참고, [Rec.2020] 표 4에서 발췌 이미지 상태 디스플레이 기준(display-referred) 백분율 R, G, B에 허용됨 백분율 기준 범위 R,G,B: 0% = 0.0, 100% = 1.0 const α= 1.09929682680944 ; const β= 0.018053968510807 ; let sign= c< 0 ? - 1 : 1 ; let abs= Math. abs( c); if ( abs< β* 4.5 ) { cl= c/ 4.5 ; } else { cl= sign* ( Math. pow(( abs+ α- 1 ) / α, 1 / 0.45 )); } c는 감마 인코딩된 빨강, 초록, 파랑 컴포넌트입니다. cl은 해당 선형광(linear-light) 컴포넌트입니다.
LCH에서 rec2020 색상 공간의 시각화. 원색(primary)과 2차색(secondary)을 표시. (표시된 색상은 sRGB로 표시되어 정확한 색상은 아님) 비교를 위해 sRGB의 원색과 2차색도 점선 원으로 함께 표시. rec2020 원색은 훨씬 높은 채도를 가짐.
테스트
10.8. 미리 정의된 CIE XYZ 색상 공간: xyz-d50, xyz-d65, xyz 키워드
- xyz-d50, xyz-d65, xyz
-
xyz 색상
공간은 숫자 3개 파라미터를 받으며,
각각 X, Y, Z 값을 의미합니다.
CIE XYZ [COLORIMETRY] 색상 공간을 나타내며,
확산 백색(diffuse white)의 휘도(Y)가 1.0이
되도록 스케일링됩니다.
필요하다면 기준백색점(reference white)에 맞게 색상 적응이 이루어집니다.
xyz-d50의 기준백색점은 D50이고, xyz-d65 및 xyz는 D65입니다.
1.0/100%를 초과하는 값도 허용되며 클램핑하지 않아야 합니다. Y 값이 1.0을 넘으면 확산 백색보다 더 밝은 색상을 나타냅니다. 0/0% 미만 값은 드물지만 색상 적응(chromatic adaptation) 결과로 나타날 수 있으며, 역시 클램핑하지 않아야 합니다.
주요 특성은 다음과 같습니다:
백분율 X,Y,Z에 허용됨 백분율 기준 범위 X,Y,Z: 0% = 0.0, 100% = 1.0
테스트
- predefined-016.html (실시간 테스트) (소스)
- xyz-001.html (실시간 테스트) (소스)
- xyz-002.html (실시간 테스트) (소스)
- xyz-003.html (실시간 테스트) (소스)
- xyz-004.html (실시간 테스트) (소스)
- xyz-005.html (실시간 테스트) (소스)
- xyz-d50-001.html (실시간 테스트) (소스)
- xyz-d50-002.html (실시간 테스트) (소스)
- xyz-d50-003.html (실시간 테스트) (소스)
- xyz-d50-004.html (실시간 테스트) (소스)
- xyz-d50-005.html (실시간 테스트) (소스)
- xyz-d65-001.html (실시간 테스트) (소스)
- xyz-d65-002.html (실시간 테스트) (소스)
- xyz-d65-003.html (실시간 테스트) (소스)
- xyz-d65-004.html (실시간 테스트) (소스)
- xyz-d65-005.html (실시간 테스트) (소스)
- color-valid.html (실시간 테스트) (소스)
10.9. 미리 정의된 색상 공간을 Lab 또는 Oklab으로 변환
모든 미리 정의된 RGB 색상 공간에서 Lab으로 변환하려면 여러 단계를 거쳐야 하며, 실제로 첫 단계만 비선형이고 나머지는 선형 계산이므로 통합할 수 있습니다.
- 감마 인코딩된 RGB를 선형광 RGB로 변환(감마 인코딩 해제)
- 선형 RGB를 CIE XYZ로 변환
- 필요하다면 D65 기준백색점(sRGB, display-p3, a98-rgb 및 rec2020에서 사용)를 Lab에서 사용하는 D50 기준백색점으로 선형 Bradford 변환. prophoto-rgb는 이미 D50 기준백색점임.
- D50 적응된 XYZ를 Lab으로 변환
Oklab으로 변환도 유사하며, 색상 적응 단계는 prophoto-rgb에만 필요합니다.
- 감마 인코딩된 RGB를 선형광 RGB로 변환(감마 인코딩 해제)
- 선형 RGB를 CIE XYZ로 변환
- 필요하다면 D50 기준백색점(prophoto-rgb에서 사용)을 Oklab에서 사용하는 D65 기준백색점으로 선형 Bradford 변환.
- D65 적응된 XYZ를 Oklab으로 변환
이 변환에 대한 샘플 JavaScript 코드는 § 18 색상 변환 샘플 코드에 있습니다.
10.10. Lab 또는 Oklab을 미리 정의된 RGB 색상 공간으로 변환
Lab에서 display-p3나 rec2020과 같은 미리 정의된 공간으로 변환도 여러 단계를 거쳐야 하며, 실제로 마지막 단계만 비선형이고 나머지는 선형 계산이므로 통합할 수 있습니다.
- Lab을 (D50 적응된) XYZ로 변환
- 필요하다면 Lab에서 사용하는 D50 기준백색점을 sRGB 및 대부분의 다른 RGB 공간에서 사용하는 D65 기준백색점으로 선형 Bradford 변환. prophoto-rgb는 이 단계가 필요 없음.
- (D65 적응된) CIE XYZ를 선형 RGB로 변환
- 선형광 RGB를 RGB로 변환(감마 인코딩)
Oklab에서 변환도 유사하며, 색상 적응 단계는 prophoto-rgb에만 필요합니다.
- Oklab을 (D65 적응된) XYZ로 변환
- 필요하다면 Oklab에서 사용하는 D65 기준백색점을 D50 기준백색점(prophoto-rgb에서 사용)으로 선형 Bradford 변환.
- (D65 적응된) CIE XYZ를 선형 RGB로 변환
- 선형광 RGB를 RGB로 변환(감마 인코딩)
이 변환에 대한 샘플 JavaScript 코드는 § 18 색상 변환 샘플 코드에 있습니다.
구현체에서는 소스와 대상 색상 영역(gamut) 내의 색상에 대해 결과가 동일하다면 (예: ICC 프로파일의 상대 컬러리메트릭 렌더링 의도 사용 등) 다른 방식으로 이 단계를 구현해도 됩니다.
10.11. 미리 정의된 RGB 색상 공간 간 변환
한 미리 정의된 RGB 색상 공간에서 다른 공간으로 변환하려면 여러 단계를 거쳐야 하며, 기준백색점이 다를 때만 필요한 단계가 하나 있습니다. src에서 dest로 변환하려면:
- 감마 인코딩된 srcRGB를 선형광 srcRGB로 변환(감마 인코딩 해제)
- 선형 srcRGB를 CIE XYZ로 변환
- src와 dest의 기준백색점이 다르면, XYZ 값을 srcWhite에서 destWhite로 선형 Bradford 변환.
- CIE XYZ를 선형 destRGB로 변환
- 선형광 destRGB를 destRGB로 변환(감마 인코딩)
미리 정의된 RGB 색상 공간 간 변환에 대한 샘플 JavaScript 코드는 § 18 색상 변환 샘플 코드에 있습니다.
10.12. 간단한 알파 합성
그리기 시, 구현체는 Compositing and Blending Level 1 [Compositing]의 Section 5.1 Simple alpha compositing의 규칙을 따라 알파를 처리해야 합니다.
11. 색상 변환
테스트
이 절은 이후에 사용될 알고리즘을 제공하며, 테스트가 필요하지 않습니다.
색상은 한 색상 공간에서 다른 색상 공간으로 변환될 수 있으며, 영역 매핑(gamut mapping)이 없고 각 색상 공간이 영역 밖(out of gamut) 색상을 표현할 수 있다면, (RGB 공간의 경우 변환 함수가 확장된 범위에 대해 정의되어 있음을 의미) (수치적 정밀도와 반올림 오차를 제외하고) 변환 전후 색상은 시각적으로 동일하며 동일한 색상 감각을 나타냅니다.
소스 색상 공간 src의 백색점 src-white에서 색상 col1을 대상 색상 공간 dest의 백색점 dest-white에서 색상 col2로 변환하려면:
- 만약 src가 원통형 극좌표 색상 표현 방식이면, 먼저 col1을 해당하는 직교 좌표 색상 표현 방식으로 변환하고, 이 값을 새로운 col1로 둡니다. 누락된 컴포넌트가 있다면 0으로 대체합니다.
- src가 선형광 표현이 아니면, 선형광으로 변환(감마 인코딩 해제)하고, 이 값을 새로운 col1로 둡니다.
- col1을 해당 백색점 src-white의 CIE XYZ로 변환하여 xyz로 둡니다.
- dest-white와 src-white가 다르면, xyz를 선형 Bradford 색상 적응 변환으로 dest-white에 맞게 적응시키고, 이 값을 새로운 xyz로 둡니다.
- dest가 원통형 극좌표 색상 표현 방식이면, dest-rect를 해당하는 직교 좌표 색상 표현 방식으로 둡니다. 아니면 dest-rect를 dest로 둡니다.
- xyz를 dest로 변환 후, 변환 함수(감마 인코딩 등)를 적용하여 col2를 생성합니다.
- dest가 디스플레이 등 물리적 출력 색상 공간이면, col2는 CSS 영역 매핑을 거쳐 표시 가능해야 합니다.
- dest-rect와 dest가 다르면, 즉 dest가 원통형 극좌표 색상 표현 방식이면, dest-rect에서 dest로 변환하고, 그 값을 col2로 둡니다. 이 과정에서 누락된 컴포넌트가 생길 수 있습니다.
12. 색상 보간
색상 보간은 그라데이션, 합성, 필터, 트랜지션, 애니메이션, 색상 혼합 및 색상 변경 함수에서 발생합니다.
두 <color> 값 사이의 보간은 다음 단계를 거칩니다:
- 두 색상에서 유사 컴포넌트를 확인하여 전달됨(carried forward)으로 처리
- 두 색상을 아래에서 보간 색상 공간이라 부르는 특정 색상 공간으로 변환 한쪽 또는 양쪽 색상이 이미 보간 색상 공간에 있으면, 변환 과정에서 무효 컴포넌트는 누락값으로 바뀜
- (필요시) 변환된 색상에서 전달됨 값을 다시 삽입
- (필요시) 선택된 <hue-interpolation-method>에 따라 hue 보정
- 색상 컴포넌트를 프리멀티플라이드 형태로 변환
- 색상값의 각 컴포넌트를 별도로 선형 보간
- 프리멀티플라이드 해제
currentcolor로 보간하거나, 그 반대도 가능합니다. 이때 사용되는 수치값은 사용 값(used value)입니다.
12.1. 보간용 색상 공간
CSS의 다양한 기능은 색상 보간에 의존합니다.
색상을 혼합하거나 조합하는 방식은 사용되는 보간 색상 공간에 따라 결과가 달라집니다. 따라서 각 보간 사례마다 적합한 색상 공간이 다를 수 있습니다.
-
물리적으로 두 색광을 혼합한 결과가 필요한 경우, CIE XYZ나 srgb-linear 색상 공간이 적합합니다. 이들은 광 세기에 대해 선형적입니다.
-
색상이 시각적으로 고르게 분포되어야 할 경우(예: 그라데이션), Oklab 색상 공간(및 Lab)은 시각적으로 균등하도록 설계되었습니다.
-
색상 혼합 시 회색화(graying out)를 피하고, 즉 전환 내내 채도를 극대화하려면, OKLCh(및 LCH)가 적합합니다.
-
마지막으로 레거시 웹 콘텐츠와의 호환성이 가장 중요할 수 있습니다. sRGB 색상 공간은 선형광도 아니고 시각적으로 균등하지 않지만, 이 경우 선택됩니다. 다만 결과는(너무 어둡거나 회색빛이 도는 혼합 등) 품질이 떨어집니다.
이러한 기능을 통틀어 호스트 문법(host syntax)이라 부릅니다.
호스트 문법이 보간 색상 공간을 지정할 수 있도록 이 명세는 color-interpolation-method 생산식을 제공합니다. 이 명세 자체에서는 사용하지 않으며, 다른 명세에서 사용할 수 있도록 노출합니다; 예: CSS Images 4 § 3.1 Linear Gradients: the linear-gradient() 표기법 참조.
호스트 문법은 각 경우에 기본 보간 색상 공간이 무엇인지를 정의해야 하며, 저자가 이 기본값을 재정의할 수 있는 문법도 제공하는 것이 바람직합니다. 해당 문법이 속성 값의 일부라면 아래 정의된 color-interpolation-method 생산식을 사용해야 하며, CSS 전반에 걸쳐 일관성을 보장합니다. 색상 보간 방법에 대한 추가 커스터마이징이 있다면 CSS 전체에 자동으로 반영될 수 있습니다.
<color-space> = <rectangular-color-space> | <polar-color-space> <rectangular-color-space> = srgb | srgb-linear | display-p3 | a98-rgb | prophoto-rgb | rec2020 | lab | oklab | xyz | xyz-d50 | xyz-d65 <polar-color-space> = hsl | hwb | lch | oklch <hue-interpolation-method> =[ shorter | longer | increasing | decreasing] hue <color-interpolation-method> = in[ <rectangular-color-space> | <polar-color-space> <hue-interpolation-method>?]
<rectangular-color-space>와 <polar-color-space> 정의에 나오는 키워드는 각 색상 공간을 의미하며, CSS에서는 같은 이름의 함수 표기법으로, 또는 (함수가 없으면) <ident>로 color() 함수에서 표현됩니다.
테스트
- gradients-with-transparent.html (실시간 테스트) (소스)
- gradient-eval-001.html (실시간 테스트) (소스)
- gradient-eval-002.html (실시간 테스트) (소스)
- gradient-eval-003.html (실시간 테스트) (소스)
- gradient-eval-004.html (실시간 테스트) (소스)
- gradient-eval-005.html (실시간 테스트) (소스)
- gradient-eval-006.html (실시간 테스트) (소스)
- gradient-eval-007.html (실시간 테스트) (소스)
- gradient-eval-008.html (실시간 테스트) (소스)
- gradient-eval-009.html (실시간 테스트) (소스)
- gradient-none-interpolation.html (실시간 테스트) (소스)
- legacy-color-gradient.html (실시간 테스트) (소스)
- oklab-gradient.html (실시간 테스트) (소스)
- srgb-gradient.html (실시간 테스트) (소스)
- srgb-linear-gradient.html (실시간 테스트) (소스)
- xyz-gradient.html (실시간 테스트) (소스)
- gradient-interpolation-method-valid.html (실시간 테스트) (소스)
- gradient-interpolation-method-invalid.html (실시간 테스트) (소스)
- gradient-interpolation-method-computed.html (실시간 테스트) (소스)
호스트 문법에서 색상 보간이 어떤 색상 공간에서 이루어져야 하는지 정의하지 않으면, 기본값은 Oklab입니다.
저자가 특정 상황에서 sRGB로 보간하고 싶다면, 원하는 그라데이션 등에서 sRGB를 보간 색상 공간으로 명시적으로 지정해 구 방식으로 opt-in 할 수 있습니다.
보간할 색상이 보간 색상 공간의 영역을 벗어나면, 그 공간으로 변환된 뒤에는 값이 범위 밖(out of range)이 됩니다.
이 값들은 클리핑하지 않고, 그대로 보간됩니다.
12.2. 누락된 컴포넌트와의 색상 보간
두 색상을 보간 색상 공간으로 변환하는 과정에서, 모든 누락된 컴포넌트는 값 0으로 대체됩니다.
따라서 두 색상을 보간하는 첫 단계는, 입력 색상에서 누락된 컴포넌트를 분류하고, 이를 보간 색상 공간의 컴포넌트와 비교하는 것입니다. 만약 유사 컴포넌트 중 누락된 컴포넌트가 발견되면, 이들은 전달됨(carried forward) 처리되어 변환된 색상에 프리멀티플라이드 및 선형 보간 전에 재삽입됩니다.
유사 컴포넌트는 다음과 같습니다:
카테고리 | 컴포넌트 |
---|---|
빨강 | r,x |
초록 | g,y |
파랑 | b,z |
명도 | L |
채도/색도 | C, S |
색상각 | H |
반대축 a | a |
반대축 b | b |
알파 | alpha |
참고: 이 분류에서 XYZ 공간은 초포화 RGB 공간으로 간주합니다. 또한 Saturation은 명도에 종속되어 있지만, 여기서는 Chroma와 같은 카테고리에 포함됩니다. HWB의 Whiteness와 Blackness 컴포넌트는 다른 색상 공간에는 유사 컴포넌트가 없습니다.
lch ( 50 % 0.02 none) color ( display-p30.7 0.5 none)
변환 결과는 다음과 같습니다
oklch ( 56.897 % 0.0001 0 ) oklch ( 63.612 % 0.1522 78.748 )
전달된 누락된 컴포넌트가 재삽입되면, 실제로 보간되는 두 색상은 다음과 같습니다:
oklch ( 56.897 % 0.0001 none) oklch ( 63.612 % 0.1522 78.748 )
전달된 누락 컴포넌트가 있는 색상과 그 컴포넌트가 없는 색상을 보간할 때, 누락 컴포넌트는 다른 색상의 컴포넌트 값을 사용합니다.
따라서, 전달 단계는 무효 컴포넌트 처리보다 먼저 수행되어야 합니다.
oklch ( 78.3 % 0.108 326.5 ) oklch ( 39.2 % 0.4 none)
실제로 보간되는 색상은
oklch ( 78.3 % 0.108 326.5 ) oklch ( 39.2 % 0.4 326.5 )
아래와 같이 되는 것이 아니라
oklch ( 78.3 % 0.108 326.5 ) oklch ( 39.2 % 0.4 0 )
전달된 누락 컴포넌트가 알파라면, 색상은 변환 과정에서 나온 0이 아니라, 전달된 알파 값으로 프리멀티플라이드 처리해야 합니다.
oklch ( 0.783 0.108 326.5 /0.5 ) oklch ( 0.392 0.4 0 / none)
실제로 보간되는 색상은
oklch ( 78.3 % 0.108 326.5 /0.5 ) oklch ( 39.2 % 0.4 0 /0.5 )
이 경우 프리멀티플라이드 OKLCh 값은 [0.3915, 0.054, 326] 및 [0.196, 0.2, 0]입니다.
두 색상 모두 해당 컴포넌트가 누락된 경우, 보간 결과 색상도 그 컴포넌트가 누락됩니다.
12.3. 알파와 함께 보간하기
보간할 색상이 완전히 불투명하지 않으면, 먼저 다음과 같이 프리멀티플라이드 처리합니다:
-
알파 값이 none이면, 프리멀티플라이드 값은 원래 값과 동일합니다. 그렇지 않으면,
-
컴포넌트 값 중 none이 있으면, 프리멀티플라이드 값도 none입니다.
-
직교 좌표 색상 시스템에서는 모든 컴포넌트 값을 알파값으로 곱합니다.
-
원통형 극좌표 색상 시스템에서는 색상각(Hue)은 곱하지 않지만, 나머지 두 축은 곱합니다.
프리멀티플라이드 색상 값에서 원래 색상 값을 얻으려면,
-
보간된 알파 값이 0 또는 none이면, 원래 값은 프리멀티플라이드 값과 동일합니다. 그렇지 않으면,
-
컴포넌트 값 중 none이 있으면, 원래 값도 none입니다.
-
그 외에는, 프리멀티플라이드된 각 컴포넌트를 보간된 알파 값으로 나눕니다.
프리멀티플라이드 알파가 왜 유용한가?
프리멀티플라이드 표현으로 색상 보간하면, 비프리멀티플라이드 표현보다 더 보기 좋은 전환이 만들어지는 경향이 있으며, 특히 완전히 불투명한 색상에서 완전히 투명한 색상으로 전환할 때 그렇습니다.
투명도 또는 색상이 고정된 채로 전환할 때는
(예:
(불투명 빨강)
와
(불투명 파랑),
또는
(불투명 빨강)
와
(투명 빨강))
프리멀티플라이드 방식과 비프리멀티플라이드 방식 모두 결과가 동일합니다.
차이는 색상과 투명도가 둘 다 다를 때만 발생합니다.
linear-gradient ( 90 deg , red, transparent, blue)
프리멀티플라이드 색상에서는, "transparent"로 전환할 때 항상 보기 좋습니다:
반면, 비프리멀티플라이드 공간에서 잘못 전환하면, 그라데이션 중앙이 눈에 띄게 회색빛이 되는데, "transparent"가 실제로는 rgba(0,0,0,0), 즉 투명 검정의 약어여서 빨강은 투명해질수록 검정으로 전환되고, 파랑도 마찬가지입니다:
이 색상의 선형 보간 중간값은 [23.4% 10.2% 38.8%]이며, 알파 값이 0.5일 때, 프리멀티플라이드 해제하면 rgb(46.8% 20.4% 77.6% / 0.5) 가 됩니다.
선형 보간의 중간값은 [29.4365% 25.776 3.554]이며, 알파 값이 0.5일 때, 프리멀티플라이드 해제하면 lab(58.873% 51.552 7.108) / 0.5) 가 됩니다.
선형 보간의 중간값(기본값인 shorter hue arc 기준)은 [29.4365% 40.563 31.82]이며, 알파 값이 0.5일 때, 프리멀티플라이드 해제하면 lch(58.873% 81.126 31.82) / 0.5) 가 됩니다.
알파 프리멀티플라이드 및 해제에 대한 샘플 JavaScript 코드는 § 18 색상 변환 샘플 코드에 있습니다.
12.4. 색상각 보간
색상각(hue angle)이 있는 색상 함수(LCH, HSL, HWB 등)는 보간 방법이 여러 가지입니다. 360°를 초과하는 호(arc)는 거의 바람직하지 않으므로, 보간 전에 색상각을 조정해 각 컴포넌트의 보간이 360° 미만, 보통 180° 미만에서 이루어지도록 합니다.
호스트 문법에서 색상각 보간 알고리즘을 다음 중 하나로 지정할 수 있습니다 (아래 각도는 도 단위로 설명하지만, 표현 방식에 관계없이 논리는 동일합니다). 색상각 보간 전략 지정은 이미 <color-interpolation-method> 문법에서 <hue-interpolation-method> 토큰으로 지원됩니다.
별도로 지정하지 않으면, 호스트 문법에서 특정 색상각 보간 알고리즘을 선택하지 않은 경우 기본값은 shorter입니다.
참고: 참고로, 보간 색상이 지정된 보간 색상 공간에 이미 있지 않다면, 변환 과정에서 무효 컴포넌트가 누락 컴포넌트로 바뀝니다.
12.4.1. shorter
색상각은 시작·종료 색상 사이의 짧은(shorter) 호를 따라 보간됩니다.
각도는 θ₂ - θ₁ ∈ [-180, 180]이 되도록 조정합니다. 의사자바스크립트:
if( θ₂ - θ₁ >180 ) { θ₁ +=360 ; } else if( θ₂ - θ₁ <-180 ) { θ₂ +=360 ; }
12.4.2. longer
색상각은 시작·종료 색상 사이의 긴(longer) 호를 따라 보간됩니다.
각도는 θ₂ - θ₁ ∈ {(-360, -180], [180, 360)}이 되도록 조정합니다. 의사자바스크립트:
if( 0 < θ₂ - θ₁ <180 ) { θ₁ +=360 ; } else if( -180 < θ₂ - θ₁ <=0 ) { θ₂ +=360 ; }
12.4.3. increasing
색상각은 첫 번째 색상에서 두 번째 색상으로 진행할 때 항상 증가(increasing) 방향으로 보간됩니다. 각도가 360이 되면 0으로 리셋 후 계속 증가합니다.
두 각도 차이에 따라 결과는 shorter 또는 longer와 같을 수 있습니다. 하지만 한쪽 색상각이 애니메이션될 때, 각도 차가 180도를 지나면 보간 호가 뒤집히지 않습니다.
만약 두 번째 색의 hue가 oklch(0.7 0.1 230)로 애니메이션되면, 중간값은 (30 + 230) * 0.5 = 130도가 되어, 같은 증가 방향으로 보간되어, oklch(0.6 0.1 130) (다른 녹색)입니다. 중간에 색상각 호가 뒤집히지 않습니다.
각도는 θ₂ - θ₁ ∈ [0, 360)이 되도록 조정합니다. 의사자바스크립트:
if( θ₂ < θ₁) { θ₂ +=360 ; }
12.4.4. decreasing
색상각은 첫 번째 색상에서 두 번째 색상으로 진행할 때 항상 감소(decreasing) 방향으로 보간됩니다. 각도가 0이 되면 360으로 리셋 후 계속 감소합니다.
두 각도 차이에 따라 결과는 shorter 또는 longer와 같을 수 있습니다. 하지만 한쪽 색상각이 애니메이션될 때, 각도 차가 180도를 지나면 보간 호가 뒤집히지 않습니다.
만약 두 번째 색의 hue가 oklch(0.7 0.1 230)로 애니메이션되면, 중간값은 (30 + 360 + 230) * 0.5 = 310도이며, 같은 감소 방향으로 보간되어, oklch(0.6 0.1 310) (다른 보라색)입니다. 중간에 색상각 호가 뒤집히지 않습니다.
각도는 θ₂ - θ₁ ∈ (-360, 0]이 되도록 조정합니다. 의사자바스크립트:
if( θ₁ < θ₂) { θ₁ +=360 ; }
13. 색역 매핑
13.1. 색역 매핑 소개
참고: 이 절은 문서의 다른 곳에 명시된 구체적 요구사항에 대한 중요한 배경을 제공합니다.
이 절은 규범적이지 않습니다(비규범)
테스트
이 절은 비규범적이므로, 테스트가 필요하지 않습니다.
원본 색상 공간에 있는 색상이 더 작은 색역을 가진 다른, 대상 색상 공간으로 변환될 때 일부 색상은 대상 색역을 벗어나게 됩니다.
중간 색상 계산에서는 이런 영역 밖 값이 유지됩니다. 그러나, 대상이 디스플레이 장치(화면이나 프린터)인 경우 영역 밖 값은 반드시 영역 내 색상으로 변환되어야 합니다.
색역 매핑은 시각적으로 거슬리지 않는 변화를 최소화하면서 영역 내 색상을 찾는 과정입니다.
13.1.1. 클리핑
가장 단순하고 가장 바람직하지 않은 방법은 컴포넌트 값을 디스플레이 가능한 범위로 단순히 클리핑하는 것입니다. 이는 세 원색(RGB 디스플레이 기준)의 비율을 바꿔 색상각(hue)이 변화합니다.
color ( srgb-linear 0.5 1 3 )
를
생각해 보겠습니다.
이 공간은 선형광 색상 공간이므로,
세 컴포넌트의 밝기를 비교할 수 있습니다.
파란색 광의 양은 초록색의 3배,
빨강 광은 초록색의 절반입니다.
빨강에 비해 파랑이 6배 많습니다.
OKLCh에서 이 색상은 hue 각도가 265.1°입니다.
이 색상을 sRGB에 맞게 클리핑하면,
가
됩니다.
파랑과 초록 광의 양이 같아집니다.
OKLCh에서 이 색상은 hue 각도가 196.1°가 되어,
총 69°의 큰 변화가 생깁니다.
13.1.2. 가장 가까운 색상(MINDE)
더 나은 방법은, 지각적으로 균등한 색상 공간에서, 가장 가까운 영역 내 색상(최소 ΔE 또는 MINDE)을 찾는 것입니다. 이 방식의 성공은 색역 매핑 색상 공간의 균등성 정도와 deltaE 함수의 예측 정확도에 달려 있습니다.
그러나 색역 매핑을 할 때 hue의 변화는 특히 거슬립니다; chroma의 변화는 좀 더 용인 가능하며, 명도의 작은 변화도 chroma 감소가 더 클 경우엔 받아들여질 수 있습니다. MINDE는 각 차원의 변화를 동등하게 취급하므로, 결과가 최적이 아닙니다.
13.1.3. 채도 축소
MINDE 알고리즘을 개선하려면, 지각적으로 균등하고 극좌표 색상 공간에서 hue는 고정하고, chroma를 줄여 색상이 색역 내로 들어오도록 매핑합니다.
color ( display-p3 1 1 0 )
)을
sRGB 디스플레이로 매핑합니다.
색역 매핑 색상 공간은 OKLCh입니다.
color ( display-p31 1 0 )
변환 결과는
color ( srgb1 1 -0.3463 )
즉,
color ( oklch0.96476 0.24503 110.23 )
chroma 컴포넌트를 점진적으로 줄여 결과 색상이 sRGB 색역 내(컴포넌트가 음수도 아니고 1 초과도 아닌) 에 들어올 때까지 반복하면, 색역 매핑된 색상이 얻어집니다.
color ( oklch0.96476 0.21094 110.23 )
즉,
color ( srgb0.99116 0.99733 0.00001 )
실제 구현에서는 선형 축소보다 더 빠르게 수렴할 수 있으며, 이진 탐색이나, 고정 hue·명도 선과 색역 경계의 기하학적 교차점 계산을 사용할 수 있습니다.
13.1.4. 과도한 채도 축소
또한 이 단순한 방법은 일부 색상(특히 매우 밝은 노랑, 시안 등)에서는 색역 경계의 상단이 얕거나 오히려 오목한 경우 최적 결과를 내지 못할 수 있습니다. 고정 명도 선이 색역 경계 바로 위를 스치면서 채도가 지나치게 낮아지는 경우가 생깁니다.
색상 공간의 선택은 색역 매핑된 색상의 만족도에 영향을 줍니다.
color ( display-p3 1 1 0
)은
CIE LCH 색상 공간에서 chroma를 점진적으로 줄입니다.
color ( display-p3 1 1 0
)은
OKLCh 색상 공간에서 chroma를 점진적으로 줄입니다.
13.1.5. 채도 축소와 국소 클리핑
단순 chroma 축소 알고리즘을 개선하려면: 각 단계마다, 현재 매핑된 색상과 클리핑된 버전 사이의 색상 차이를 계산합니다. 만약 현재 색상이 색역 경계 밖이지만 클리핑 버전과의 색상 차이가 지각 가능 최소 차이(just noticeable difference, JND) 임계값 이하면, 클리핑 버전 색상을 매핑 결과로 반환합니다. 실질적으로, 각 단계마다 MINDE 매핑을 수행하되 hue와 명도 변화가 아주 작고 눈에 띄지 않도록 제한합니다.
color ( display-p3 1 1 0
)은
CIE LCH 색상 공간에서 chroma를 점진적으로 줄이고,
국소 클리핑을 적용합니다.
color ( display-p3 1 1 0
)은
OKLCh 색상 공간에서 chroma를 점진적으로 줄이고,
국소 클리핑을 적용합니다.
13.1.6. 지각적 균등성의 일탈: 색상각 곡률
CIE LCH 색상 공간과 deltaE2000 거리 척도는 hue가 270°~330° 범위인 색상에서 색상각 변화(shift)가 크게 발생해 최적이 아닌 결과를 내는 것으로 알려져 있습니다.

OKLCh 색상 공간과 deltaEOK 거리 척도를 사용하면 모든 hue 각도에서 이 문제가 발생하지 않습니다.

13.2. CSS RGB 대상 색역 매핑
테스트
색상의 실제 값은 스크립트에 노출되지 않아 자동 테스트가 어렵습니다.
CSS 색역 매핑 알고리즘은 RGB 디스플레이의 영역을 벗어난(영역 밖) 개별 SDR(Standard Dynamic Range) CSS 색상에 적용되며, 해당 색상을 CSS 색역 매핑해야 할 때 사용됩니다.
상대 컬러리메트릭 렌더링 의도를 구현하며, 대상 영역 내의 색상은 변경되지 않습니다.
참고: 프린터 색역 등 최대 검정 레벨이 0보다 훨씬 높은 경우에는 각 흑·백 기준점에 맞춘 별도의 알고리즘이 필요하며, 채도가 줄어들 때 매우 밝거나 매우 어두운 색상은 명도 변화가 발생할 수 있습니다.
참고: 이 알고리즘은 개별 색상에 대한 것이며, 색상 이미지처럼 이웃 픽셀 간의 관계를 보존하고 디테일·질감 보존이 중요한 경우에는 지각적 렌더링 의도가 더 적합합니다. 그 경우에는 대상 색역 내의 색상도 변경될 수 있습니다.
CSS 색역 매핑은 OKLCh 색상 공간에서 이루어지며, 색상 차이 공식은 deltaEOK를 사용합니다. local-MINDE 개선이 적용됩니다.
명도 축에서 범위를 벗어난 색상은, 명도가 1.0 이상이면 대상 색상 공간에서 흰색, 명도가 0.0 이하이면 대상 색상 공간에서 검정이 반환됩니다.
이진 탐색(binary search) 구현에서는, 각 단계마다 현재 매핑된 색상과 클리핑된 버전의 deltaEOK를 계산합니다. 현재 색상이 영역 밖이지만 클리핑 버전과의 deltaEOK가 지각 가능 최소 차이(JND) 임계값보다 작으면, 클리핑 버전 색상을 매핑 결과로 반환합니다.
기하학적(geometric) 구현에서는, 교차점을 정확히 찾은 뒤, 명도 고정선에서 채도가 더 높은 쪽으로 투영(projection)하여 아래 중 하나에 도달할 때까지 진행합니다:
-
투영된 점과 그 점의 클리핑 버전 사이의 deltaEOK가 JND 1을 초과하거나
-
투영된 점의 chroma가 원래 색상의 chroma와 같아질 때(즉, 원래 색상을 넘어서 투영하지 않음)
그 후 클리핑된 색상을 매핑 결과로 반환합니다.
OKLCh 색상 공간에서 JND 1은 OKLCh 차이 0.02입니다.
참고: CIE Lab 색상 공간에서, 명도(L) 범위가 0~100이고 deltaE2000을 사용할 때, JND 1은 2입니다. Oklab과 OKLCh는 명도 범위가 0~1이므로, deltaEOK 기준 JND 1은 100배 더 작습니다.
13.2.1. Local MINDE 기반 이진 탐색 색역 매핑 알고리즘 예시(의사코드)
- 만약 destination이 색역 제한이 없는 경우(XYZ-D65, XYZ-D50, Lab, LCH, Oklab, OKLCh)라면, origin을 destination으로 변환해 그대로 반환
- origin_OKLCh에 origin을 origin color space에서 OKLCh 색상 공간으로 변환한 값을 저장
- origin_OKLCh의 명도가 100% 이상이면, `oklab(1 0 0 / origin.alpha)`를 destination으로 변환해 반환
- origin_OKLCh의 명도가 0% 이하이면, `oklab(0 0 0 / origin.alpha)`를 destination으로 변환해 반환
- inGamut(color) 함수는, 전달받은 색상이 destination의 색역 내에 있으면 true를 반환. HSL, HWB의 경우 sRGB 색역 내에 있으면 true.
- inGamut(origin_OKLCh)이 true면, origin_OKLCh를 destination으로 변환해 반환
- 그렇지 않으면, delta(one, two) 함수는 색상 one과 two의 deltaEOK를 반환
- JND를 0.02로 설정
- epsilon을 0.0001로 설정
- clip(color) 함수는 color를 destination으로 변환 후, 각 컴포넌트를 기준 범위로 클램핑해서 반환
- current를 origin_OKLCh로 설정
- clipped를 clip(current)로 설정
- E를 delta(clipped, current)로 설정
-
만약 E < JND라면
- clipped를 색역 매핑 결과로 반환
- min을 0으로 설정
- max를 origin_OKLCh의 chroma로 설정
- min_inGamut을 true로 설정(현재 min이 색역 내임을 표시)
-
while (max - min > epsilon) 아래 반복
- chroma를 (min + max) /2로 설정
- current의 chroma 컴포넌트를 chroma로 설정
- 만약 min_inGamut이 true이고 inGamut(current)이 true면, min을 chroma로 설정하고 반복 계속
-
그렇지 않으면 아래 실행:
- clipped를 clip(current)로 설정
- E를 delta(clipped, current)로 설정
-
만약 E < JND라면
- (JND - E < epsilon)면 clipped 반환
-
아니면,
- min_inGamut을 false로 설정
- min을 chroma로 설정
- 그 외에는 max를 chroma로 설정하고 반복 계속
- clipped를 색역 매핑 결과로 반환
14. <color> 값 해석하기
특정 속성에 대해 별도의 명시가 없는 한, 지정된 색상은 계산된(computed) 색상으로 해석된 후, 아래에 설명된 대로 사용된(used) 색상으로 추가 해석됩니다.
해석된 값(resolved value)은 <color>의 사용된 값입니다.
테스트
14.1. sRGB 값 해석하기
다음에 적용됩니다:
-
hwb() 값
다음에는 적용되지 않습니다:
-
color() 값 중 srgb 또는 srgb-linear 색상 공간을 사용하는 경우
sRGB 색상이 저자가 이름이 있는 색상 또는 시스템 색상으로 명시적으로 지정된 경우, 지정 값(declared value)은 해당 이름 또는 시스템 색상으로, ASCII 소문자로 변환됩니다. 계산 값과 사용 값은 해당하는 sRGB 색상이며, 명시된 알파 컴포넌트와 함께 ([0, 1] 범위로 클램핑 후) 알파가 지정되지 않으면 불투명으로 기본값 설정).
그 외에는, 지정 값, 계산 값, 사용 값은 해당하는 sRGB 색상이며, 명시된 알파 컴포넌트와 함께 ([0, 1] 범위로 클램핑 후) 알파가 지정되지 않으면 불투명으로 기본값 설정).
역사적 이유로, sRGB 색상에서 calc()가 단일 값으로 해석될 때, 지정 값은 "calc(" ")" 래퍼 없이 직렬화됩니다.
또한 역사적 이유로, calc()가 단일 값으로 단순화될 때, 색상 값은 [0.0, 255.0]로 클램핑됩니다.
이 클램핑은 Infinity, -Infinity, NaN과 같은 값도 처리하며, 각각 255, 0, 0으로 클램핑합니다.
테스트
14.2. Lab 및 LCH 값 해석하기
지정 값, 계산 값, 사용 값은 해당하는 CIE Lab 또는 LCH 색상이며 (L, C, H 클램핑 후) 지정된 알파 컴포넌트와 함께 (<number>로, <percentage>가 아님; 알파 미지정 시 기본값은 불투명입니다).
14.3. Oklab 및 OKLCh 값 해석하기
이 내용은 oklab() 및 oklch() 값에 적용됩니다.
지정 값, 계산 값, 사용 값은 해당하는 Oklab 또는 OKLCh 색상이며 (L, C, H 클램핑 후) 지정된 알파 컴포넌트와 함께 (<number>로, <percentage>가 아님; 알파 미지정 시 기본값은 불투명입니다).
14.4. color() 함수 값 해석하기
지정 값, 계산 값, 사용 값은 지정된 색상 공간의 색상이며, 지정된 알파 컴포넌트와 함께 (<number>로, <percentage>가 아님; 알파 미지정 시 기본값은 불투명입니다).
예를 들어 아래의 계산 값은
color ( display-p30.823 0.6554 0.2537 /1 )
다음과 같습니다:
color ( display-p30.823 0.6554 0.2537 )
xyz 색상 공간으로 지정된 색상은 xyz-d65 색상 공간의 별칭이므로, 계산 값과 사용 값은 xyz-d65 색상 공간에 있습니다.
14.5. 기타 색상 해석하기
이 내용은 시스템 색상(<deprecated-color> 포함), transparent, 그리고 currentcolor에 적용됩니다.
각 <system-color> 키워드와 <deprecated-color> 키워드의 지정 값은 그 자체입니다. 계산 값은 해당 색상 공간의 색상입니다. 단, 이런 색상은 '강제 색상 모드(forced colors mode)'에 의해 변경되어서는 안 됩니다.
< button style = "color: ButtonText; background: ButtonFace" ></ button >
color 속성의 지정 값은 "ButtonText" 계산 값은 예를 들어 rgb(0, 0, 0)일 수 있습니다.
transparent의 지정 값은 "transparent"이고, 계산 값과 사용 값은 투명 검정(transparent black)입니다.
currentcolor 키워드는 그 자체로 계산됩니다.
color 속성에서는, currentcolor의 사용 값은 상속된 값으로 해석됩니다. 다른 속성에서는, 사용 값이 같은 요소의 color 속성의 사용 값입니다.
참고: 즉 currentcolor 값이 상속될 경우, 키워드로 상속되며, color 속성 값 자체로 상속되는 것이 아니므로, 자식 요소는 자신의 color 속성으로 값을 해석합니다.
< div > < p > Assume this example text is long enough to wrap on multiple lines.</ p > </ div >
그리고 아래 css:
div{ color : forestgreen; text-shadow : currentColor; } p{ color : mediumseagreen; } p::firstline{ color : yellowgreen; }
첫 번째 줄 fragment의 text-shadow 속성에 대한 사용 값은 yellowgreen입니다.
테스트
15. <color> 값 직렬화하기
이 절은 CSS Object Model의 CSS 값 직렬화 중 <color> 값 직렬화와 관련된 부분을 갱신·대체합니다.
이 절에서 명세에 사용되는 문자열과 해당 문자들은 다음과 같습니다.
문자열 | 문자(들) |
---|---|
" " | U+0020 SPACE |
"#" | U+0023 NUMBER SIGN |
"," | U+002C COMMA |
"-" | U+002D HYPHEN-MINUS |
"." | U+002E FULL STOP |
"/" | U+002F SOLIDUS |
"none" | U+006E 라틴 소문자 N U+006F 라틴 소문자 O U+006E 라틴 소문자 N U+0065 라틴 소문자 E |
문자열 "."은 항상 소수점 구분자로 사용되며, 로캘과 관계없이, 천 단위 구분자는 없어야 합니다.
구문 형태가 누락된 색상 컴포넌트를 지원하는 경우, none (NONE, nOnE 등과 동일)은 직렬화 시 항상 소문자 "none"으로 직렬화됩니다.
15.1. 알파 값 직렬화하기
이 내용은 선택적 알파 값을 가질 수 있는 모든 <color> 값에 적용됩니다. opacity 속성에는 적용되지 않습니다.
알파가 [0, 1] 범위로 클램핑된 뒤 1이면, 직렬화에서 생략됩니다; 1(완전 불투명)이 기본값입니다.
알파가 1이 아닌 다른 값이면, 아래 설명된 대로 직렬화에 명시적으로 포함됩니다.
값이 0~255의 정수(8비트 부호 없는 정수)로 내부 표현되는 경우, 다음 단계를 따릅니다:
- alpha를 주어진 정수로 둡니다.
- 0~100 사이의 정수 중, 2.55를 곱하고 가장 가까운 정수로 반올림(Math.round, 두 값이 똑같이 가까우면 큰 쪽으로 반올림)했을 때 alpha가 되는 값이 있으면, 해당 정수를 100으로 나눈 값을 rounded로 둡니다.
- 없으면, alpha를 0.255로 나눈 뒤 가장 가까운 정수로 반올림(Math.round, 두 값이 똑같이 가까우면 큰 쪽으로 반올림), 1000으로 나눈 값을 rounded로 둡니다.
- rounded를 <number>로 직렬화해 반환합니다.
그 외에는, 주어진 값을 (<number>로, <percentage>가 아님) 직렬화해 반환합니다.
예를 들어, 알파가 8비트 부호 없는 정수 237로 저장된 경우, 정수 93이 조건에 부합하므로 Math.round(93 * 2.55)가 237이 되어, 알파는 "0.93"으로 직렬화됩니다.
반면, 알파가 8비트 부호 없는 정수 236인 경우, 해당하는 정수가 없으므로 (92는 235, 94는 240이 됨), 236 ÷ 0.255 = 925.490196078이므로, 알파는 "0.92549"로 직렬화됩니다 (최대 6자리, 끝의 0은 생략).
<number> 값은 10진수로 표현되며, "." 문자가 소수점 구분자로 사용됩니다. 앞의 0은 생략하면 안 됩니다. 뒤의 0은 생략해야 합니다.
예를 들어, 알파 값이 70%라면 직렬화 문자열은 "0.7"이 됩니다. 소수점 앞에 0이 있고, "."이 소수점 구분자이며 (로캘이 ',' 등 다른 문자를 쓰더라도), "7" 뒤에 오는 0은 모두 생략됩니다.
알파 값의 정밀도(직렬화 시 소수점 이하 자리수)는 이 명세에서 정의하지 않지만, 정수 백분율 값이 왕복 가능한 수준이어야 합니다. 따라서 직렬화 값은 최소 소수점 이하 두 자리 이상이어야 하며 (끝의 0이 제거된 경우 제외). 값은 +∞ 방향으로 반올림되어야 하며, 자르기(truncate)하면 안 됩니다.
예를 들어, 알파 값이 12.3456789%라면, "0.12", "0.123", "0.1234", "0.12346" (5는 +∞로 반올림, 뒤에 6이 있으므로) 또는 더 긴 직렬화 문자열로 표현될 수 있습니다.
<alpha-value>가 유효 범위 밖에서 지정된 경우, 구문 분석 시 클램핑되므로 지정 값은 클램핑됩니다. 다만, CSS Values 4 § 10.12 범위 검사에 따라, calc()로 지정된 <alpha-value>는 직렬화 시 지정 형태에서는 클램핑되지 않지만, 계산 값은 클램핑됩니다.
15.2. sRGB 값 직렬화하기
다음 sRGB 값의 직렬화 형태는:
-
hwb() 값
지정 값에서 유도됩니다.
속성 값 직렬화 시, 저자가 CSS 이름이 있는 색상, 시스템 색상, 더 이상 사용되지 않는 색상, transparent로 설정한 경우, ASCII 소문자 키워드 값을 지정 값으로 유지합니다. 계산 값 및 사용 값은 해당하는 sRGB 값입니다.
따라서 transparent의 직렬화 지정 값은 "transparent" 문자열이고, 직렬화 계산 값은 "rgba(0, 0, 0, 0)" 문자열입니다.
그 외의 모든 sRGB 값은, 지정 값, 계산 값, 사용 값이 해당하는 sRGB 값입니다.
직렬화 과정에서, 누락 값은 모두 0으로 변환됩니다.
15.2.1. HTML 호환 sRGB 값 직렬화
아래 조건이 모두 충족되면:
- 색상 공간이 sRGB이다
- 알파가 1이다
- RGB 컴포넌트 값이 0~255의 정수(8비트 부호 없는 정수)로 내부 표현된다
- HTML 호환 직렬화가 요청됨
그럼 해당 sRGB 값은 6자리 16진수 색상 표기법으로 직렬화됩니다:
총 7자 문자열: "#" 문자 뒤에 빨강, 초록, 파랑 컴포넌트의 2자리 16진수 표현을 순서대로 붙이며, ASCII 소문자 16진수를 사용합니다. 공백은 허용되지 않습니다.
context.fillStyle ="rgb(255, 0, 255)" console.log ( context.fillStyle); //"#ff00ff"
색상 공간은 sRGB, 표현은 컴포넌트당 8비트, 데이터 포맷은 none 값이나 확장 범위 값을 생성하지 않으며, 알파가 1입니다.
HTML 호환 직렬화는 "#ff00ff"(대문자 아님)입니다.
그 외에는 sRGB의 CSS sRGB 값 직렬화 또는 다른 색상 공간에 대해 해당 직렬화를 사용합니다.
context.fillStyle ="lab(29% 39 20)" ; console.log ( context.fillStyle); //"lab(29 39 20)"
CSS 직렬화는 "lab(29 39 20)" 문자열입니다.
context.fillStyle ="#ff00ffed" ; console.log ( context.fillStyle); //"rgba(255, 0, 255, 0.93)"
알파가 1이 아니므로 CSS 직렬화는 "rgba(255, 0, 255, 0.93)" 문자열입니다.
15.2.2. CSS sRGB 값 직렬화
해당 sRGB 값은 rgb() 또는 rgba() 형태로 직렬화되며 (알파값(클램핑됨)이 정확히 1인지 아닌지에 따라 결정), 함수명은 모두 ASCII 소문자입니다.
호환성을 위해 sRGB 컴포넌트 값은 <number> 형태로 직렬화되며, <percentage> 형태가 아닙니다. 또한 호환성을 위해, 컴포넌트 값은 10진수, 범위 [0-255]로 직렬화되며, 저장 비트 깊이에 관계없습니다.
앞서 언급한 대로, 알파값이 1일 때는 명시적으로 직렬화되지 않습니다. 또한 호환성을 위해 알파가 정확히 1일 경우 rgb() 형태가 사용되며, 암시적 알파를 가집니다; 그렇지 않으면 rgba() 형태, 명시적 알파값을 사용합니다.
호환성을 위해, 레거시 형태인 콤마 구분자를 사용하며; 각 콤마 뒤에는 정확히 하나의 ASCII 공백이 옵니다. 이는 rgba()에서 파랑 컴포넌트와 알파 값을 구분할 때도 슬래시가 아니라 콤마를 사용함을 포함합니다.
hwb ( 740 deg 20 % 30 % /50 % )
먼저 정규화되어
hwb ( 20 20 % 30 % /50 % )
그 후 sRGB로 변환되어, 아래와 같이 직렬화됩니다:
rgba ( 178.5 , 93.5 , 51 , 0.5 )
반환 결과의 정밀도는 아래에서 설명합니다.
참고: CSS Color 3과 달리, rgb() 함수의 파라미터는 <number> 타입이며, <integer> 타입이 아닙니다. 즉, 8비트 이상의 정밀도는 소수점 이하로 표시됩니다.
sRGB 컴포넌트 값의 정밀도 (직렬화 값의 유효숫자 자리수)는 이 명세에서 정의하지 않지만, 8비트 값이 왕복 가능한 수준이어야 합니다. 값은 +∞ 방향으로 반올림되어야 하며, 자르면 안 됩니다.
참고: getComputedStyle에서 반환된 색상값에서 <integer> 컴포넌트 값을 기대하는 스크립트 작성자는 <number>에도 대응하도록 업데이트해야 합니다.
예를 들어,
rgb ( 146.064 107.457 131.223 )
이제 유효하며, 아래와 같습니다:
rgb ( 57.28 % 42.14 % 51.46 % )
둘 다에 대한 준수 직렬화 형태는 "rgb(146.06, 107.46, 131.2)" 문자열입니다.
컴포넌트 값의 소수점 이하 0은 모두 생략되어야 하며; 소수점 이하가 모두 0이면 소수점도 생략해야 합니다. 즉, 정수 컴포넌트로 지정된 sRGB 색상은 하위 호환 정수 값으로 직렬화됩니다.
15.3. Lab 및 LCH 값 직렬화
lch() 및 lab() 값의 직렬화 형태는 계산 값에서 유도되며, lab() 또는 lch() 형태를 사용합니다. 함수명은 모두 ASCII 소문자입니다.
컴포넌트 값은 10진수로 직렬화되며; L, a, b, C 컴포넌트 값은 <number>로 직렬화되며, Lab 백분율 기준 범위 또는 LCH 백분율 기준 범위를 사용하여 백분율을 숫자로 변환합니다; 0% L은 0, 100% L은 100으로 매핑됩니다. 컴포넌트 값 사이 구분자는 ASCII 공백 문자 " "입니다.
컴포넌트 값의 소수점 이하 0은 모두 생략되어야 하며; 소수점 이하가 모두 0이면 소수점도 생략해야 합니다.
lab() 컴포넌트 값의 정밀도 (직렬화 값의 유효숫자 자리수)는 이 명세에서 정의하지 않지만, 광색역으로 인해 0~100의 L 값, ±127의 a/b 값이 왕복 가능한 수준이어야 하며, 최소 16비트 정밀도가 필요합니다; 결과적으로 소수점 이하 최소 3자리 이상이어야 하며, 끝의 0이 생략된 경우 제외. (내부 저장은 half float 또는 float 권장). 값은 +∞ 방향으로 반올림되어야 하며, 자르면 안 됩니다.
참고: ±125를 넘는 a/b 값도 초광색역에서는 가능합니다. 예를 들어 prophoto-rgb 원색 및 2차색은 이 범위를 넘지만 ±200 이내입니다.
앞서 언급한 대로, 알파값이 1이면 명시적으로 직렬화하지 않습니다. 1이 아닌 알파값은 명시적으로 직렬화해야 하며, " / " (ASCII 공백, 슬래시, 또다른 공백) 문자열로 b값과 알파값을 구분합니다.
아래의 직렬화 값은
lch ( 56.2 % 83.6 357.4 /93 % )
문자열 "lch(56.2 83.6 357.4 / 0.93)"이며, "lch(56.2% 83.6 357.4 / 0.93)"이 아닙니다.
15.4. Oklab 및 OKLCh 값 직렬화
oklch() 및 oklab() 값의 직렬화 형태는 계산 값에서 유도되며, oklab() 또는 oklch() 형태를 사용합니다. 함수명은 모두 ASCII 소문자입니다.
컴포넌트 값은 10진수로 직렬화되며; L, a, b, C 컴포넌트 값은 <number>로 직렬화되며, Oklab 백분율 기준 범위 또는 OKLCh 백분율 기준 범위를 사용하여 백분율을 숫자로 변환합니다; 0% L은 0, 100% L은 1.0으로 매핑됩니다. 컴포넌트 값 사이 구분자는 ASCII 공백 문자 " "입니다.
아래의 직렬화 값은
oklab ( 54.0 % -0.10 -0.02 )
문자열 "oklab(0.54 -0.1 -0.02)"이며, "oklab(54 -0.1 -0.02)" 또는 "oklab(54% -0.1 -0.02)"가 아닙니다.
컴포넌트 값의 소수점 이하 0은 모두 생략되어야 하며; 소수점 이하가 모두 0이면 소수점도 생략해야 합니다.
아래의 직렬화 값은
oklch ( 56.43 % 0.0900 123.40 )
문자열 "oklch(0.5643 0.09 123.4)"이며, "oklch(0.5643 0.0900 123.40)"이 아닙니다.
oklab() 컴포넌트 값의 정밀도 (직렬화 값의 유효숫자 자리수)는 이 명세에서 정의하지 않지만, 광색역으로 인해 0~1(0%~100%)의 L 값, ±0.5의 a/b/C 값이 왕복 가능한 수준이어야 하며, 최소 16비트 정밀도가 필요합니다; 결과적으로 소수점 이하 최소 5자리 이상이어야 하며, 끝의 0이 생략된 경우 제외. (내부 저장은 half float 또는 float 권장). 값은 +∞ 방향으로 반올림되어야 하며, 자르면 안 됩니다.
참고: ±0.5를 넘는 a/b/C 값도 초광색역에서는 가능합니다. 예를 들어 prophoto-rgb의 초록·파랑 원색은 C가 각각 0.526, 1.413입니다.
앞서 언급한 대로, 알파값이 1이면 명시적으로 직렬화하지 않습니다. 1이 아닌 알파값은 명시적으로 직렬화해야 하며, " / " (ASCII 공백, 슬래시, 또다른 공백) 문자열로 마지막 컴포넌트(b, 또는 C) 값과 알파값을 구분합니다.
15.5. color() 함수 값 직렬화
color() 값의 직렬화 형태는 계산 값에서 유도되며, color() 형태를 사용합니다. 함수명과 색상 공간 이름은 ASCII 소문자입니다.
컴포넌트 값은 10진수로 <number>로 직렬화됩니다. 컴포넌트 값 사이, 그리고 색상 공간 이름과 첫 컴포넌트 사이에는 ASCII 공백 문자 " "를 사용합니다.
아래의 직렬화 값은
color ( dIsPlAy-P30.964 0.763 0.787 )
문자열 "color(display-p3 0.96 0.76 0.79)"입니다. 소수점 이하 두 자리로 유지한 경우, 0.787이 0.79로 반올림되었으며 0.78로 잘리지 않았다는 점에 유의하세요.
컴포넌트 값의 소수점 이하 0은 모두 생략되어야 하며; 소수점 이하가 모두 0이면 소수점도 생략해야 합니다.
아래의 직렬화 값은
color ( rec20200.400 0.660 0.340 )
문자열 "color(rec2020 0.4 0.66 0.34)"이며, "color(rec2020 0.400 0.660 0.340)"이 아닙니다.
색상 공간이 sRGB라도 직렬화 결과에 색상 공간 이름을 명시적으로 포함해야 합니다.
미리 정의된 색상 공간별 최소 왕복 정밀도는 아래와 같습니다:
색상 공간 | 최소 비트 수 |
---|---|
srgb | 10 |
srgb-linear | 12 |
display-p3 | 10 |
a98-rgb | 10 |
prophoto-rgb | 12 |
rec2020 | 12 |
xyz, xyz-d50, xyz-d65 | 16 |
(컴포넌트당 16비트, half-float 또는 float 권장). 값은 +∞ 방향으로 반올림되어야 하며, 자르면 안 됩니다.
참고: rgb(), hsl() 등 레거시 형태와 비교할 때, color(srgb)는 더 높은 최소 정밀도가 요구됩니다. 더 높은 정밀도를 원하는 스타일시트 저자는 color(srgb) 형태 사용을 권장합니다.
앞서 언급한 대로, 알파값이 1이면 명시적으로 직렬화하지 않습니다. 1이 아닌 알파값은 명시적으로 직렬화해야 하며, " / " (ASCII 공백, 슬래시, 또다른 공백) 문자열로 마지막 컴포넌트와 알파값을 구분합니다.
아래의 직렬화 값은
color ( prophoto-rgb0.2804 0.40283 0.42259 /85 % )
문자열 "color(prophoto-rgb 0.28 0.403 0.423 / 0.85)"이며, 소수점 이하 3자리로 유지한 경우입니다.
15.6. 기타 색상 직렬화
이 내용은 currentcolor에 적용됩니다.
이 값의 직렬화 형태는 계산 값에서 유도되며, 색상 이름은 ASCII 소문자입니다.
currentColor의 직렬화 값은 "currentcolor" 문자열입니다.
16. opacity-value 직렬화
이 내용은 opacity 속성에 적용됩니다.
지정된 opacity 값은 <number>로 직렬화되며, <percentage>가 아닙니다.
이 <number> 값은 10진수로 표현되며, "." 문자가 소수점 구분자로 사용됩니다. 앞의 0은 생략하면 안 됩니다. 뒤의 0은 생략해야 합니다.
opacity 값이 [0,1] 범위를 벗어나도, 직렬화된 지정 값에서는 클램핑하지 않고 그대로 유지됩니다.
opacity 값의 정밀도(직렬화 시 소수점 이하 자리수)는 이 명세에서 정의하지 않지만, 정수 백분율 값이 왕복 가능한 수준이어야 합니다. 따라서 직렬화 값은 최소 소수점 이하 두 자리 이상이어야 하며 (끝의 0이 제거된 경우 제외). 값은 +∞ 방향으로 반올림되어야 하며, 자르면 안 됩니다.
17. 기본 스타일 규칙(Default Style Rules)
아래 스타일시트는 참고용이며, 규범적이지 않습니다. 이 스타일시트는 구현체가 HTML 문서의 기본 스타일로 사용할 수 있습니다.
/* 하드 데스크탑 사용자 에이전트의 하이퍼링크 색상 */ :link{ color : LinkText; } :visited{ color : VisitedText; } :active{ color : ActiveText; }
18. 색 변환 샘플 코드
이 섹션은 규범적이지 않습니다.
테스트
이 섹션은 규범적이지 않으며, 테스트가 필요하지 않습니다.
명확성을 위해 행렬 곱셈에는 라이브러리를 사용합니다. (곱셈과 덧셈을 모두 인라인하는 것보다 더 읽기 쉽습니다). 행렬은 컬럼 우선 순서입니다.
// 색 변환 샘플 코드 // ICC 프로파일과 컬러 관리 시스템을 이용한 변환도 가능합니다 // 명확성을 위해 행렬 곱셈에 라이브러리(multiply-matrices.js)를 사용합니다 // 표준 백색점, 4자리 CIE x,y 색도좌표로 정의됨 const D50= [ 0.3457 / 0.3585 , 1.00000 , ( 1.0 - 0.3457 - 0.3585 ) / 0.3585 ]; const D65= [ 0.3127 / 0.3290 , 1.00000 , ( 1.0 - 0.3127 - 0.3290 ) / 0.3290 ]; // sRGB 관련 함수 function lin_sRGB( RGB) { // sRGB 값 배열을 변환 // in-gamut 값이 [0 - 1] 범위일 때 // 선형 라이트(비보정) 형태로 변환 // https://en.wikipedia.org/wiki/SRGB // 확장 전이 함수: // 음수 값은 축을 반영하여 선형 부분이 확장됨, // 이후 반영된 거듭제곱 함수 사용 return RGB. map( function ( val) { let sign= val< 0 ? - 1 : 1 ; let abs= Math. abs( val); if ( abs<= 0.04045 ) { return val/ 12.92 ; } return sign* ( Math. pow(( abs+ 0.055 ) / 1.055 , 2.4 )); }); } function gam_sRGB( RGB) { // 0.0-1.0 범위 선형 라이트 sRGB 값 배열을 변환 // 감마 보정 형태로 변환 // https://en.wikipedia.org/wiki/SRGB // 확장 전이 함수: // 음수 값은 축 반영 후 선형 부분이 확장됨, // 이후 반영된 거듭제곱 함수 사용 return RGB. map( function ( val) { let sign= val< 0 ? - 1 : 1 ; let abs= Math. abs( val); if ( abs> 0.0031308 ) { return sign* ( 1.055 * Math. pow( abs, 1 / 2.4 ) - 0.055 ); } return 12.92 * val; }); } function lin_sRGB_to_XYZ( rgb) { // 선형 라이트 sRGB 값 배열을 CIE XYZ로 변환 // sRGB의 자체 백색점 D65 사용(색도 적응 없음) var M= [ [ 506752 / 1228815 , 87881 / 245763 , 12673 / 70218 ], [ 87098 / 409605 , 175762 / 245763 , 12673 / 175545 ], [ 7918 / 409605 , 87881 / 737289 , 1001167 / 1053270 ], ]; return multiplyMatrices( M, rgb); } function XYZ_to_lin_sRGB( XYZ) { // XYZ를 선형 라이트 sRGB로 변환 var M= [ [ 12831 / 3959 , - 329 / 214 , - 1974 / 3959 ], [ - 851781 / 878810 , 1648619 / 878810 , 36519 / 878810 ], [ 705 / 12673 , - 2585 / 12673 , 705 / 667 ], ]; return multiplyMatrices( M, XYZ); } // display-p3 관련 함수 function lin_P3( RGB) { // 0.0 - 1.0 범위의 display-p3 RGB 값을 변환 // 선형 라이트(비보정) 형태로 변환 return lin_sRGB( RGB); // sRGB와 동일 } function gam_P3( RGB) { // 0.0-1.0 범위의 선형 라이트 display-p3 RGB 배열을 변환 // 감마 보정 형태로 변환 return gam_sRGB( RGB); // sRGB와 동일 } function lin_P3_to_XYZ( rgb) { // 선형 라이트 display-p3 값 배열을 CIE XYZ로 변환 // D65 사용(색도 적응 없음) // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html var M= [ [ 608311 / 1250200 , 189793 / 714400 , 198249 / 1000160 ], [ 35783 / 156275 , 247089 / 357200 , 198249 / 2500400 ], [ 0 / 1 , 32229 / 714400 , 5220557 / 5000800 ], ]; return multiplyMatrices( M, rgb); } function XYZ_to_lin_P3( XYZ) { // XYZ를 선형 라이트 P3로 변환 var M= [ [ 446124 / 178915 , - 333277 / 357830 , - 72051 / 178915 ], [ - 14852 / 17905 , 63121 / 35810 , 423 / 17905 ], [ 11844 / 330415 , - 50337 / 660830 , 316169 / 330415 ], ]; return multiplyMatrices( M, XYZ); } // prophoto-rgb 관련 함수 function lin_ProPhoto( RGB) { // prophoto-rgb 값 배열 변환 // in-gamut 색상이 [0.0 - 1.0] 범위일 때 // 선형 라이트(비보정) 형태로 변환 // 전이 곡선은 감마 1.8, 작은 선형 부분 포함 // 확장 전이 함수 const Et2= 16 / 512 ; return RGB. map( function ( val) { let sign= val< 0 ? - 1 : 1 ; let abs= Math. abs( val); if ( abs<= Et2) { return val/ 16 ; } return sign* Math. pow( abs, 1.8 ); }); } function gam_ProPhoto( RGB) { // 0.0-1.0 범위의 선형 라이트 prophoto-rgb 값 배열을 변환 // 감마 보정 형태로 변환 // 전이 곡선은 감마 1.8, 작은 선형 부분 포함 // TODO: 음수 값은 축 반영 후 선형 부분 확장, 이후 거듭제곱 추가 const Et= 1 / 512 ; return RGB. map( function ( val) { let sign= val< 0 ? - 1 : 1 ; let abs= Math. abs( val); if ( abs>= Et) { return sign* Math. pow( abs, 1 / 1.8 ); } return 16 * val; }); } function lin_ProPhoto_to_XYZ( rgb) { // 선형 라이트 prophoto-rgb 값 배열을 CIE D50 XYZ로 변환 // 행렬은 유리수 형태로 표현 불가, 64비트 정확도로 계산됨 // 참고: https://github.com/w3c/csswg-drafts/issues/7675 var M= [ [ 0.79776664490064230 , 0.13518129740053308 , 0.03134773412839220 ], [ 0.28807482881940130 , 0.71183523424187300 , 0.00008993693872564 ], [ 0.00000000000000000 , 0.00000000000000000 , 0.82510460251046020 ] ]; return multiplyMatrices( M, rgb); } function XYZ_to_lin_ProPhoto( XYZ) { // D50 XYZ를 선형 라이트 prophoto-rgb로 변환 var M= [ [ 1.34578688164715830 , - 0.25557208737979464 , - 0.05110186497554526 ], [ - 0.54463070512490190 , 1.50824774284514680 , 0.02052744743642139 ], [ 0.00000000000000000 , 0.00000000000000000 , 1.21196754563894520 ] ]; return multiplyMatrices( M, XYZ); } // a98-rgb 관련 함수 function lin_a98rgb( RGB) { // 0.0 - 1.0 범위의 a98-rgb 값 배열을 변환 // 선형 라이트(비보정) 형태로 변환 // 음수 값도 허용 return RGB. map( function ( val) { let sign= val< 0 ? - 1 : 1 ; let abs= Math. abs( val); return sign* Math. pow( abs, 563 / 256 ); }); } function gam_a98rgb( RGB) { // 0.0-1.0 범위의 선형 라이트 a98-rgb 값 배열을 변환 // 감마 보정 형태로 변환 // 음수 값도 허용 return RGB. map( function ( val) { let sign= val< 0 ? - 1 : 1 ; let abs= Math. abs( val); return sign* Math. pow( abs, 256 / 563 ); }); } function lin_a98rgb_to_XYZ( rgb) { // 선형 라이트 a98-rgb 값 배열을 CIE XYZ로 변환 // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html // 아래 값은 원리적으로 R G B W 색도좌표에서 계산됨 // 참고: matrixmaker.html var M= [ [ 573536 / 994567 , 263643 / 1420810 , 187206 / 994567 ], [ 591459 / 1989134 , 6239551 / 9945670 , 374412 / 4972835 ], [ 53769 / 1989134 , 351524 / 4972835 , 4929758 / 4972835 ], ]; return multiplyMatrices( M, rgb); } function XYZ_to_lin_a98rgb( XYZ) { // XYZ를 선형 라이트 a98-rgb로 변환 var M= [ [ 1829569 / 896150 , - 506331 / 896150 , - 308931 / 896150 ], [ - 851781 / 878810 , 1648619 / 878810 , 36519 / 878810 ], [ 16779 / 1248040 , - 147721 / 1248040 , 1266979 / 1248040 ], ]; return multiplyMatrices( M, XYZ); } // Rec. 2020 관련 함수 function lin_2020( RGB) { // 0.0 - 1.0 범위의 rec2020 RGB 값 배열을 변환 // 선형 라이트(비보정) 형태로 변환 // ITU-R BT.2020-2 p.4 const α= 1.09929682680944 ; const β= 0.018053968510807 ; return RGB. map( function ( val) { let sign= val< 0 ? - 1 : 1 ; let abs= Math. abs( val); if ( abs< β* 4.5 ) { return val/ 4.5 ; } return sign* ( Math. pow(( abs+ α- 1 ) / α, 1 / 0.45 )); }); } function gam_2020( RGB) { // 0.0-1.0 범위의 선형 라이트 rec2020 RGB 값 배열을 변환 // 감마 보정 형태로 변환 // ITU-R BT.2020-2 p.4 const α= 1.09929682680944 ; const β= 0.018053968510807 ; return RGB. map( function ( val) { let sign= val< 0 ? - 1 : 1 ; let abs= Math. abs( val); if ( abs> β) { return sign* ( α* Math. pow( abs, 0.45 ) - ( α- 1 )); } return 4.5 * val; }); } function lin_2020_to_XYZ( rgb) { // 선형 라이트 rec2020 값 배열을 CIE XYZ로 변환 // D65 사용(색도 적응 없음) // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html var M= [ [ 63426534 / 99577255 , 20160776 / 139408157 , 47086771 / 278816314 ], [ 26158966 / 99577255 , 472592308 / 697040785 , 8267143 / 139408157 ], [ 0 / 1 , 19567812 / 697040785 , 295819943 / 278816314 ], ]; // 0은 실제로 4.994106574466076e-17로 계산됨 return multiplyMatrices( M, rgb); } function XYZ_to_lin_2020( XYZ) { // XYZ를 선형 라이트 rec2020으로 변환 var M= [ [ 30757411 / 17917100 , - 6372589 / 17917100 , - 4539589 / 17917100 ], [ - 19765991 / 29648200 , 47925759 / 29648200 , 467509 / 29648200 ], [ 792561 / 44930125 , - 1921689 / 44930125 , 42328811 / 44930125 ], ]; return multiplyMatrices( M, XYZ); } // 색도 적응 function D65_to_D50( XYZ) { // Bradford 색도 적응(D65에서 D50으로) // 아래 행렬은 세 가지 연산 결과임: // - XYZ에서 망막 원추 영역으로 변환 // - 한 기준 백색에서 다른 백색으로 성분 스케일링 // - 다시 XYZ로 변환 // 참고: https://github.com/LeaVerou/color.js/pull/354/files var M= [ [ 1.0479297925449969 , 0.022946870601609652 , - 0.05019226628920524 ], [ 0.02962780877005599 , 0.9904344267538799 , - 0.017073799063418826 ], [ - 0.009243040646204504 , 0.015055191490298152 , 0.7518742814281371 ] ]; return multiplyMatrices( M, XYZ); } function D50_to_D65( XYZ) { // Bradford 색도 적응(D50에서 D65로) // 참고: https://github.com/LeaVerou/color.js/pull/360/files var M= [ [ 0.955473421488075 , - 0.02309845494876471 , 0.06325924320057072 ], [ - 0.0283697093338637 , 1.0099953980813041 , 0.021041441191917323 ], [ 0.012314014864481998 , - 0.020507649298898964 , 1.330365926242124 ] ]; return multiplyMatrices( M, XYZ); } // CIE Lab 및 LCH function XYZ_to_Lab( XYZ) { // XYZ가 D50 기준이라 가정하고 CIE Lab으로 변환 // CIE 표준에서 유리수로 정의 var ε= 216 / 24389 ; // 6^3/29^3 var κ= 24389 / 27 ; // 29^3/3^3 // XYZ를 기준 백색에 맞게 스케일링한 xyz 계산 var xyz= XYZ. map(( value, i) => value/ D50[ i]); // f 계산 var f= xyz. map( value=> value> ε? Math. cbrt( value) : ( κ* value+ 16 ) / 116 ); return [ ( 116 * f[ 1 ]) - 16 , // L 500 * ( f[ 0 ] - f[ 1 ]), // a 200 * ( f[ 1 ] - f[ 2 ]) // b ]; // L은 [0,100] 범위, CSS에서는 퍼센트 추가 } function Lab_to_XYZ( Lab) { // Lab을 D50 적응 XYZ로 변환 // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html 참고 var κ= 24389 / 27 ; // 29^3/3^3 var ε= 216 / 24389 ; // 6^3/29^3 var f= []; // f 계산, 명도 관련 항부터 시작 f[ 1 ] = ( Lab[ 0 ] + 16 ) / 116 ; f[ 0 ] = Lab[ 1 ] / 500 + f[ 1 ]; f[ 2 ] = f[ 1 ] - Lab[ 2 ] / 200 ; // xyz 계산 var xyz= [ Math. pow( f[ 0 ], 3 ) > ε? Math. pow( f[ 0 ], 3 ) : ( 116 * f[ 0 ] - 16 ) / κ, Lab[ 0 ] > κ* ε? Math. pow(( Lab[ 0 ] + 16 ) / 116 , 3 ) : Lab[ 0 ] / κ, Math. pow( f[ 2 ], 3 ) > ε? Math. pow( f[ 2 ], 3 ) : ( 116 * f[ 2 ] - 16 ) / κ]; // 기준 백색으로 xyz 스케일링하여 XYZ 계산 return xyz. map(( value, i) => value* D50[ i]); } function Lab_to_LCH( Lab) { var epsilon= 0.0015 ; var chroma= Math. sqrt( Math. pow( Lab[ 1 ], 2 ) + Math. pow( Lab[ 2 ], 2 )); // 채도(Chroma) var hue= Math. atan2( Lab[ 2 ], Lab[ 1 ]) * 180 / Math. PI; if ( hue< 0 ) { hue= hue+ 360 ; } if ( chroma<= epsilon) { hue= NaN ; } return [ Lab[ 0 ], // L은 그대로 chroma, // 채도 hue// 색상, 도 단위 [0 ~ 360) ]; } function LCH_to_Lab( LCH) { // 극좌표형에서 변환 return [ LCH[ 0 ], // L은 그대로 LCH[ 1 ] * Math. cos( LCH[ 2 ] * Math. PI/ 180 ), // a LCH[ 1 ] * Math. sin( LCH[ 2 ] * Math. PI/ 180 ) // b ]; } // OKLab 및 OKLCH // https://bottosson.github.io/posts/oklab/ 참고 // XYZ <-> LMS 행렬을 기준 백색에 맞게 재계산 // 참고: https://github.com/w3c/csswg-drafts/issues/6642#issuecomment-943521484 // 64비트 정확도로 재계산 // https://github.com/color-js/color.js/pull/357 참고 function XYZ_to_OKLab( XYZ) { // XYZ(D65 기준)를 받아 OKLab으로 변환 var XYZtoLMS= [ [ 0.8190224379967030 , 0.3619062600528904 , - 0.1288737815209879 ], [ 0.0329836539323885 , 0.9292868615863434 , 0.0361446663506424 ], [ 0.0481771893596242 , 0.2642395317527308 , 0.6335478284694309 ] ]; var LMStoOKLab= [ [ 0.2104542683093140 , 0.7936177747023054 , - 0.0040720430116193 ], [ 1.9779985324311684 , - 2.4285922420485799 , 0.4505937096174110 ], [ 0.0259040424655478 , 0.7827717124575296 , - 0.8086757549230774 ] ]; var LMS= multiplyMatrices( XYZtoLMS, XYZ); // JavaScript의 Math.cbrt는 부호 일치하는 세제곱근 반환 // 다른 언어로 포팅 시 주의 // 특히 일반 거듭제곱 함수 사용 시 유의 return multiplyMatrices( LMStoOKLab, LMS. map( c=> Math. cbrt( c))); // L은 [0,1] 범위, CSS에서는 100을 곱하고 퍼센트 추가 } function OKLab_to_XYZ( OKLab) { // OKLab을 받아 D65 기준 XYZ로 변환 var LMStoXYZ= [ [ 1.2268798758459243 , - 0.5578149944602171 , 0.2813910456659647 ], [ - 0.0405757452148008 , 1.1122868032803170 , - 0.0717110580655164 ], [ - 0.0763729366746601 , - 0.4214933324022432 , 1.5869240198367816 ] ]; var OKLabtoLMS= [ [ 1.0000000000000000 , 0.3963377773761749 , 0.2158037573099136 ], [ 1.0000000000000000 , - 0.1055613458156586 , - 0.0638541728258133 ], [ 1.0000000000000000 , - 0.0894841775298119 , - 1.2914855480194092 ] ]; var LMSnl= multiplyMatrices( OKLabtoLMS, OKLab); return multiplyMatrices( LMStoXYZ, LMSnl. map( c=> c** 3 )); } function OKLab_to_OKLCH( OKLab) { var epsilon= 0.000004 ; var hue= Math. atan2( OKLab[ 2 ], OKLab[ 1 ]) * 180 / Math. PI; var chroma= Math. sqrt( OKLab[ 1 ] ** 2 + OKLab[ 2 ] ** 2 ); if ( hue< 0 ) { hue= hue+ 360 ; } if ( chroma<= epsilon) { hue= NaN ; } return [ OKLab[ 0 ], // L은 그대로 chroma, hue]; } function OKLCH_to_OKLab( OKLCH) { return [ OKLCH[ 0 ], // L은 그대로 OKLCH[ 1 ] * Math. cos( OKLCH[ 2 ] * Math. PI/ 180 ), // a OKLCH[ 1 ] * Math. sin( OKLCH[ 2 ] * Math. PI/ 180 ) // b ]; } // 프리멀티플 알파 변환 function rectangular_premultiply( color, alpha) { // 직교 색공간에서의 색상과 알파값을 받아 프리멀티플 형태로 반환 return color. map(( c) => c* alpha) } function rectangular_un_premultiply( color, alpha) { // 직교 색공간에서 프리멀티플된 색상과 알파값을 받아 실제 색상 반환 if ( alpha=== 0 ) { return color; // 0 나누기 방지 } return color. map(( c) => c/ alpha) } function polar_premultiply( color, alpha, hueIndex) { // 원통형 색공간에서의 색상과 알파값을 받아 프리멀티플 형태로 반환 // hueIndex는 색상 배열에서 색상 각도 위치를 의미 // 예: OKLCH에선 2, HSL에선 0 return color. map(( c, i) => c* ( hueIndex=== i? 1 : alpha)) } function polar_un_premultiply( color, alpha, hueIndex) { // 원통형 색공간에서 프리멀티플된 색상과 알파값을 받아 실제 색상 반환 // hueIndex는 색상 배열에서 색상 각도 위치를 의미 // 예: OKLCH에선 2, HSL에선 0 if ( alpha=== 0 ) { return color; // 0 나누기 방지 } return color. map(( c, i) => c/ ( hueIndex=== i? 1 : alpha)) } // 편의 함수 예시 function hsl_premultiply( color, alpha) { return polar_premultiply( color, alpha, 0 ); }
19. ΔE2000 및 ΔEOK 색상 차이 샘플 코드
이 섹션은 규범적이지 않습니다.
테스트
이 섹션은 규범적이지 않으며, 테스트가 필요하지 않습니다.
19.1. ΔE2000
가장 단순한 색상 차이 지표인 ΔE76은 Lab 색공간에서의 유클리드 거리입니다. 이는 좋은 1차 근사값이지만, 인쇄 및 섬유 염색과 같은 색상 중요 산업에서는 더 향상된 공식이 개발되었습니다. 현재 가장 널리 사용되는 공식은 ΔE2000입니다. 이 공식은 ΔE76에 비해 여러 비대칭성과 비선형성을 보정합니다. 공식이 복잡하고, 중간 계산의 부호에 크게 의존하기 때문에 많은 구현체가 잘못된 결과를 내기도 합니다 [Sharma].
아래 샘플 코드는 검증 되었으며, [Sharma]에서 공개한 Lab 값 쌍과 ΔE2000 기대값 테스트 세트에 대해 유효 숫자 5자리까지 맞으며, 정확합니다.
// deltaE2000은 deltaE76 및 deltaE94보다 통계적으로 의미 있는 개선이 이루어졌음 // CIE 및 Idealliance에서 추천함 // 특히 deltaE76이 10 미만인 색상 차이에 대해 권장됨 // 하지만 매우 복잡하며 // 많은 구현에 소오차가 있음! /** * @param {number[]} reference - CIE Lab 값 배열: L은 0..100, a와 b는 -150..150 근처 값 * @param {number[]} sample - CIE Lab 값 배열: L은 0..100, a와 b는 -150..150 근처 값 * @return {number} 기준색상과 샘플 색상 간의 차이 정도 */ function deltaE2000( reference, sample) { // 기준색상(reference)과 샘플 색상(sample) 모두 CIE Lab 색상에서 deltaE 2000 계산 // 이 구현은 가시 조건 영향 인자 kL, kC, kH가 모두 1임을 가정함 // (일반적으로 그렇게 사용됨) let [ L1, a1, b1] = reference; let [ L2, a2, b2] = sample; let C1= Math. sqrt( a1** 2 + b1** 2 ); let C2= Math. sqrt( a2** 2 + b2** 2 ); let Cbar= ( C1+ C2) / 2 ; // 평균 채도(Chroma) // 평균 채도에서 a축 비대칭 인자 계산 // 거의 무채색에 대해 JND 타원체를 다시 원으로 만듦 let C7= Math. pow( Cbar, 7 ); const Gfactor= Math. pow( 25 , 7 ); let G= 0.5 * ( 1 - Math. sqrt( C7/ ( C7+ Gfactor))); // 비대칭 인자로 a축 스케일링 // 이 때문에 Lab2000 색공간은 존재하지 않음 let adash1= ( 1 + G) * a1; let adash2= ( 1 + G) * a2; // 스케일링된 a와 원래 b축에서 새로운 채도 계산 let Cdash1= Math. sqrt( adash1** 2 + b1** 2 ); let Cdash2= Math. sqrt( adash2** 2 + b2** 2 ); // 새로운 색상(hue) 계산, 진짜 무채색은 0, 도 단위 const π= Math. PI; const r2d= 180 / π; const d2r= π/ 180 ; let h1= ( adash1=== 0 && b1=== 0 ) ? 0 : Math. atan2( b1, adash1); let h2= ( adash2=== 0 && b2=== 0 ) ? 0 : Math. atan2( b2, adash2); if ( h1< 0 ) { h1+= 2 * π; } if ( h2< 0 ) { h2+= 2 * π; } h1*= r2d; h2*= r2d; // 명도 및 채도 차이 (부호 중요) let ΔL= L2- L1; let ΔC= Cdash2- Cdash1; // 색상 차이, 부호 처리 주의 let hdiff= h2- h1; let hsum= h1+ h2; let habs= Math. abs( hdiff); let Δh; if ( Cdash1* Cdash2=== 0 ) { Δh= 0 ; } else if ( habs<= 180 ) { Δh= hdiff; } else if ( hdiff> 180 ) { Δh= hdiff- 360 ; } else if ( hdiff< - 180 ) { Δh= hdiff+ 360 ; } else { console. log( "상상할 수 없는 오류 발생" ); } // 가중 색상 차이, 채도가 클수록 더 많이 적용 let ΔH= 2 * Math. sqrt( Cdash2* Cdash1) * Math. sin( Δh* d2r/ 2 ); // 평균 명도 및 채도 let Ldash= ( L1+ L2) / 2 ; let Cdash= ( Cdash1+ Cdash2) / 2 ; let Cdash7= Math. pow( Cdash, 7 ); // Lab의 파란 영역 비선형성 보정 // hue 가중 인자 네 가지 가능성(각도에 따라 부호 다름) let hdash; if ( Cdash1== 0 && Cdash2== 0 ) { hdash= hsum; // 이 값은 0이어야 함 } else if ( habs<= 180 ) { hdash= hsum/ 2 ; } else if ( hsum< 360 ) { hdash= ( hsum+ 360 ) / 2 ; } else { hdash= ( hsum- 360 ) / 2 ; } // CIELAB의 균일성 부족에 대한 위치 보정 // 모두 JND 타원체를 구에 가깝게 만드려는 시도임 // SL 명도 선명 인자, 배경 L=50 가정 let lsq= ( Ldash- 50 ) ** 2 ; let SL= 1 + (( 0.015 * lsq) / Math. sqrt( 20 + lsq)); // SC 채도 인자, CMC 및 deltaE94 공식과 유사 let SC= 1 + 0.045 * Cdash; // 파란 영역 비선형성 교차 인자 T let T= 1 ; T-= ( 0.17 * Math. cos(( hdash- 30 ) * d2r)); T+= ( 0.24 * Math. cos( 2 * hdash* d2r)); T+= ( 0.32 * Math. cos((( 3 * hdash) + 6 ) * d2r)); T-= ( 0.20 * Math. cos((( 4 * hdash) - 63 ) * d2r)); // SH 색상 인자, 채도 및 보정된 색상 각도에 따라 결정됨(deltaE94와 유사) let SH= 1 + 0.015 * Cdash* T; // RT 색상 회전 인자, JND 타원체와 먼셀 일정 색상선 보상 // 중간~높은 채도 파란 영역에서 적용(색상각 225~315) let Δθ= 30 * Math. exp( - 1 * ((( hdash- 275 ) / 25 ) ** 2 )); let RC= 2 * Math. sqrt( Cdash7/ ( Cdash7+ Gfactor)); let RT= - 1 * Math. sin( 2 * Δθ* d2r) * RC; // 최종적으로 각 항을 제곱합의 제곱근으로 deltaE 계산 let dE= ( ΔL/ SL) ** 2 ; dE+= ( ΔC/ SC) ** 2 ; dE+= ( ΔH/ SH) ** 2 ; dE+= RT* ( ΔC/ SC) * ( ΔH/ SH); return Math. sqrt( dE); // 끝! };
19.2. ΔEOK
Oklab은 CIE Lab에서 발생하는 색상 선형성, 색상 균일성, 채도 비선형성의 문제를 겪지 않기 때문에, 색상 차이 지표가 이러한 문제를 보정할 필요가 없으며 단순히 Oklab 색공간에서의 유클리드 거리로 정의됩니다.
// deltaE OK 계산 // 단순 제곱합의 제곱근 /** * @param {number[]} reference - OKLab 값 배열: L은 0..1, a와 b는 -1..1 * @param {number[]} sample - OKLab 값 배열: L은 0..1, a와 b는 -1..1 * @return {number} 기준색상과 샘플 색상 간의 차이 정도 */ function deltaEOK( reference, sample) { let [ L1, a1, b1] = reference; let [ L2, a2, b2] = sample; let ΔL= L1- L2; let Δa= a1- a2; let Δb= b1- b2; return Math. sqrt( ΔL** 2 + Δa** 2 + Δb** 2 ); }
부록 A: 폐지된 CSS 시스템 색상
이전 CSS 버전에서는 여러 추가 시스템 색상을 정의했습니다. 하지만 이러한 색상 키워드는 폐지되었으며, 그 이유는 원래 목적(웹사이트 요소를 네이티브 OS와 유사하게 보이게 하는 것)을 충분히 달성하지 못하고, 웹페이지가 네이티브 OS 대화상자를 “스푸핑”하기 쉽게 만들어 보안 위험을 초래하며, 지문 채취 범위를 넓혀 사용자 프라이버시를 저해하기 때문입니다.
사용자 에이전트는 이러한 키워드를 지원해야 하며, 지문 채취를 줄이기 위해 아래에 나열된 (폐지되지 않은) 시스템 색상에 매핑해야 합니다. 저자는 이러한 키워드를 사용하면 안 됩니다.
폐지된 시스템 색상은 <deprecated-color> 서브타입으로 나타내며, 아래와 같이 정의됩니다:
- ActiveBorder
- 활성 창 테두리. ButtonBorder와 동일.
- ActiveCaption
- 활성 창 캡션. Canvas와 동일.
- AppWorkspace
- 다중 문서 인터페이스 배경색. Canvas와 동일.
- Background
- 데스크탑 배경. Canvas와 동일.
- ButtonHighlight
- 3D 요소 중 빛을 받는 쪽의 테두리 색상(테두리 한 겹으로 3D처럼 보이는 경우). ButtonFace와 동일.
- ButtonShadow
- 3D 요소 중 빛을 받지 않는 쪽의 테두리 색상(테두리 한 겹으로 3D처럼 보이는 경우). ButtonFace와 동일.
- CaptionText
- 캡션, 크기 조절 박스, 스크롤바 화살표 박스의 텍스트. CanvasText와 동일.
- InactiveBorder
- 비활성 창 테두리. ButtonBorder와 동일.
- InactiveCaption
- 비활성 창 캡션. Canvas와 동일.
- InactiveCaptionText
- 비활성 캡션의 텍스트 색상. GrayText와 동일.
- InfoBackground
- 툴팁 컨트롤 배경색. Canvas와 동일.
- InfoText
- 툴팁 컨트롤 텍스트 색상. CanvasText와 동일.
- Menu
- 메뉴 배경색. Canvas와 동일.
- MenuText
- 메뉴 내 텍스트. CanvasText와 동일.
- Scrollbar
- 스크롤바 회색 영역. Canvas와 동일.
- ThreeDDarkShadow
- 3D 요소의 두 겹 테두리 중 바깥쪽(빛 반대)의 더 어두운 테두리 색상. ButtonBorder와 동일.
- ThreeDFace
- 3D 요소의 면 배경색(두 겹 테두리로 3D처럼 보이는 경우). ButtonFace와 동일.
- ThreeDHighlight
- 3D 요소의 두 겹 테두리 중 바깥쪽(빛을 받는 쪽)의 더 밝은 테두리 색상. ButtonBorder와 동일.
- ThreeDLightShadow
- 3D 요소의 두 겹 테두리 중 안쪽(빛을 받는 쪽)의 더 어두운 테두리 색상. ButtonBorder와 동일.
- ThreeDShadow
- 3D 요소의 두 겹 테두리 중 안쪽(빛 반대)의 더 밝은 테두리 색상. ButtonBorder와 동일.
- Window
- 창 배경색. Canvas와 동일.
- WindowFrame
- 창 프레임. ButtonBorder와 동일.
- WindowText
- 창 내 텍스트. CanvasText와 동일.
테스트
- deprecated-sameas-001.html (실시간 테스트) (소스)
- deprecated-sameas-002.html (실시간 테스트) (소스)
- deprecated-sameas-003.html (실시간 테스트) (소스)
- deprecated-sameas-004.html (실시간 테스트) (소스)
- deprecated-sameas-005.html (실시간 테스트) (소스)
- deprecated-sameas-006.html (실시간 테스트) (소스)
- deprecated-sameas-007.html (실시간 테스트) (소스)
- deprecated-sameas-008.html (실시간 테스트) (소스)
- deprecated-sameas-009.html (실시간 테스트) (소스)
- deprecated-sameas-010.html (실시간 테스트) (소스)
- deprecated-sameas-011.html (실시간 테스트) (소스)
- deprecated-sameas-012.html (실시간 테스트) (소스)
- deprecated-sameas-013.html (실시간 테스트) (소스)
- deprecated-sameas-014.html (실시간 테스트) (소스)
- deprecated-sameas-015.html (실시간 테스트) (소스)
- deprecated-sameas-016.html (실시간 테스트) (소스)
- deprecated-sameas-017.html (실시간 테스트) (소스)
- deprecated-sameas-018.html (실시간 테스트) (소스)
- deprecated-sameas-019.html (실시간 테스트) (소스)
- deprecated-sameas-020.html (실시간 테스트) (소스)
- deprecated-sameas-021.html (실시간 테스트) (소스)
- deprecated-sameas-022.html (실시간 테스트) (소스)
- deprecated-sameas-023.html (실시간 테스트) (소스)
부록 B: 폐지된 특이 Hex 색상
CSS가 Quirks 모드로 파싱될 때, <quirky-color>는 <color>의 한 타입으로, 특정 속성에서만 유효합니다:
이 타입은 이러한 속성들을 포함하거나 참조하는 속성에서는 유효하지 않습니다. 예를 들어 background 축약형이나, 함수형 표기 예: color-mix() 내부에서는 사용할 수 없습니다.
또한, <quirky-color>는 <color>로 파싱될 때, @supports 규칙에서 영향을 받는 속성에는 유효해야 하지만,
CSS.supports()
메서드에서는 해당 속성에 대해 유효하지 않습니다.
<quirky-color>는 아래 규칙에 따라 <number-token>, <dimension-token>, 또는 <ident-token>로 표현될 수 있습니다:
-
<ident-token>인 경우, 토큰의 표현은 정확히 3글자 또는 6글자여야 하며, 모두 16진수 숫자여야 합니다. 해당 값과 동일한 <hex-color>를 나타냅니다.
-
<number-token>인 경우, 반드시 integer 플래그가 설정되어 있어야 합니다.
정수 값을 직렬화합니다. 직렬화 결과가 6글자보다 짧으면, 앞에 "0"을 추가하여 6글자로 만듭니다. 해당 값과 동일한 <hex-color>를 나타냅니다.
-
<dimension-token>인 경우, 반드시 integer 플래그가 설정되어 있어야 합니다.
정수 값을 직렬화하고, 토큰의 단위 표현을 뒤에 붙입니다. 결과가 6글자보다 짧으면, 앞에 "0"을 추가하여 6글자로 만듭니다. 해당 값과 동일한 <hex-color>를 나타냅니다.
(즉, Quirks Mode에서는 hex 색상을 앞에 "#" 없이 쓸 수 있지만, 독특한 파싱 규칙이 적용됩니다.)
테스트
특이 hex 색상
감사의 글
CSS Color 3에 기여한 분들 외에도, 편집자들은 Emilio Cobos Álvarez, Alexey Ardov, Chris Bai, Amelia Bellamy-Royds, Lars Borg, Mike Bremford, Andreu Botella, Dan Burzo, Max Derhak, fantasai, Simon Fraser, Devon Govett, Phil Green, Dean Jackson, Andreas Kraushaar, Pierre-Anthony Lemieux, Tiaan Louw, Cameron McCormack, Romain Menke, Chris Murphy, Isaac Muse, Jonathan Neal, Chris Needham, Björn Ottosson, Christoph Päper, Brad Pettit, Xidorn Quan, Craig Revie, Melanie Richards, Florian Rivoal, Jacob Rus, Joseph Salowey, Simon Sapin, Igor Snitkin, Lea Verou, Mark Watson, James Stuckey Weber, Sam Weinig, 그리고 Natalie Weizenbaum께 감사드립니다.
변경 사항
2024년 2월 13일 후보 권고안 초안 이후 변경 사항
- color 속성에서 사용되는 값은 원시 상속값이 아니라, 해석된 상속값임을 명확히 함
- sRGB로 해석되거나 레거시 색상 구문을 지원하는 색상 등 색상 카테고리 명시
- 색상(Hue) 정규화 예제 추가
- 유사 컴포넌트 표에서 알파가 누락된 오류 수정, 본문에서는 유사하다고 설명됨
- 불투명도(opacity) 값의 직렬화를 한 섹션으로 모아 명확히 함
- color-interpolation-method 및 호스트 구문 관련 문구 명확화
- 누락된 색상(Hue) 반환을 위한 epsilon 정의
- 중앙 축에 충분히 가까운 색상을 무채색으로 더 정확하게 정의
- ‘color channel’ 대신 ‘color component’ 용어 일관 사용
- 상관 색온도(Correlated Color Temperature) 용어 설명과 참고 추가
- premultiplied 용어 내보내기 및 일관되게 연결
- 폐지된 시스템 색상과 미폐지 시스템 색상의 동등성은 위험요소에서 제외
- “parse a CSS <color>” 알고리즘의 의도된 사용 방식 명확화
- HTML 호환 직렬화 예제 추가, 수정
- HTML 호환 직렬화에서 누락값을 0으로 변환하는 체크 제거(이미 변환됨)
- HTML 호환 직렬화와 CSS 직렬화 모두에 누락값이 0이 되는 노트 위치 이동
- sRGB용 HTML 호환 hex 직렬화 추가
- xyz-d65 및 xyz-d50 예제 추가
- XYZ에서 밝기를 나타내는 컴포넌트(Y) 명확화
- CSS 색역 매핑은 실제 값에 적용됨을 명확화
- hslToRgb 예제 코드에서 hue 정규화 제거(입력값은 이미 파싱 시 정규화됨)
- 색역 매핑 알고리즘 4단계 의사코드 수정
- 보간이 색상 결합의 가장 일반적 상황임을 명확히, 단 유일하지 않음도 명시
- deltaE 테이블에서 텍스트 대비 충분히 확보
- <absolute-color-function> 용어 남은 부분 제거, <absolute-color> function으로 일관성 유지
- 감사의 글 업데이트
- 색역(mesh) 다이어그램 추가
- CSSOM 직렬화를 명시된 값이 아닌 선언된 값으로 기술
- 휘도(luminance) 정의 내보내기 추가
- <opacity-value> 생성 규칙 추가
- hslToRgb 결과값이 [0,1] 범위임을 명확화
- 선형화 후 RGB 공간은 가산적임을 명확화
2022년 11월 1일 후보 권고안 초안 이후 변경 사항
- cssom-1에서 옮긴 uint8_t alpha 직렬화 단계 추가
- HSL 음수 채도(parse-time clamp)를 0으로 처리, CSS Color 3의 최신 interop 동작 복원
- 보간 시 항상 색 공간 변환을 수행, powerless 컴포넌트는 누락 처리
- alpha 1 직렬화 생략 시점 명확화
- hue 각도를 [0,360]로 제한하는 중복 구속 조건 제거(이미 처리됨)
- ActiveCaption 설명 수정(배경색임)
- 불투명도(opacity)와 알파(alpha) 구분, opacity는 opacity-value 사용(클램핑 방식 다름)
- premultiplication 이전에 carry-forward 처리 명확화
- 색역 매핑 알고리즘 업데이트
- hue 보간 관련 이슈 수정
- HWB에서 white 또는 black이 100%일 때 무채색이라는 기준은 합이 100%임을 명확히
- rgb → hsl 변환 시 음수 채도 반환 방지, hue를 반대쪽으로 조정
- ProPhoto에 64비트 정확도 행렬 사용(유리수 표현 불가)
- Oklab 행렬을 64비트 정확도로 재계산(이전 32비트와 결과 동일)
- GMA 결과를 목적지 색 공간에서 항상 반환(목적지가 무한대이면 매핑 없음)
- Oklab에서 JND 1의 값이 0.02인 이유 설명 추가
- sRGB 값 해석은 color() 함수에는 적용되지 않음을 명확화
- alpha 값 정의 위치를 opacity 속성 위로 이동, opacity 지정값은 클램핑하지 않음 명확화
- 시스템 색상은 프라이버시 보호를 위해 스푸핑 명시적으로 허용
- D50→D65 역색도 적응 행렬 수정
- 선형 Bradford와 원래 Bradford 색도 적응 알고리즘 명확 구분
- 색역 매핑 알고리즘에서 clipped를 바로 gamut mapped 결과로 반환, 불필요한 단계 제거
- 색도 적응 행렬을 더 높은 정밀도로 업데이트
- 색상 파싱 알고리즘(parse a css color) 추가, 타 명세에 색상 처리 재정의 필요 없음
- 색역 매핑에서 geometric 용어 사용(analytical 대신)
- HSL 문법과 문장 일치(퍼센트, 숫자 모두 허용)
- LCH 알파 보간 예제 수정(hue 각도 un-premultiply 오류 수정)
- sRGB, display-p3 전달 함수 수정(특정 컴포넌트 값에서만 영향, 실제 8/10비트에서는 불가능)
- 시스템 색상 지정값은 자신임을 명확화
- PNG cICP 청크 명시, 이미지 태깅 용도
- hue 증가/감소 시 0/360 처리 방식 기술
- 무력(HWB hue) 단점이 HSL hue와 동일함 명확화
- 휘도(luminance)와 명도(lightness) 비교 및 도표 추가
- hue 보간 키워드 설명 및 예제 추가
- 무채색 HWB 색상에 대한 규범적 문장 사용
- hue 보간 각도 범위 [0,360)로 수정([0,360] 아님)
- L=0%/100%일 때 검은색/흰색 표시되는 것은 색역 매핑 때문임을 명확화, powerlessness 설명 제거
- ‘representing black’ ‘representing white’ 혼란스러운 문장 제거
- opponent a, b가 유사함 명확화
- RGB 컴포넌트 지정값 범위로 일관성 있게 명시
- Lab, LCH, Oklab, OKLCh 직렬화 시 퍼센트 참조 범위 명시
- Oklab 보간 필수, 이전 ‘may’ 삭제, 명시적 opt-out 설명
- Lab, LCH, Oklab, OKLCh 튜토리얼은 비규범적임을 명확히 표시, 일부 정의는 본문으로 이동
- 보간 시 유사 컴포넌트 체크가 색 공간 변환 이전임을 명확히
- HWB 구문 변경 및 참조 범위, CSS Color 5에서 역포팅
- carry-forward 연산을 powerless 처리 이전에 하도록 명확화
- 레거시 rgb() 구문에서 color 컴포넌트는 모두 숫자 또는 모두 퍼센트여야 함을 명확화
- 레거시 구문에서는 color 컴포넌트가 모두 퍼센트 또는 모두 숫자여야 함 명확화
- 명시 범위 초과 alpha 예제 추가(calc() 사용 여부 구분)
- 직렬화 시 끝자리 0 자르기 예제 관련 텍스트에 배치
- 예시 명확화, text-shadow 값 사용
- currentColor 해석 명확화
- 감사의 글 업데이트
- 무채색이 a,b 또는 chroma가 누락된 것이라는 주장 제거
- HSL, HWB를 무한대 색역으로 변경, 라운드트립 향상 목적
- HSL 퍼센트 참조 범위 정의
- 최신 색상 구문 hsl(), hsla()는 혼합 숫자·퍼센트 허용
- 최신 색상 구문 rgb(), rgba()는 혼합 숫자·퍼센트 허용
- ‘modern color syntax’ 용어 정의(레거시 색상 구문은 이미 정의됨)
- ‘analogous components’ 용어 일관 사용
- 모든 미리 정의된 색 공간에서 보간 허용으로 변경
- color() 함수에는 RGB/XYZ 세 파라미터 요구 명확화
- 이름 색상, 시스템 색상, transparent 직렬화 명확화
- Lab, LCH, Oklab, OKLCh의 지정값 정의
- 기타 sRGB 색상의 지정값 정의
- 이름·시스템 색상의 지정값 정의
- 파싱값 시점에서 alpha, Lightness, Chroma, Hue 클램핑
- CIE Lightness, specular white 언급 삭제
- as-specified Hue 유지 요구 삭제; [0, 360]로 클램핑
- Lightness 및 숫자 직렬화 예시 일관화
- 사소한 오타 및 편집적 명확화
2022년 7월 5일 후보 권고안 초안 이후 변경 사항
- hue 보간 “specified” 값 제거
- hue 보간 각도 정의 더 정확하게, 360deg 차이 유지
- premultiplication에서 carry-forward alpha 예시 추가
- L=100%일 때 a,b, C,h powerless임을 명확화(흰색 표현)
- L=400 언급 제거, hdr-CIELAB에 해당, CIE Lab에는 적용 안 됨
- Oklab, OKLCh 대문자 일관화
- 용어 섹션에 valid color, invalid color, out of gamut, in gamut 정의 이동
- “longer” hue 보간 정의 수정
- 호스트 구문(host syntax) 개념 추가 설명
- 색상 견본(color swatch) 접근성 개선
- 레거시 형태는 “none” 지원하지 않음 명확화
- hue 생성식에서 “none” 제거, 레거시 구문에서 허용 안 함
- CMYK, CMYKOGV 일부 언급 제거, CSS Color5로 이동
- 보간 색상에서 누락값 처리 방법 명확화
- xyz-params 문법 업데이트, 숫자와 퍼센트 모두 허용으로 본문과 일치
- 모든 예제·도표에 ID, self-link 명시
- 색역 매핑 소개 읽기 중요성 명확화, 구현자 대상
- 커스텀 색 공간 관련 남은 언급 제거(feature는 CSS Color 5 이동)
- <color> 및 <alpha-value> 문법 리팩토링
- 더 나은 독해 흐름을 위한 편집적 리팩토링
- 색역 매핑 알고리즘 의사코드 업데이트, 불필요한 deltaE 호출 제거
2022년 6월 28일 작업 초안 이후 변경 사항
- 후보 권고안 상태로 업데이트
2022년 4월 28일 작업 초안 이후 변경 사항
- opacity 속성을 모듈 최상단(color 속성 옆)에 이동, 세부 설명 전 배치
- color 속성 설명 개선, 특히 다른 속성에 미치는 영향
- 동일 모듈 색상에서 hue 보간 더 긴 쪽 공식 수정
- 새 시스템 색상 AccentColor, AccentColorText 추가
- 색 공간 변환 단계 전체 설명을 새 섹션에 추가
- premultiplication 및 un-premultiplication에 대해 none alpha 처리 설명
2021년 12월 15일 작업 초안 이후 변경 사항
- 시스템 색상 완전 해석, 강제 색상 모드에서는 변경 금지
- color() 함수에 파라미터 수 오류 허용 삭제
- CIE Lightness 및 OK Lightness 직렬화를 퍼센트 대신 숫자로 변경
- 폐지된 시스템 색상 동등성 위험요소로 표시
- CIE 및 OK L,a,b,C 퍼센트 값 참조 범위 추가
- 직사각형/극좌표 색 공간 모두에 premultiplication/undo 샘플 코드 추가 공지
- 색역 매핑 본문 및 의사코드에 범위 초과 클램핑 추가
- ProPhoto RGB / ROMM에 대한 규범적 참고 추가
- sRGB 및 Display P3의 참조 주변(black point) 값 수정
- Display P3에 대한 규범적 참고 추가
- 흰색보다 더 흰색, 검은색보다 더 검은색의 색역 축소에서 무한 루프 방지
- none 값 직렬화 명확화
- Oklab 보간 opt-in 명확화, 레거시 색상에는 적용되지 않음
- none 값으로 premultiplication 동작 정의
- rgb에서 누락값은 0으로 직렬화 명확화
- calc()에서 none 값 사용 명확화
- System Colors 표기 일관성 오류, 오타 수정
- SelectedItem, SelectedItemText 예시 추가
- 레거시 색상 존재/부존재 명시
- CIE XYZ에 대한 규범적 참고 추가
- HWB, HSL에 대한 규범적 참고 추가
- hwb()는 레거시 문법이 아니므로, 이전 콤마 구분 구문 지원하지 않음 명확화
- 레거시 색상만 색역 매핑 수행, 나머지는 무한대
- 분광광도계(spectrophotometer), 분광복사계(spectroradiometer) 용어 구분
- 사소한 오타 및 문법 개선
2021년 6월 1일 작업 초안 이후 변경 사항
- 색역 매핑 섹션 추가, CSS 색역 매핑 알고리즘 정의(OKLCh에서 chroma 축소 및 지역 MINDE)
- color(xyz ...)의 계산값은 color(xyz-d65 ...)
- 보간 색 공간에 srgb-linear 추가
- Colors 3 이후 변경 사항 섹션 업데이트
- Oklab, OKLCh 값 해석 섹션 추가
- srgb-linear 색 공간 추가
- @color-profile 및 device-cmyk를 level 5로 이동(CSSWG 결의)
- 보간 색 공간(interpolation color space) 정의
- 행렬은 row-major임을 명확화, 행렬 곱 라이브러리 연결
- 옛 보안·프라이버시 섹션 분리
- quirks-mode 특이 hex 색상 정의
- device-cmyk에서 fallback 색상 제거
- 기본값 선언 없는 호스트 구문은 Oklab을 기본 사용
- deltaE OK 샘플 코드 추가
- OKlab, OKLCh 변환 샘플 코드 추가
- oklab(), oklch() 함수 추가 Oklab, OKLCh 설명 추가
- CIE LCH 결함 설명 추가
- none 키워드를 통해 색상 컴포넌트 모두 “누락” 가능, powerless 컴포넌트 자동 누락, NaN 참조는 “누락” 개념으로 수정
- x,y 백색점 값 명시, 전체에 일관 적용
- 호스트 구문(host syntax) 용어 정의
- override-color 색상 해석 시 컨텍스트 정의
- 새 시스템 색상 쌍 추가
- HSL, HWB 샘플 코드 수정
- 오류 없는 HSL 값 테이블로 교체
- Lea Verou 공동 편집자로 WG 결의에 따라 추가
- hue 각도 무한대 허용 명확화
- MarkText 예시 수정
- 도표, 예시 추가 및 수정
- 편집적 명확화
- 사소한 오타, 마크업 수정
2020년 11월 12일 작업 초안 이후 변경 사항
- Lab 값이 LCH로 변환될 때 거의 무채색에서 색상 불확정(hue indeterminate) 문제 명시
- RGB-Lab 상호변환 단계 중 선형 조합 단계 명확화
- CSS Color 5에서 사용할 @color-profile의 components 설명자 추가
- 모든 미리 정의된 RGB 색 공간을 확장 범위로 정의
- 색상 보간 전에 색역 매핑(gamut mapping)이나 색역 클리핑(gamut clipping) 단계가 없음을 명확히 함
- 레거시 sRGB 구문 보간 명확화
- color()에서 lab 옵션 제거
- 미리 정의된 색 공간 간 상호변환 단계 나열
- ‘color space’ 용어 일관 사용(두 단어)
- 색상 혼합 시 색 공간 선택에 대한 가이드 추가
- 예제 정밀도 향상을 위해 재계산
- 색상 보간(hue interpolation) 예제 추가
- color() 구문 단순화, fallback 옵션 제거
- @color-profile에서 연결할 수 있는 ICC 프로파일 유형 명확화
- 드문 ICC Named Colors 지원 제거
- 표준 백색점 색도(chromaticity) 정밀도 향상
- 한 미리 정의된 색 공간에서 상표(trademark) 설명 제거
- 보간 설명을 보간 공간(interpolation space)과 좀 더 일반적으로 서술
- 접근성 고려사항(Accessibility Considerations) 섹션 수정
- color()에서 color space 인자는 반드시 필요(sRGB도 포함)
- currentColor가 sRGB에 한정되지 않음을 명확화
- sRGB→XYZ→sRGB 행렬 소정 수정, round-trip 개선
- Rec2020 전달 함수 명확화, ITU Rec BT.2020-2 올바른 참고 추가
- 예제 fallback 구문 올바른 문법으로 수정
- 레거시 색상이 아닌 경우 감마 인코드 공간 보간 강제하지 않음
- premultiplied alpha 보간 정의
- currentColor로의 색상 보간 시작, 관련 논의
- NaN이 포함된 hue 보간 정의
- 색상 보간 일반화
- Lab에서 보간 정의, LCG로 오버라이드 가능
- hue 보간 관련 수정
- hue 각도 보간 정의
- 보간 섹션 추가
- 일부 예제 구문 수정
- color()에서 퍼센트 허용 컴포넌트 명확화
- lch()는 lab()로 직렬화하지 않고 자기 자신으로 직렬화하도록 변경
- color()에서 레거시 sRGB가 아닌 경우 컴포넌트당 최소 10비트 정밀도
- color()에서 color space는 선택 사항이 아님
- lab()과 color(lab) 간 최소 정밀도 일치
- color() 함수 fallback 절차 명확화 - 첫 번째 유효한 색상(색역 내)이 우선, 아니면 첫 번째 유효 색상을 색역 매핑, 아니면 투명 검은색
- opacity 속성과 불투명도가 있는 색상의 차이 명확화, 특히 중첩된 텍스트 글리프 렌더링에서
- ΔE2000 샘플 코드(검증된 것) 추가
- 기존에 정의되지 않았던 chromaticity 용어 정의, 예시 및 chromaticity 다이어그램 정의
- 색상 가산성(color additivity) 설명 추가, 예시 포함
- WPT 테스트에 소스 링크 추가
- color, valid color 용어 내보내기, 다른 명세에서 참조 가능
- 직렬화 시 컴포넌트당 최소 비트수 정의
- “applies to” 정의 업데이트(CSS-wide 변경)
- 미리 정의된 색 공간에 이미지 상태(display referred/scene referred) 추가
- 색도 좌표와 함께 백색점 상관 색온도(예: D65) 명시, 명확성 향상
- 반올림은 +∞ 방향임을 명확화
- 오타, 마크업 수정, 링크 수정
2019년 11월 5일 작업 초안 이후 변경 사항
- 다른 명세에서 사용할 용어 일부 내보내기
- WCAG 2.0에서 2.1로 요구사항 업데이트
- 직렬화에 사용되는 유니코드 문자 완전 명시
- 특수 이름 색상 직렬화 정의
- device-cmyk() 직렬화 정의
- color() 직렬화 정의
- 웹 호환 최대화 방식으로 RGB 직렬화 완전 정의
- Lab, LCH 직렬화 정의
- 알파 값 직렬화 완전 정의
- RFC2119 실수 방지 위한 일관성 점검
- 모든 예제에 ID 추가, 참조 가능하게 함
- 해석 색상(resolved color)과 직렬화 색상(serialized color) 섹션 분리
- (보안) ICC 프로파일은 실행 코드 없음 명시
- 범위 초과란 무엇인지 profiled colors에 대해 정의
- 범위 초과 클램핑 명확화
- 명시값 예제 추가
- 계산값(computed values) 명확화
- 지문채취 방지, 폐지된 시스템 색상에 필수 매핑 추가
- X11 색상 표준화 이유와 역사에 대한 설명 추가
- hwb 샘플 코드 수정
- MacBeth 패치용 DeltaE2000 값 표 추가
- ICC profile Internet Media type에 대한 설명 추가
- PNG sRGB 청크 참조 추가
- CMYK → Lab 변환 명확화
- RGB → Lab 변환 명확화
- HSL vs. LCH 비교 추가
- Rec BT.2020 색 공간 설명 보강
- prophoto-rgb 설명 업데이트
- Value Definitions 섹션에서 중복된 “keywords” 삭제
- 유효하지 않은 색상 예제 추가
- 여러 fallback 예제 추가
- 사소한 오타, 마크업 수정
- 선언되지 않은 커스텀 색 공간 처리 명확화
- 예제와 설명 노트 일부 명확화
- 유효/무효 ICC 프로파일 처리 규정
- 명시적으로 태그된 색 공간의 이미지 처리 규정
- 4k, SDR 비디오용 색 공간 정의
- 사용자 대비 설정 우선 적용 명시
- 강제 색상 모드 외에서 시스템 색상 의미 명확화
- 기본 스타일 규칙 업데이트
- color()에 CIE XYZ 색 공간 추가
- hue 각도 명확화, NaN 명시적으로 허용
- 시스템 색상 페어링 설명 보강, AA 접근성 대비 요구
- 중첩된 글리프와 opacity 속성 상호작용 경고 추가
- color 정의 문법 수정
- Highlight/HighlightText 설명 보강
- prophoto-rgb 전달 함수 수정
- prophoto-rgb 기본색 더 높은 정밀도 사용
- “표시 불가” 정의 시작
- canvas surface 관련 문단 삭제
- buttonborder, mark, marktext 시스템 색상 추가
- sRGB→HWB 역변환 추가
- 극좌표 색 공간은 원통형임을 명확화(구형 아님)
- 접근성 고려사항(Accessibility Considerations) 섹션 추가
- 색역 매핑을 컴포넌트별 클리핑이 아니라 chroma 축소로 서술 시작
- rec2020 백색 색도 수정
- @color-profile에서 device-cmyk 사용 가능; CMYK→color 알고리즘에서 단순 변환은 최후 수단으로만 사용
- 인쇄 지향 CMYK 및 KCMYOGV 예제 추가
- 사용자 정의 색 공간은 dashed-ident로, 미리 정의된 색 공간 확장성 확보
- color() 함수에 lab 옵션 추가
- CIE Lab에 대한 규범적 참고 추가
- prophoto-rgb가 D50 백색점 사용하므로 색도 적응 불필요 명확화
- LCH에서 각도 증가 방향 명확화
- 색상명은 ASCII 대소문자 구분 없음 명확화
- color 속성 초기값을 CanvasText로 변경
- 혼란스러운 gray() 함수 CSS WG 결의로 삭제
- 분산된 정의를 Color terminology 섹션에 통합
- 도움이 되는 그림 및 예제 추가
- 사소한 편집적 명확화, 맞춤법, 오타, 마크업 수정
2016년 7월 5일 작업 초안 이후 변경 사항
- Lab 및 LCH의 Lightness를 퍼센트로 변경, CSS 호환성 확보
- 색상 값 클램핑 명확화
- 퍼센트 opacity 허용
- sRGB, linear-light sRGB 용어 정의, 타 명세에서 사용 가능
- CSS 시스템 색상 목록 추가, Text를 CanvasText로 이름 변경
- 시스템 색상 키워드는 자신으로 계산됨
- 시스템 색상에 대해 computed/used 값 항목 추가
- 비폐지 시스템 색상 소개를 forced-colors 모드 중심으로 재작성
- 미리 정의된 색 공간 일관된 하이픈 사용
- 불투명하지 않은 요소가 레이어에 그려짐(포지션 없어도) 내용 복원
- color 속성 초기값을 검은색으로 변경
- LCH의 hue는 360deg로 모듈로 처리(이후 변경됨)
- LCH, Lab에서 L 허용 범위와 L=100 의미 명확화
- 비디오에서 사용하는 색 공간 참조 업데이트
- prophoto-rgb 미리 정의 색 공간 추가
- display-p3의 검은색/흰색 휘도값 수정
- display-p3 전달 함수 명확화
- a98-rgb 색 공간 추가, 기본색 색도 표 수정
- currentColor의 computed 값이 해석된 색상이 아님을 명확화
- 예제 구문을 최신 명세에 맞게 업데이트
- color-mod() 함수 제거
- propdef 테이블에서 “media” 삭제
- “transparent black”, “opaque black” 용어 내보내기, 일관 사용
- 계산된 값(percent 등) 명확화
- 색상 컴포넌트의 필수 정밀도 및 반올림 동작 명확화
- color 속성이 컬러 폰트 글리프에 영향 없음(명시적 참조 시 제외, 예: currentColor)
- 색상 값 해석 방법 명확화
- HSL, HWB, 이름 색상은 sRGB로 해석됨 명확화
- device-cmyk에서 sRGB로 변환 단순화
- 이전 콤마 사용 색상 구문을 “레거시”로 명명, 예제를 콤마 없는 형태로 변경
- 표시 색상을 디바이스 색역에 제한하는 불필요한 요구사항 제거
- P3를 display-p3로 이름 변경; DCI P3와 혼동하지 않도록 명확화
- “color()” 함수 파라미터 설명 보완
- 미리 정의된 색 공간을 “@color-profile” 식별자에서 허용하지 않음
- “color”, “color-adjust”, “opacity” 속성 정의에 정식 순서 추가
- 알파 합성(alpha compositing) 정의를 SVG11에서 CSS Compositing으로 변경
- 샘플 변환 코드가 비규범적임 명확화
- 보안·프라이버시 고려사항(Security and Privacy Considerations) 추가
- 여러 참고 문헌 최신 버전으로 업데이트
- 인라인 이슈를 GitHub 이슈 링크로 전환
- 사소한 편집 명확화, 서식 및 마크업 개선
Colors 3와의 변경 사항
CSS Color 3와 비교했을 때 주요 변경점은 CSS 색상이 더 이상 sRGB의 좁은 색역으로 제한되지 않는다는 점입니다.
이를 지원하기 위해 여러 새로운 기능이 추가되었습니다:
추가 기술적 변경 사항:
- <color>의 직렬화는 이제 CSS Object Model이 아닌 이곳에서 정의됨
- sRGB 색상을 HWB 표기법으로 지정하기 위한 hwb() 함수
- 이름 색상 rebeccapurple 추가
문법적 변화도 있습니다:
- rgb() 및 rgba() 함수는 이제 <number> 값을 받아들임 (<integer> 대신).
- hsl() 및 hsla() 함수는 색상(Hue)에 <angle>과 <number> 모두 허용
- rgb(), rgba(), hsl(), hsla()는 이제 서로의 별칭(alias)임 (모두 선택적 alpha를 가질 수 있음).
- rgb(), rgba(), hsl(), hsla() 모두 공백으로 구분된 인자와 선택적 슬래시(/)로 구분된 불투명도(opacity) 구문을 사용할 수 있음. 모든 색상 함수가 이 구문을 따름. CSS의 함수형 표기 디자인 원칙에 맞게 변경됨.
- <alpha-value> 사용 시 <percentage>와 <number> 모두 허용
- 투명도를 지정할 수 있도록 4자리, 8자리 hex 색상 추가
- 무력(powerless) 컴포넌트를 나타내는 none 값 추가
20. 보안 고려 사항
시스템 색상은 실제로 사용자의 시스템 색상과 일치한다면 보안 위험이 있습니다. 악성 사이트가 시스템에서 제공하는 것처럼 보이는 사용자 인터페이스를 만들기 쉬워지기 때문입니다. 하지만 이제 여러 시스템 색상이 "일반적"으로 정의되었으므로, 이러한 위험은 완화된 것으로 여겨집니다.
21. 프라이버시 고려 사항
이 명세는 "시스템" 색상을 정의하며, 이론적으로 사용자의 OS 설정 정보를 노출할 수 있고, 이는 지문채취(fingerprinting) 위험이 있습니다.
22. 접근성 고려 사항
이 명세는 저자들이 색상만으로 구분하는 것을 피할 것을 권장합니다.
이 명세는 브라우저가 특정 시스템 색상 전경/배경 조합에 대해 충분한 대비를 보장할 것을 권장합니다. AA 또는 AAA 대비 비율을 구체적으로 요구하는 것은 고려되었으나, 브라우저가 종종 OS에서 선택한 색상이나 사용자가 직접 선택한 색상을 그대로 전달하기 때문에, (편두통이나 간질 등으로 낮은 대비를 원하는 사용자를 포함하여) CSSWG에서는 특정 대비 수준을 요구할 수 없었습니다.