CSS 값과 단위 모듈 레벨 5

W3C 워킹 드래프트,

이 문서에 대한 자세한 정보
현재 버전:
https://www.w3.org/TR/2024/WD-css-values-5-20241111/
최신 공개 버전:
https://www.w3.org/TR/css-values-5/
에디터스 드래프트:
https://drafts.csswg.org/css-values-5/
역사:
https://www.w3.org/standards/history/css-values-5/
피드백:
CSSWG 이슈 저장소
명세 내 인라인
에디터:
Tab Atkins (Google)
Elika J. Etemad / fantasai (Apple)
Miriam E. Suzanne (초빙 전문가)
이 명세에 대한 수정 제안:
GitHub 에디터
테스트 스위트:
https://wpt.fyi/results/css/css-variables/

요약

이 CSS 모듈은 CSS 속성이 허용하는 공통 값과 단위, 그리고 CSS 속성 정의에서 이를 설명하는 데 사용되는 구문을 설명합니다.

CSS는 구조화된 문서(HTML, XML 등)를 화면, 인쇄물 등에서 렌더링하는 방식을 기술하는 언어입니다.

이 문서의 상태

이 섹션은 이 문서가 발행된 시점의 상태를 설명합니다. 현행 W3C 발행물 목록 및 이 기술 보고서의 최신 버전은 W3C 기술 보고서 색인 https://www.w3.org/TR/에서 확인할 수 있습니다.

이 문서는 CSS 작업 그룹에 의해 워킹 드래프트로, 권고 트랙에 따라 발행되었습니다. 워킹 드래프트로 발행되었다고 해서 W3C 및 그 회원의 승인이나 보증이 있음을 의미하지 않습니다.

이 문서는 초안이며, 언제든지 다른 문서로 갱신, 대체, 폐기될 수 있습니다. 진행 중인 작업 외로 이 문서를 인용하는 것은 부적절합니다.

피드백은 GitHub 이슈로 등록(권장)하거나, 제목에 사양 코드 “css-values”를 포함해서, 예: “[css-values] …코멘트 요약…”와 같이 남겨 주세요. 모든 이슈와 코멘트는 아카이브됩니다. 또는 (아카이브됨) 공개 메일링 리스트 www-style@w3.org로 보낼 수도 있습니다.

이 문서는 2023년 11월 3일 W3C 프로세스 문서의 적용을 받습니다.

이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성되었습니다. W3C는 해당 그룹 결과물과 관련된 공개 특허 공개 목록을 유지하고, 그 페이지에는 특허 공개 방법에 대한 안내도 포함되어 있습니다. 특정 특허가 필수 청구항을 포함한다고 판단하는 자는 W3C 특허 정책 6절에 따라 공개해야 합니다.

이 명세는 초창기 탐색 단계에 있습니다. 피드백은 언제든 환영하며, 중대한 파괴적인 변경도 있을 수 있습니다.

1. 소개

이 명세는 CSS 값과 단위 레벨 4에 대한 변경(diff) 명세입니다.

1.1. 모듈 상호작용

이 모듈은 [CSS-VALUES-4]를 확장하며, 이는 [CSS21]1.4.2.1, 4.3, A.2 섹션의 데이터 타입 정의를 대체 및 확장합니다.

2. 텍스트 데이터 타입

CSS Values 4 § 4 Textual Data Types 참고.

3. 값 정의 구문

CSS Values 4 § 2 Value Definition Syntax 참고.

또한,

  1. 조건부 표기(conditional notation)의 불리언 조합. 이는 <boolean-expr[]> 표기를 사용하여 작성되며, 괄호와 키워드를 이용한 불리언 논리의 재귀적 표현을 나타냅니다. 대괄호 안에 명세된 문법에 적용되며, 예: <boolean-expr[ ( &lt;media-feature&gt; ) ]>를 사용해 미디어 쿼리를 표현합니다.

3.1. 함수 표기 정의

CSS Values 4 § 2.6 Functional Notation Definitions 참고.

3.1.1. 함수 인자 내 콤마

함수 표기는 내부 문법의 일부를 구분하기 위해 흔히 콤마를 사용합니다. 그러나, 일부 함수(예: mix()) 는 자체적으로 콤마를 포함할 수 있는 값들을 허용합니다. 이러한 값들(<whole-value>, <declaration-value>, <any-value>) 는 콤마 포함 생산식입니다.

이런 문법을 명확하게 지원하기 위해 콤마 포함 생산식은 중괄호 {}로 감쌀 수 있습니다. 이 괄호는 문법적 용도이며 실제 값에 포함되지 않습니다. 구체적으로:

예를 들어, random-item() 함수의 문법은 다음과 같습니다:
random-item( <random-caching-options>, [<declaration-value>?]# )

# 표시는 콤마로 구분된 반복을 의미하므로, 예를 들어 세 개의 키워드 중 하나를 무작위로 선택하려면, 함수의 일반적인 형식으로 다음과 같이 작성합니다:

font-family: random-item(--x, serif, sans-serif, monospace);

그러나, 값에 콤마가 포함되어야 하는 경우가 있으며, 이럴 때 값들을 {}로 감싸면, 해당 콤마와 함수 인자 구분 콤마를 구분할 수 있습니다:

font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace});

이 코드는 세 가지 font-family 리스트 중 하나를 무작위로 선택합니다: Times, serif, Arial, sans-serif, Courier, monospace 중 하나입니다.

이것은 반드시 전부일 필요는 없고, 필요한 인자만 {}로 감싸고, 필요 없는 경우는 그대로 둘 수 있습니다. 또, 꼭 필요하지 않아도 {}를 둘러도 무방합니다. 예시:

font-family: random-item(--x, {Times, serif}, sans-serif, {monospace});

이 경우 선택지는 Times, serif, sans-serif, monospace 입니다.

단, 이 {} 감싸기는 일부 함수 인자에만 허용됩니다—콤마 포함 생산식으로 정의된 경우만 가능합니다. 다른 생산식에서는 유효하지 않으며, {}로 감싸면 함수 문법 일치에 실패해 무효가 됩니다. 아래는 잘못된 예시입니다:

background-image: linear-gradient(to left, {red}, magenta);

참고: {} 감싸기가 꼭 필요하지 않아도 허용되므로, 임의 값 대입 함수 (예: var())로 인해 값에 콤마가 포함될지 아닐지 확실치 않을 때, 방어적으로 {}로 감쌀 수 있습니다. 예를 들어 font-family: random-item(--x, {var(--list1)}, monospace) 구문은 --list1 커스텀 속성에 콤마가 포함되어 있는지에 상관없이 제대로 동작합니다.

함수 표기는 가능하다면 {} 감싸기 없이 직렬화됩니다.

다음 제네릭 생산식들이 콤마 포함 생산식입니다:

레거시 호환을 위해, <declaration-value>var()의 fallback 값으로 쓰일 때 비엄격 콤마 포함 생산식입니다. "{"로 시작하지 않아도 제한 없이 콤마와 {} 블록을 포함할 수 있습니다. 다만 "{"로 시작하면 한정된 {} 블록 내용만 취급하며 표준 콤마 포함 생산식 규칙을 따릅니다: fallback은 {} 블록의 내용이고, {} 자체는 포함되지 않습니다.

다른 문맥도 비엄격 콤마 포함 생산식을 사용할 수도 있으나, 꼭 필요한 경우에만 사용해야 합니다.

3.2. 불리언 식 반복자 <boolean-expr[]>

여러 문맥(예: @media, @supports, if() 등)은 조건을 명세할 때 불리언 논리(and/or/not/그룹화)와의 결합을 허용합니다. 같은 비단순 재귀 구문 구조를 공유하므로, 특별한 <boolean-expr[]> 생산식이 이런 패턴을 일반화시킵니다.

<boolean-expr[]> 표기는 내부의 값 타입을 대괄호로 감싸고, 예: <boolean[ <test> ]>, 단일 값뿐 아니라, not, and, or 키워드 및 그룹 괄호를 활용해 불리언 조합을 지원합니다. 형식적으로 다음과 같습니다:

<boolean-expr[ <test> ]> = not <boolean-expr-group> | <boolean-expr-group>
                                            [ [ and <boolean-expr-group> ]*
                                            | [ or <boolean-expr-group> ]* ]

<boolean-expr-group> = <test> | ( <boolean-expr[ <test> ]> ) | <general-enclosed>

<boolean-expr[]> 생산식은 참, 거짓 또는 알 수 없음(unknown) 값을 나타냅니다. 3값 Kleene 논리로 해석되며, 최상위 unknown 값(다른 <boolean-expr[]> 구문에 직접적으로 중첩되지 않은 경우)은 별도 명시가 없다면 false로 판정됩니다. 자세한 내용은 부록 B: 불리언 논리 참고.

예를 들어 @container 규칙은 크기 쿼리, 스타일 쿼리, 스크롤 상태 쿼리 등 다양한 테스트를 허용합니다. 이 모든 쿼리는 불리언 논리로 임의로 결합 가능합니다. <boolean-expr[]>@container 쿼리의 문법은 다음과 같이 작성할 수 있습니다:
<container-query> = <boolean-expr[ <cq-test> ]>
<cq-test> = (<size-query>) | style( <style-query> ) | scroll-state( <scroll-state-query> )
<size-query> = <boolean-expr[ ( <size-feature> ) ]> | <size-feature>
<style-query> = <boolean-expr[ ( <style-feature> ) ]> | <style-feature>
<scroll-state-query> = <boolean-expr[ ( <scroll-state-feature> ) ]> | <scroll-state-feature>

<general-enclosed> 로직 분기는 미래 호환성을 위한 것으로—별도 명시가 없다면, 이전 UA에서는 새로운 식을 “unknown”으로 간주해 생산식을 무효화하지 않고 파싱하게 해줍니다. 이에 맞춰, <boolean-expr[]><test> 항목은 <general-enclosed>까지 포함할 수 있도록 정의해야 합니다.

3.3. CSS 내 구문 지정: <syntax> 타입

CSS의 일부 기능(예: attr() 함수나 등록된 커스텀 속성)은 다른 값을 어떻게 파싱할지 명세할 수 있도록 허용합니다. 이는 <syntax> 생산식으로 선언하며, 명세에서 CSS 기능을 정의할 때 사용하는 CSS 값 정의 구문의 제한된 형태와 유사하고, 구문 정의를 나타냅니다:

<syntax> = '*' | <syntax-component> [ <syntax-combinator> <syntax-component> ]* | <syntax-string>
<syntax-component> = <syntax-single-component> <syntax-multiplier>?
                   | '<' transform-list '>'
<syntax-single-component> = '<' <syntax-type-name> '>' | <ident>
<syntax-type-name> = angle | color | custom-ident | image | integer
                   | length | length-percentage | number
                   | percentage | resolution | string | time
                   | url | transform-function
<syntax-combinator> = '|'
<syntax-multiplier> = [ '#' | '+' ]

<syntax-string> = <string>

<syntax-component>는 <> (각괄호) 안의 <syntax-type-name> 나열(지원하는 구문 구성요소 이름과 매핑됨), 혹은 <ident> (키워드 의미) 중 하나로 구성됩니다. 그리고 <syntax-component>에는 반복자(multiplier)를 붙일 수 있어, 값 리스트임을 의미할 수 있습니다.

참고: <length>length는 서로 다른 타입입니다. 전자는 <length>, 후자는 length 키워드를 의미합니다.

여러 <syntax-component>들은 | <delim-token>으로 조합할 수 있으며, 명시된 순서에 따라 값을 매칭합니다.

<percentage> | <number> | auto

위 구문을 <syntax>로 파싱하면, <percentage> 값, <number> 값, 그리고 auto 키워드를 허용합니다.

red | <color>

구문 정의<syntax>에 따라 파싱 시 red식별자로, blue<color>로 해석됩니다.

* <delim-token>범용 구문 정의를 의미합니다.

<transform-list> 생산식은 <transform-function>+와 동등한 축약형입니다. 참고: <transform-list> 뒤에는 <syntax-multiplier>가 올 수 없습니다.

공백은 각괄호 <delim-token> (< >)와 그 안의 <syntax-type-name> 사이에 허용되지 않으며, <syntax-multiplier> 앞에도 공백이 허용되지 않습니다.

참고: 공백 제한은 <transform-list>에도 적용됩니다.

<syntax-string><string> 값이 CSS 문법에 따라 파싱되어 유효할 때, 동일한 의미로 값이 해석됩니다.

참고: <syntax-string>은 주로 호환성 때문에 존재합니다. <syntax> 정의 전까지 @property 규칙에서 이 용도에 <string> 타입이 사용됐습니다.

3.3.1. <syntax>로 파싱하기

<syntax>의 목적은 보통 다른 값을 어떻게 파싱할지 규정하는 것입니다 (예: 등록된 커스텀 속성의 값, 또는 attr() 함수에서 속성 값 등). 하지만, 일반적인 CSS 문법 파싱 알고리즘은 파싱 결과가 모호하거나 가공이 필요할 수 있어 명확한 내부 구조를 리턴하지 않습니다.

이 문제를 피하고 명확한 결과를 얻으려면, <syntax>로 파싱하기를 사용하세요:

<syntax>로 파싱하기를 사용하려면, 문자열, 리스트, 또는 component values values<syntax>syntax, 옵션으로 문맥용 element el을 받아 다음 단계를 수행합니다. 리턴값은 CSS 값 또는 보장-무효 값 중 하나입니다.
  1. component values 리스트 파싱을 통해 values를 파싱하고, 결과를 raw parse에 할당합니다.

  2. el이 있을 경우 임의 값 대입 함수 치환raw parse에 수행하고, 결과를 raw parse로 재설정합니다.

  3. CSS 문법 파싱을 사용해 valuessyntax에 따라 파싱합니다. * 값은 <declaration-value>?로 취급, parsed result에 결과를 할당합니다. syntax| 결합자가 있을 경우, parsed result는 처음 일치하는 분기의 결과입니다.

  4. 만약 parsed result가 실패이면, 보장-무효 값을 반환.

  5. 단언: parsed result는 현재 1개 이상의 CSS 값으로 구성된 명확한 리스트임. (<syntax> 각 분기나 * 구문이 모호하지 않게 정의됨)

  6. parsed result를 반환

참고: 본 알고리즘은 파싱된 값을 계산값(computed value)으로 해석하지 않습니다. 값이 쓰이는 맥락에서 일반적으로 계산이 이루어지므로, 그렇지 않은 경우 호출측 알고리즘이 직접 처리해야 합니다.

4. 레벨 4 값 타입에 대한 확장

CSS 값과 단위 레벨 4 참고.

4.1. 리소스 식별자: <url> 타입

CSS Values 4 § 4.5 리소스 식별자: <url> 타입 참고.

4.1.1. 요청 URL 수정자

<request-url-modifier><url-modifier><url> 리소스의 request에 연관된 URL 요청 수정 단계를 적용하여 영향을 주는 것들입니다. CSS Values 4 § 4.5.4 URL 처리 모델 참고.

이 명세는 다음의 <request-url-modifier>들을 정의합니다:

<request-url-modifier> = <crossorigin-modifier> | <integrity-modifier> | <referrerpolicy-modifier>
<crossorigin-modifier> = crossorigin(anonymous | use-credentials)
<integrity-modifier> = integrity(<string>)
<referrerpolicy-modifier> = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url)
<crossorigin-modifier> = crossorigin(anonymous | use-credentials)
이 수정자에 대한 URL 요청 수정 단계request req가 주어졌을 때 아래와 같습니다:
  1. requestmode를 "cors"로 설정합니다.

  2. 값이 use-credentials인 경우, requestcredentials mode를 "include"로 설정합니다.

<integrity-modifier> = integrity(<string>)
이 수정자에 대한 URL 요청 수정 단계request req에 대해 주어진 <string> 값을 requestintegrity metadata로 설정합니다.
<referrerpolicy-modifier> = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url)
이 수정자의 URL 요청 수정 단계request req에 대해, 주어진 값을 일치하는 ReferrerPolicyreferrer policy로 설정하는 것입니다.
URL 값의 요청 수정자 적용 알고리즘: request req<url> url이 주어지면, req를 인자로 하여 url에 명시된 <request-url-modifier> 각각의 URL 요청 수정 단계를 순서대로 호출합니다.

4.2. 2D 위치 지정: <position> 타입

<position> 값은 정렬 대상 (예: 배경 이미지)의 위치를 정렬 컨테이너 (예: background positioning area) 내부에서 기본적으로 왼쪽, 위쪽 엣지를 기준으로 두 엣지 사이의 오프셋 쌍으로 지정합니다. 구문은 아래와 같습니다:

<position> = <position-one> | <position-two> | <position-four>
<position-one> = [
  left | center | right | top | bottom |
  x-start | x-end | y-start | y-end |
  block-start | block-end | inline-start | inline-end |
  <length-percentage>
]
<position-two> = [
  [ left | center | right | x-start | x-end ] &&
  [ top | center | bottom | y-start | y-end ]
|
  [ left | center | right | x-start | x-end | <length-percentage> ]
  [ top | center | bottom | y-start | y-end | <length-percentage> ]
|
  [ block-start | center | block-end ] &&
  [ inline-start | center | inline-end ]
|
  [ start | center | end ]{2}
]
<position-four> = [
  [ [ left | right | x-start | x-end ] <length-percentage> ] &&
  [ [ top | bottom | y-start | y-end ] <length-percentage> ]
|
  [ [ block-start | block-end ] <length-percentage> ] &&
  [ [ inline-start | inline-end ] <length-percentage> ]
|
  [ [ start | end ] <length-percentage> ]{2}
]

값이 하나만 지정된 경우(<position-one>), 두 번째 값은 center로 간주합니다.

값이 두 개일 경우(<position-two>), 첫 번째 값 if <length-percentage>이면 정렬 대상정렬 컨테이너의 왼쪽 엣지 사이 수평 오프셋을, 두 번째 값이 <length-percentage>이면 위쪽 엣지 사이 수직 오프셋을 의미합니다.

두 키워드가 모두 startend인 경우, 첫 번째는 block 축, 두 번째는 inline 축을 나타냅니다.

참고: 축 관련 키워드 쌍은 순서를 바꿀 수 있지만, 키워드와 길이/백분율 조합은 순서를 바꿀 수 없습니다. 따라서 center left 또는 inline-start block-end는 허용되지만, 50% left는 허용되지 않습니다. startend는 축이 정해져 있지 않으므로 start endend start는 서로 다른 위치를 나타냅니다.

값이 네 개면(<position-four>) 각 <length-percentage>는 앞에 오는 키워드로 지정된 엣지 사이의 오프셋을 나타냅니다. 예시로 background-position: bottom 10px right 20px은 아래쪽 엣지에서 위로 10px, 오른쪽 엣지에서 왼쪽으로 20px 만큼 오프셋을 둡니다.

양수 값은 정렬 컨테이너의 엣지로부터 내부로의 오프셋을 의미합니다. 음수 값은 정렬 컨테이너의 엣지로부터 외부로의 오프셋을 의미합니다.

다음 선언들은 왼쪽 위 모서리로부터 지정 방향(수평, 수직) 오프셋을 의미합니다:
background-position: left 10px top 15px;   /* 10px, 15px */
background-position: left      top     ;   /*  0px,  0px */
background-position:      10px     15px;   /* 10px, 15px */
background-position: left          15px;   /*  0px, 15px */
background-position:      10px top     ;   /* 10px,  0px */
<position> 값은 왼쪽 위 모서리 이외 다른 모서리를 기준으로 지정할 수도 있습니다. 예를 들어 아래 선언은 배경 이미지를 아래에서 10px, 오른쪽에서 3em 만큼 띄웁니다:
background-position: right 3em bottom 10px

계산값(computed value)으로서 <position>의 값은 각각 <length-percentage>로 주어진 수평 및 수직 오프셋 쌍이며, 정렬 대상정렬 컨테이너의 각각 왼쪽, 위쪽 엣지 간 거리를 나타냅니다.

<length-percentage>
<length-percentage> 값은 정렬 대상정렬 컨테이너의 지정 엣지 간 오프셋 크기를 지정합니다.

예: background-position: 2cm 1cm의 경우, 배경 이미지의 왼쪽 위 모서리는 background positioning area의 왼쪽 위에서 오른쪽으로 2cm, 아래로 1cm 떨어진 곳에 위치합니다.

수평 방향 <percentage> 값은 (정렬 컨테이너 너비 - 정렬 대상 너비)에 상대적입니다. 수직 방향 <percentage> 값은 (정렬 컨테이너 높이 - 정렬 대상 높이)에 상대적입니다.

값 쌍이 0% 0%이면 정렬 대상의 왼쪽 위 모서리가 정렬 컨테이너의 왼쪽 위 모서리에 정렬됩니다. 값 쌍 100% 100%정렬 대상의 오른쪽 아래 모서리를 정렬 컨테이너의 오른쪽 아래 모서리에 맞춥니다. 값 쌍 75% 50%정렬 대상의 가로 75%, 세로 50% 지점이 정렬 컨테이너의 가로 75%, 세로 50% 지점에 위치하게 됩니다.
요소 내 이미지 위치를 보여주는 다이어그램
background-position: 75% 50% 의 의미 다이어그램.
top
right
bottom
left
각 엣지(top/left/right/bottom)에 해당하는 (기본 0%) 오프셋을 정렬 대상정렬 컨테이너에 지정합니다.
y-start
y-end
x-start
x-end
해당 축에서 start/end 쪽의 물리적 엣지와 동일하게 처리합니다.
block-start
block-end
inline-start
inline-end
해당 block/inline 축에서 start/end 쪽의 물리적 엣지와 동일하게 처리합니다.
center
해당 축에서 50% 오프셋으로 계산됩니다.

별도 명시가 없는 한, 흐름-상대 키워드는 값이 지정된 요소의 writing mode에 따라 해석됩니다.

참고: background-position 속성은 3값 구문도 허용합니다. 그러나, 다른 길이 또는 백분율 컴포넌트와 조합할 때 파싱의 모호성이 발생하기 때문에 3값 구문은 일반적으로 허용되지 않습니다.

var()가 일부(또는 전체) 컴포넌트에 사용된 경우 등 background-position 롱핸드로 어떻게 확장되는지 정의 필요. [이슈 #9690]

4.2.1. <position> 파싱

다른 키워드, <length> 또는 <percentage> 등과 문법 내에 함께 쓰일 때, <position>그리디하게 파싱됩니다. 가능한 최대한 많은 컴포넌트를 소모합니다.

예: transform-origin은 (사실상) <position> <length>? 형태의 3D 위치를 정의합니다. left 50px 값은 z 컴포넌트가 생략된 2값 <position>로 파싱됩니다. 반면 top 50px 값은 1값 <position> + <length>로 해석됩니다.

4.2.2. <position> 직렬화

지정값(specified value)으로 <position>을 직렬화할 때:

컴포넌트 하나만 지정된 경우:
  • 암시적인 center 키워드를 추가하여 2-컴포넌트 값으로 직렬화합니다.

컴포넌트 2개 지정된 경우:
  • 키워드는 키워드 자체로 직렬화합니다.

  • <length-percentage><length-percentage>로 직렬화합니다.

  • 컴포넌트 순서는 항상 "수평, 수직"입니다.

컴포넌트 4개 지정된 경우:
  • 키워드, 오프셋 모두 직렬화합니다.

  • 컴포넌트 순서는 "수평→수직" 또는 block축→inline축 순서도 가능합니다.

참고: <position> 값은 단일 값이어도 단일 값으로 직렬화되지 않습니다. <position><length> 등과 연결되는 문법 일부에서 파싱 모호성이 발생하는 것을 방지하기 위함입니다(예: transform-origin).

계산값으로서 <position>은 왼쪽, 위쪽 엣지 기준 오프셋 <length-percentage> 쌍으로 직렬화됩니다.

4.2.3. <position> 값 결합

보간(Interpolation)<position>의 각 컴포넌트(x, y)를 독립적으로, 왼쪽 위 모서리 기준 오프셋 <length-percentage>로 정규화하여 처리합니다.

덧셈(addition)<position>의 각 컴포넌트(x, y)를 독립적으로, 왼쪽 위 모서리 기준 오프셋 <length-percentage>로 정규화하여 덧셈(addition)을 적용합니다.

5. 보간 진행(progress) 함수 표기

본 절은 초기 탐색용 초안이며, CSSWG의 승인을 받지 않았습니다. [이슈 #6245]

progress(), media-progress(), container-progress() 함수 표기는 주어진 값(진행값(progress value))이 한 값(시작값(progress start value))에서 다른 값(끝값(progress end value))까지 상대적으로 어느 만큼 진행됐는지 비율을 나타냅니다. 각각 수학 함수, 미디어 특성, 컨테이너 특성에 대해 대응하며, 공통적인 문법 패턴을 따릅니다:

progress-function() = progress-function( progress value from start value to end value )

각 함수는 <number> 값으로 progress 함수 계산을 통해 해석됩니다.

progress 함수 계산을 하려면, 진행값, 시작값, 끝값이 주어졌을 때:
시작값끝값이 다른 값인 경우

(진행값 - 시작값) / (끝값 - 시작값)으로 계산합니다.

시작값끝값이 같은 값인 경우

공유된 값과 진행값이 같은지, 더 작은지, 더 큰지에 따라 0, -∞, +∞ 중 하나로 합니다.

참고: 반환값은 순수 <number>이며, 기본적으로 인자들과 타입 일치(made consistent) 처리는 하지 않습니다.

결과로 얻은 수치는 수학 함수mix 표기 등 다른 계산식에 입력할 수 있습니다.

5.1. 계산된 진행 값: progress() 표기

progress() 함수 표기는 한 <number> 값을 반환하며, 이 값은 한 계산식(즉, 진행값)이 다른 두 계산식(즉, 시작값끝값) 사이 어디쯤에 위치하는지 비율로 나타냅니다. progress()수학 함수입니다.

progress()의 문법은 다음과 같습니다:

<progress()> = progress(<calc-sum>, <calc-sum>, <calc-sum>)

여기서 첫 번째, 두 번째, 세 번째 <calc-sum>은 각각 진행값, 시작값, 끝값을 의미합니다.

인자인 계산식<number>, <dimension>, <percentage> 모두 사용 가능하나, 타입 일치(consistent type)가 반드시 맞아야 하며, 그렇지 않으면 함수는 무효입니다.

progress()의 값은 <number>이며, progress 함수 계산을 거친 뒤, 인자들의 타입 일치에 맞춰 타입 일치(made consistent)가 적용된 값입니다.

percent-progress() 표기가 필요할까, 아니면 충분히 자동 변환되므로 필요 없을까?

참고: progress() 함수는 사실상 특정 calc() 패턴의 구문적 설탕(syntactic sugar)이므로 수학 함수 취급을 받습니다.

5.2. 미디어 쿼리 진행 값: media-progress() 표기

progress() 표기와 비슷하게, media-progress() 함수 표기는 지정한 미디어 쿼리 [MEDIAQUERIES-4]의 현재 값을 두 명시적 값(시작값, 끝값) 사이에서 진행값으로 표현하여, <number> 값으로 반환합니다.

media-progress()의 문법은 다음과 같습니다:

<media-progress()> = media-progress(<mf-name>, <calc-sum>, <calc-sum>)

여기서 media feature명(<mf-name>)이 진행값이 되고, 두 개의 <calc-sum>은 각각 시작값끝값을 의미합니다.

지정된 media feature는 “range” 타입이어야 하며, 시작값, 끝값 모두 지정된 미디어 쿼리에 대해 유효한 값이어야 합니다. 또 두 개 계산식 값이 타입 일치해야 하며, 아니면 함수는 무효입니다.

시작값, 끝값에 대한 계산식 해석은, 함수가 실제 사용되는 맥락이 아닌 해당 media feature에 따라 해석해야 합니다.

media-progress()의 값은 <number>이며, progress 함수 계산을 통해 얻습니다.

참고: media-progress()수학 함수가 아니며, 단순히 <number> 값을 계산하는 함수입니다.

5.3. 컨테이너 쿼리 진행 값: container-progress() 표기

container-progress() 함수 표기는 media-progress() 함수 표기와 동일하나, 컨테이너 특성 [CSS-CONTAIN-3]media feature 대신 사용합니다.

container-progress()의 문법은 아래와 같습니다:

<container-progress()> = container-progress(<mf-name> [ of <container-name> ]?, <calc-sum>, <calc-sum>)

<mf-name>size feature를 의미하며, 선택적 <container-name>은 어떤 컨테이너를 사용할지 이름으로 지정할 수 있습니다. size feature의 값이 진행값이며, 두 <calc-sum> 값으로 각각 시작값끝값을 지정합니다.

<mf-name>은 반드시 유효한 size feature이어야 하며, 시작값, 끝값 모두 해당 size feature에 대해 유효한 값이어야 하고, 두 계산식타입 일치해야 합니다. container-progress()는 프로퍼티 값 문맥에서만 유효하며, media query 등에서는 사용할 수 없습니다.

시작값, 끝값계산 해석은, 함수가 사용된 맥락이 아니라 해당 size feature 기준으로 해석해야 합니다. 적합한 컨테이너가 없다면, container-progress()<size-feature> 쿼리를 소뷰포트 크기에 대해 평가합니다.

media-progress()의 값은 <number>이며, progress 함수 계산을 통해 결정됩니다.

참고: container-progress()수학 함수가 아니며, <number> 값을 계산할 뿐입니다.

6. 혼합 및 보간 표기: *-mix() 계열

이 기능은 여러 중단점(multiple breakpoints)을 잘 처리하지 못합니다, 및 재설계가 필요할 수 있습니다. [Issue #6245]

CSS의 여러 mix 표기법은 두 값의 보간을 표현할 수 있으며, 주어진 진행점에서의 mix 시작값mix 종료값, (즉 mix 진행값)을 나타냅니다. 이러한 함수 표기법(functional notations)은 다음 문법 패턴을 따릅니다:

mix-function() = mix-function( <progress>, [=mix start value|start-value=], [=mix end value|end-value=] )

CSS의 mix 표기법에는 다음이 포함됩니다:

그리고 마지막으로, 임의의 속성 값(단, 속성의 전체 값만, 개별 구성 요소는 아님)의 보간을 나타낼 수 있는 일반적인 mix() 표기법이 있습니다.

Note: cross-fade() 표기법에는 두 값 이상을 혼합할 수 있는 대체 문법이 존재하지만, <progress>의 복잡한 표현은 허용하지 않습니다.

mix() 표기법에는 키프레임 집합을 인수로 받는 변형이 있습니다. 이는 특정 @keyframes 규칙을 참조하고, 해당하는 속성 선언을 추출합니다. 다른 mix 표기법들도 키프레임을 받을 수 있게 하는 것이 좋겠지만, 전체 속성 값이 아닌 구성 요소 값에 대해 키프레임 집합을 어떻게 표현할지에 대한 문제가 있습니다.

6.1. 보간 진행 표현: <progress> 타입

<progress> 값 타입은 mix 진행값을 나타내며, 궁극적으로는 백분율(percentage)로 해석됩니다. 그러나 미디어 쿼리나 애니메이션 타임라인과 같은 소스에서 해당 백분율 값을 가져올 수 있고, 보간 전에 이징 함수로 변환할 수도 있습니다.

문법은 다음과 같이 정의됩니다:

<progress> = [ <percentage> | <number> | <'animation-timeline'> ] && [ by <easing-function> ]?

여기서:

<percentage-token>
동등한 <number>로 계산됩니다: 0%0이 되고, 100%1이 됩니다 등.

Note: 이는 리터럴 백분율(literal percentages)만 허용합니다, 예: 15%; calc(100% / 7) 같은 계산식은 작동하지 않으며, 대신 다른 타입에 대해 백분율을 해석하는 일반 규칙을 따르려 시도합니다 (예: <length>, width의 경우). 대신 calc(1 / 7) 같은 표현을 사용하세요.

<number>
mix 진행값을 나타냅니다.

Note: 이는 progress(), media-progress(), 및 container-progress() 표기법의 사용을 허용합니다.

<'animation-timeline'>
지정된 애니메이션 타임라인의 진행으로서 mix 진행값을 나타냅니다. 다만 noneauto 값은 유효하지 않습니다. [CSS-ANIMATIONS-2] [WEB-ANIMATIONS-2]
<easing-function>
지정된 입력 mix 진행값이징 함수를 사용해 출력 mix 진행값으로 변환합니다. [CSS-EASING-1]

Note: 0 미만 및 1 초과의 진행값도 유효합니다; 이는 시작값과 종료값으로 정의된 범위를 넘는 보간을 표현할 수 있게 합니다.

Note: <progress> 자체는 <percentage>일 수 있으며, 등가의 <number>으로 매핑됩니다. 해결(resolves)되어 <number>가 되는 함수는, 예를 들어 progress()는 문맥의 일반 규칙에 따라 <percentage>들을 해결합니다; 예컨대 width에서는 길이에 대해 해석됩니다.

computed value로서, <progress> 값이 <percentage> 또는 <number>로 지정된 경우, 계산된 값은 <number>로 변환된 뒤 <easing-function> (있다면)에 의해 변환됩니다. computed value로서의 <progress> 값이 <'animation-timeline'>로 지정된 경우에는 계산된 값이 해당 <'animation-timeline'><easing-function> (있다면)입니다.

6.2. 수치 및 차원 값 보간: calc-mix() 표기법

calc-mix() mix 표기법은 수치 또는 차원 값의 보간을 나타냅니다. calc()처럼, 이는 수학 함수이며, 다음과 같은 문법 형태를 가집니다:

<calc-mix()> = calc-mix( <progress>, <calc-sum>, <calc-sum> )

<calc-sum> 인수들은 <number>, <dimension>, 또는 <percentage>로 계산될 수 있지만, 일관된 타입(consistent type)을 가져야 하며, 그렇지 않으면 함수는 무효입니다. 결과 타입은 일관된 타입이며, progress(<progress>) 값의 타입과 맞추어 조정됩니다.

유효한 calc-mix()used value는 이 두 값을 <progress>가 주는 진행도로 보간한 결과입니다. 만약 <progress> 값이 <number>로 계산될 수 있다면, computed value도 마찬가지로 두 computed values를 해당 <progress> 값으로 보간한 결과가 됩니다 (즉 A * (1-progress) + B * progress). 그렇지 않으면 각 인수가 그 타입에 따라 계산된 상태로 calc-mix() 표기법 자체가 계산된 값입니다.

6.3. 색상 값 보간: color-mix() 표기법

이 규격은 color-mix() 함수 표기법mix 표기법으로 확장하며, 다음 문법을 허용합니다:

<color-mix()> =
  color-mix( [ <progress> && <color-interpolation-method>? ] , <color>, <color> ) |
  color-mix( <color-interpolation-method>, [<color> && <percentage [0,100]>?]#{2} )

첫 번째 mix 표기법 변형의 used value는 두 번째 변형에서의 두 번째 <color> 인수의 <percentage><progress> 값을 할당한 것과 동등합니다. 즉, color-mix(progress, color1, color2)color-mix(color1, color2 progress)와 동등합니다. 두 번째 변형에 대한 규범적 정의는 CSS Color 5 § 3 Mixing Colors: the color-mix() Function을 참조하세요.

<progress>는 0–100% 범위를 벗어난 백분율을 반환할 수 있지만, color-mix()는 그러한 값을 허용하지 않으므로, 그 처리를 어떻게 할지 정의할 필요가 있습니다.

6.4. 이미지 값 보간: cross-fade() 표기법

이 규격은 cross-fade() 함수 표기법mix 표기법으로 확장하며, 다음 문법을 허용합니다:

<cross-fade()> =
  cross-fade( <progress>, [ <image> | <color> ], [ <image> | <color> ] ) |
  cross-fade( <cf-image># )

첫 번째 mix 표기법 변형의 used value는 두 번째 변형에서의 두 번째 <progress> 값을 두 번째 <color> 인수의 <percentage>로 할당한 것과 동등합니다. 즉, cross-fade(progress, image1, image2)cross-fade(image1, image2 progress)와 동등합니다. 두 번째 변형에 대한 규범적 정의는 CSS Images 4 § 2.6 Combining images: the cross-fade() notation을 참조하세요.

6.5. 변환(transform) 값 보간: transform-mix() 표기법

transform-mix() mix 표기법은 보간된 <transform-list>을 나타내며, 다음 문법 형태를 가집니다:

<transform-mix()> = transform-mix( <progress>, <transform-list>, <transform-list> )

used value로서 유효한 transform-mix()의 값은 이 두 값을 <progress>이 제공하는 진행도로 보간한 결과입니다. 만약 <progress> 값이 <percentage>로 계산될 수 있고, <transform-list>들이 used-value-time 정보 없이 보간될 수 있다면, computed value도 마찬가지로 그 computed values를 해당 <progress> 값으로 보간한 결과가 됩니다; 그렇지 않으면 각 인수가 그 타입에 따라 계산된 상태로 transform-mix() 표기법 자체가 계산된 값입니다.

transform-mix() 자체는 <transform-function>입니다.

6.6. 속성 값 보간: mix() 표기법

임의의 두 속성 값의 보간(Interpolation)mix() mix 표기법으로 표현할 수 있으며, 이 표기법은 두 가지 대체 문법 패턴을 지원합니다:

<mix()> =
  mix( <progress> , <whole-value> , <whole-value> ) |
  mix( <progress> && of <keyframes-name> )

첫 번째 문법 대안은 다른 mix 표기법처럼, 첫 번째 <whole-value> (그것의 mix 시작값)과 두 번째 <whole-value> (그것의 mix 종료값) 사이를 보간합니다. 두 번째 문법은 mix 진행값을 사용하여 키프레임 집합에서 해당 속성 선언들을 보간하므로 더 복잡한 보간 곡선을 허용합니다.

표준 mix 표기법 변형의 경우, 만약 mix()가 보간하는 두 <whole-value>가 지정된 속성의 값으로서 보간 가능(interpolable)하고, 보간된 값을 mix() 없이 표현할 수 있다면, mix()computed value는 이 두 값을 <progress>이 주는 진행도로 보간한 결과가 됩니다. 그렇지 않으면, mix()의 computed value는 해당 mix() 함수 표기법 자체이며, 그 <progress> 값은 계산되고, 제시된 <whole-value>들은 (제공되었다면) 이 속성의 값으로 계산됩니다.

예를 들어, 대부분의 mix() 사용은 computed-value 시에 해결됩니다:
color: mix(90%, red, blue);
/* via simple interpolation,
   computes to: */
color: rgb(10% 0 90%);

color: mix(90%, currentcolor, black);
/* can’t be fully resolved at computed-value time,
   but still has a defined representation: */
color: color-mix(currentcolor 90%, black 10%);

float: mix(90%, left, right);
/* discretely animatable */
float: right;

그러나 몇몇 경우는 중간 표현(intermediate representation)을 가지지 않습니다:

transform: mix(90%, translate(calc(1em + 50%)), rotate(30deg));
/* because functions don’t match, it will interpolate
   via matrix(). But translate(%) needs layout
   information to turn into a matrix(), so the
   interpolated value can’t actually be represented.
   Computes to: */
transform: mix(90%, translate(calc(16px + 50%)), rotate(30deg));
transform: mix(90% of ripple);

mix() 표기법은 <whole-value>입니다. 또한, 만약 그 어떤 <whole-value> 인수도 애니메이션 불가능(not animatable)하다면, 해당 표기법은 무효입니다.

예를 들어, 다음 선언들은 무효이며 무시됩니다:
/* Invalid start value */
color: mix(90%, #invalid, #F00);

/* Function is mixed with other values */
background: url(ocean) mix(10%, blue, yellow);

/* 'animation-*' is not animatable */
animation-delay: mix(0%, 0s, 2s);

7. 기타 값 치환 함수

7.1. 전체 속성 값을 표현하기: <whole-value> 타입

이 명세에서 정의된 몇몇 함수는 속성의 "전체 값"으로만 사용할 수 있습니다. 예를 들어, background-position: toggle(50px 50px, center);는 유효하지만, background-position: toggle(50px, center) 50px;는 유효하지 않습니다. <whole-value> 생성 규칙은 이러한 값을 나타냅니다.

모든 속성은 암시적으로 <whole-value>를 전체 값으로 허용합니다. 이는 CSS 전체 키워드를 전체 값으로 받아들이는 것과 동일합니다.

함수의 구성 값으로 사용될 때, <whole-value>도 해당 속성의 전체 값으로서 일반적으로 유효한 모든 CSS 값을 나타냅니다 (여기에는 추가적인 <whole-value> 함수가 포함될 수 있습니다). 그러나 일부 함수는 <whole-value> 인자가 포함할 수 있는 내용을 제한할 수 있습니다.

7.2. 지원되는 첫 번째 값 선택: first-valid() 표기법

CSS는 미래 호환 파싱을 통한 점진적 향상을 지원합니다: 작성자는 스타일 규칙에서 같은 속성을 여러 번 선언할 수 있으며, 그때마다 다른 값을 사용할 수 있습니다. CSS UA는 자동으로 마지막으로 이해할 수 있는 값을 사용하고 나머지는 버립니다. 이 원칙과 @supports 규칙을 활용하면 작성자가 새로운 UA와 오래된 UA 모두에서 잘 동작하는 스타일시트를 작성할 수 있습니다.

그러나 var() (또는 파싱 후에 해석되는 유사한 치환 함수)를 사용하면 이러한 기능이 방해받게 됩니다; CSS UA는 어떤 속성이든 파싱 시점에 유효하다고 가정해야만 합니다.

first-valid() 함수 표기법은 선언 파싱에 내재된 폴백 동작을 인라인으로 제공합니다. 대부분의 표기법과 달리, 인자에 유효하든 유효하지 않든 어떤 구문이든 받을 수 있으며, 인자 중 UA에서 지원되는(유효하게 해석되는) 첫 번째 값을 해당 속성의 전체 값으로 나타냅니다.

<first-valid()> = first-valid( <declaration-value># )

만약 인자 중 어느 것도 해당 속성에 대해 유효한 값을 나타내지 않는다면, 해당 속성은 computed-value 단계에서 무효가 됩니다.

first-valid()<whole-value>입니다.

이 이름을 다르게 해야 할까요? 추가 결의에서 이 부분을 확실히 결정하지 못했습니다.

참고: 인자로 실질적으로 <whole-value>를 받는 것 같지만, first-valid()는 오히려 <declaration-value>를 받는 것으로 정의되어 있습니다. 이는 "값이 선언에 대해 무효일 수 있는 경우"에 사용될 의도로 정의된 것이기 때문입니다. <declaration-value>는 자신이 대응하는 값에 대해 문맥적 유효성 제약을 두지 않지만, <whole-value>는 그렇지 않습니다.

7.3. 조건부 값 선택: if() 표기법

if() 표기법은 임의 치환 함수로, 조건부 값을 표현합니다. 인자는 순서가 있는 세미콜론으로 구분된 문장 리스트로, 각각 조건, 콜론, 값의 순서로 구성됩니다. if() 표기법은 인자 목록에서 처음으로 true가 되는 조건에 해당하는 값을 반환합니다. 어떤 조건도 일치하지 않으면, if() 표기법은 빈 토큰 스트림을 나타냅니다.

if() 표기법의 구문은 다음과 같이 정의됩니다:

<if()> = if( [ <if-condition> : <declaration-value>? ; ]*
             <if-condition> : <declaration-value>? ;? )
<if-condition> = <boolean-expr[ <if-test> ]> | else
<if-test> =
  supports( [ <supports-condition> | <ident> : <declaration-value> ] ) |
  media( <media-query> ) |
  style( <style-query> )

else 키워드는 항상 true인 조건을 나타냅니다.

if() 함수를 해석하다의 경우, true인 <declaration-value>?를 처음 만난 <if-condition>에 따라 반환합니다. 아무 조건도 true가 아니라면, 아무것도 반환하지 않습니다(빈 토큰 스트림).

참고: @media / @supports / @container 규칙과는 달리, false인 경우 내용을 단순히 무시하고 그 외 상황에서는 cascade에 따라 값을 결정하는 반면, if()가 있는 선언은 조건이 false여도 cascade를 되돌리지 않습니다; 어떤 폴백 값이든 인라인으로 지정해야 합니다.

7.4. 값 전환: toggle() 표기법

toggle() 표현식은 하위 요소가 부모와 동일한 값을 상속받는 대신 값 목록을 순환(cycle)하여 사용할 수 있게 합니다.

다음 예시는 <em> 요소가 일반적으로는 기울임꼴이지만, 이탤릭 텍스트 내에 있으면 보통체로 나타나게 만듭니다:
em { font-style: toggle(italic, normal); }
다음 예시는 중첩된 리스트의 마커를 순환시켜 최상위 리스트에는 disc 모양 마커를, 중첩 리스트에는 circle, 그다음은 square, 그리고 box를 사용하고, 5번째 이하 중첩부터는 다시 disc부터 반복합니다.
ul { list-style-type: toggle(disc, circle, square, box); }

toggle() 표현식의 구문은 다음과 같습니다:

<toggle()> = toggle( <whole-value># )

toggle() 표기법은 <whole-value>입니다. 하지만, 중첩될 수 없으며, attr() 또는 calc() 표기법을 포함할 수 없습니다. 이렇게 포함된 선언은 무효가 됩니다.

다음 toggle() 예시들은 모두 무효입니다:
background-position: 10px toggle(50px, 100px);
/* toggle()은 속성의 유일한 값이어야 함 */

list-style-type: toggle(disc, 50px);
/* 50px는 'list-style-type'의 유효한 값이 아님 */

toggle()의 computed value를 결정하려면, 먼저 각 인자가 해당 속성의 유일한 값일 때의 computed value를 평가해서 각 인자가 나타내는 값을 Cn이라 부릅니다. 그런 다음, 속성의 상속된 값과 각 Cn를 비교합니다. 가장 먼저 상속된 값과 일치하는 Cn이 있으면, toggle()의 computed value는 Cn+1이 됩니다. 만약 일치한 인자가 목록의 마지막 인자이거나, 매칭되는 값이 없다면, toggle()의 computed value는 첫 번째 인자가 나타내는 값이 됩니다.

참고: toggle() 내에서 값을 반복하면 목록을 단축시킨다는 의미입니다. 예를 들어 toggle(1em, 2em, 1em, 4em)toggle(1em, 2em)과 동등합니다.

참고: toggle()는 부모의 computed value를 명시적으로 참조하므로, 비상속 속성에도 동작합니다. 이는 inherit 키워드가 비상속 속성에도 동작하는 것과 비슷합니다.

참고: computed value는 속성의 특정 직렬화가 아니라 값의 추상 집합이므로 computed value 간의 비교는 항상 모호함 없이 예상한 결과를 가져야 합니다. 예컨대, Level 2 background-position의 computed value는 두 개의 오프셋(절대 길이 또는 퍼센트)일 뿐이므로, background-position: top centerbackground-position: 50% 0%는 동일한 computed value가 됩니다. 만약 속성 정의의 "Computed Value" 항목이 모호하거나 과도하게 엄격해 보이면, 피드백을 제공해 주세요.

toggle()약식 속성에서 사용되면, 각 longhand에 대해 toggle() 값을 할당하는데, 각 인자가 마치 약식 속성의 유일한 값이었던 것처럼 나뉘어 전달됩니다. (즉, longhand 별로 인자가 매핑됩니다.)

예를 들어, 다음과 같은 약식 선언은:
margin: toggle(1px 2px, 4px, 1px 5px 4px);

다음과 같은 longhand 선언과 같습니다:

margin-top:    toggle(1px, 4px, 1px);
margin-right:  toggle(2px, 4px, 5px);
margin-bottom: toggle(1px, 4px, 4px);
margin-left:   toggle(2px, 4px, 5px);

1px이 top margin에 두 번, 4px이 bottom margin에 두 번 등장하므로, 각각 두 가지 값만 순환하고 좌우 마진은 세 가지 값을 순환하게 됨을 유의하세요. 즉, 위의 선언들은 아래의 longhand 선언과 같은 계산 값을 가져옵니다:

margin-top:    toggle(1px, 4px);
margin-right:  toggle(2px, 4px, 5px);
margin-bottom: toggle(1px, 4px);
margin-left:   toggle(2px, 4px, 5px);

이는 의도와 다를 수도 있습니다.

7.5. 커스텀 속성 참조: var() 표기법

var() 표기법은 커스텀 속성의 값을 대체합니다. 자세한 내용은 CSS 커스텀 속성 모듈을 참조하세요. [CSS-VARIABLES]

7.6. 상속 값 참조: inherit() 표기법

inherit 키워드와 마찬가지로, inherit() 함수 표기법은 부모의 computed value로 해석됩니다. 그러나 동일한 속성의 값이 아니라, 첫 번째 인자로 지정된 속성의 토큰화된 computed value로 해석됩니다. 두 번째 인자가 있는 경우, 첫 인자가 보장된 무효 값으로 해석될 때 폴백으로 사용됩니다.

inherit()임의 치환 함수이며, 구문은 다음과 같이 정의됩니다:

<inherit()> = inherit( <custom-property-name>, <declaration-value>? )

inherit() 함수를 해석하다의 경우, 첫 번째 인자로 지정된 커스텀 속성에 대한 상속 값을 반환하며, (지정된 경우) 두 번째 인자가 폴백으로 사용됩니다.

참고: 향후 CSS 레벨에서는 inherit()에서 표준 CSS 속성을 지정할 수 있게 할 수 있습니다. 하지만 모든 CSS 속성에 대해 computed value의 토큰화가 완전하게 표준화되지 않았으므로 이 기능은 5단계에서는 보류되었습니다. computed valueused value와 다르며, getComputedStyle()로 반환되는 resolved value와 항상 같지 않을 수 있습니다. 따라서 inherit(width)를 허용하더라도, 자주 키워드 auto가 반환되고, 실제 <length>는 반환되지 않을 수 있습니다.

7.7. 속성 참조: attr() 표기법

attr() 함수는 attribute의 값을 element의 속성에 치환합니다. 이는 var() 함수가 커스텀 속성 값을 함수에 치환하는 것과 유사합니다.

attr() = attr( <attr-name> <syntax>? , <declaration-value>?)

<attr-name> = [ <ident-token> '|' ]? <ident-token>

attr() 인자는 다음과 같습니다:

<attr-name>

참조되는 속성의 이름을 지정합니다. 이는 <wq-name> (from [SELECTORS-3])과 비슷하지만 와일드카드 접두사를 사용할 수는 없습니다.

네임스페이스가 명시되지 않은 경우 (예: attr(foo)처럼 식별자만 제공된 경우), 널 네임스페이스가 적용됩니다. (이는 일반적으로 의도한 동작이며, 네임스페이스 속성은 드뭅니다. 특히, HTML과 SVG에는 네임스페이스 속성이 존재하지 않습니다.) 속성 선택자와 마찬가지로, <attr-name>의 대소문자 구분은 문서 언어에 따릅니다.

attr()가 요소에 적용된 속성에서 사용되면, 해당 요소의 주어진 이름의 속성을 참조합니다; 의사 요소에 적용된 경우, 속성은 의사 요소의 기원 요소에서 검색됩니다.

<syntax>

속성 값이 어떻게 CSS 구문에 따라 파싱될지 지정합니다. 구문에 맞지 않으면 폴백이 발생합니다.

<syntax> 인자를 생략하면 속성의 리터럴 값이 CSS 문자열 값으로 처리되며, CSS 파싱(이스케이프, 공백/주석 제거 등)도 아무것도 하지 않습니다.

참고: *와 같은 구문을 지정하는 것과는 다릅니다. 이는 여전히 CSS 파싱을 수행하지만(유효하게만 파싱되는 한 어떠한 추가 요구사항 없음) 결과를 <string> 값이 아니라 직접 치환합니다.

<declaration-value>

attr()의 폴백 값을 지정합니다. 속성 값이 없거나 지정된 타입으로 파싱에 실패할 때 대신 치환됩니다.

<syntax> 인자를 생략하면, 폴백은 지정하지 않은 경우 빈 문자열로 기본 설정됩니다. 그렇지 않으면, 지정하지 않은 경우 보장된 무효 값이 됩니다.

속성에 하나 이상의 attr() 함수가 있고, 해당 함수가 구문적으로 유효하다면, 전체 속성의 문법도 파싱 시점에는 유효하다고 간주됩니다. 실제 구문 검사는 attr() 함수가 치환된 뒤 computed-value 시점에 수행됩니다.

폴백 값은 반드시 지정된 타입일 필요는 없습니다. 예를 들어, 작성자가 속성에 요구하는 타입이 <number px>라면, 폴백 값으로도 auto와 같은 다른 값을 사용할 수 있습니다. 예시: width: attr(size <number px>, auto);
이 예시는 XML 파일 데이터를 시각적으로 표현하기 위해 attr()을 사용하는 방법을 보여줍니다:
<stock>
  <wood length="12"/>
  <wood length="5"/>
  <metal length="19"/>
  <wood length="4"/>
</stock>

stock::before {
  display: block;
  content: "To scale, the lengths of materials in stock are:";
}
stock > * {
  display: block;
  width: attr(length <number em>, 0px);
  height: 1em;
  border: solid thin;
  margin: 0.5em;
}
wood {
  background: orange url(wood.png);
}
metal {
  background: silver url(metal.png);
}

7.7.1. 속성 값 치환: attr() 표기법

attr()임의 치환 함수이며, var()와 비슷하게, computed value 단계에서(가능하면) 해당 값으로 대체됩니다. 그렇지 않으면, 보장된 무효 값으로 치환되며, 해당 선언은 computed-value 단계에서 무효가 됩니다.

attr() 함수를 해석하다 방법:
  1. el을(를) attr() 함수가 포함된 스타일이 적용되는 요소로 지정합니다. attr name을(를) 함수에서 지정한 속성 이름으로 지정합니다. syntax를 함수에서 지정한 <syntax> 값으로, 입력하지 않았다면 null로 지정합니다. fallback을 함수에서 지정한 <declaration-value>? 인자로 지정하고, 입력하지 않았다면 보장된 무효 값으로 지정합니다.

  2. elattr name이라는 속성이 없다면, 보장된 무효 값fallback을 반환합니다. 그렇지 않으면, attr value에 그 속성의 값을 지정합니다.

  3. syntax가 null이면, attr value 값을 갖는 CSS <string>을 반환합니다.

    참고: 값에 대해 어떤 파싱이나 변환도 일어나지 않습니다.

  4. <syntax>attr valuesyntaxel을 사용해 파싱합니다. 결과와 fallback을 반환합니다.

7.7.2. 보안

attr() 함수는 페이지에서 스타일링에 사용될 의도가 없던 속성도 참조할 수 있으며, 민감한 정보(예: 페이지 스크립트에서 사용하는 보안토큰 등)를 포함할 수도 있습니다.

일반적으로는, 이는 문제가 되지 않습니다. 대부분의 상황에서 attr()로 정보를 추출해 악의적인 쪽에 전달하는 것은 어렵습니다. 예외는 URL입니다. 만약 CSS만으로 임의의 속성 값을 포함한 URL을 만들 수 있다면, 3자 CSS가 허용된 환경에서는 속성에 저장된 정보를 손쉽게 외부로 전송할 수 있습니다.

이를 방지하기 위해, attr()로 생성된 값은 attr()-taint로 간주되며, attr()-tainted 값을 포함한 함수 역시 마찬가지입니다. 등록된 커스텀 속성attr()이 포함된 경우 그 attr()-tainted 값은 var() 치환 과정에서도 attr()-taint를 유지합니다.

attr()-tainted 값을 <url>이나 그 안에 사용하는 경우 선언은 computed-value 단계에서 무효가 됩니다.

예를 들어, 아래 모든 경우는 무효입니다:

다만, attr()을 다른 목적으로 사용하는 것은, url과 가깝더라도 괜찮습니다:

참고: 이 제한을 구현하려면 attr() 값에서 만들어진 값에 dirty bit을 추적해야 하며, 이는 등록된 커스텀 속성을 통해 값이 완전히 문자열로 치환될 수도 있기 때문입니다. 즉, 단순히 값 식만 검사하는 방식으로는 충분하지 않습니다. 문자열 타입이 아닌 경우도 string()과 같이 값을 문자열화할 수 있는 함수를 통해 이 조건에 걸릴 수 있으니 유의하세요: --foo: attr(foo number); background-image: src(string(var(--foo))) 역시 무효가 되어야 합니다.

8. 난수 값 생성

디자인에 어느 정도의 "무작위성"을 도입하면, 반복되는 요소가 덜 정적이고 덜 동일하게 느껴지도록 하거나, 페이지에 눈에 띄지 않는 "재미"를 줄 수 있어 유용한 경우가 많습니다.

random()random-item() 함수 (무작위 함수) 는 작성자들이 디자인 관점에서 예측 가능한 방식으로 페이지에 무작위성을 도입할 수 있도록 합니다. 여러 위치에서 같은 무작위 값을 재사용할지, 인스턴스마다 고유하게 사용할지 결정할 수 있게 해줍니다.

무작위 수 생성 방식은 UA가 정합니다. 두 개의 무작위 값에 쉽게 탐지되는 상관관계가 없어야 한다는 점은 권장되지만, 본 명세에서는 암호학적 강도에 대해 특별히 규정하지 않습니다. 무작위 함수를 암호학적 품질이 필요한 목적으로는 절대 사용하면 안 됩니다.

8.1. 난수 값 생성: random() 함수

random() 함수는 수학 함수로, 최소~최대 값 범위 중에서 균등 분포로 난수를 생성합니다. 또한, 선택적으로 최소~최대 내부에서 일정한 step 간격만 값 후보에 포함되게 제한할 수 있습니다:

<random()> = random( <random-caching-options>? , <calc-sum>, <calc-sum>, [by <calc-sum>]? )
<random-caching-options> = <dashed-ident> || per-element

각 인자의 의미는 다음과 같습니다:

<random-caching-options>

선택적인 <random-caching-options>는 주어진 random() 함수가 페이지 내 다른 random()과 동일하게(또는 다르게) 해석될지 제어할 수 있습니다. 자세한 내용은 § 8.3 난수 생성/캐싱: <random-caching-options> 값을 참고하세요.

기본적으로, random()은 하나의 값으로 해석되며, 해당 스타일을 사용하는 모든 요소가 그 값을 공유합니다. 동일한 인자를 가진 두 random()은 같은 무작위 값을 반환합니다.

<dashed-ident>를 제공해도 특별한 효과는 없지만, 인자 리스트를 서로 다른 것으로 만들어주기 때문에 otherwise-identical한 두 개 이상의 random() 함수가 서로 다른 값을 생성할 수 있습니다.

per-element 키워드를 사용하면, random() 함수가 스타일시트에서의 1회 해석이 아니라, 각 요소별로 별도의 값을 생성합니다.

<calc-sum>, <calc-sum>

두 개의 필수 계산값이 함수가 해석될 수 있는 최소/최대 값을 지정합니다. 양 끝값 모두 포함입니다 (결과가 min 또는 max가 될 수도 있습니다).

최대값이 최소값보다 작으면, 최소값과 같게 동작합니다.

예를 들어, random(100px, 300px)<length> 기준 100px ~ 300px 사이의 무작위 값을 반환합니다: 100px, 300px, 또는 234.5px 등 그 사이 값일 수도 있습니다.
by <calc-sum>

마지막 선택적 인자는 step 값을 지정합니다. 이 값이 있으면 함수가 해석될 수 있는 값들은 min + (N * step)의 형태로 제한되며, N은 0 또는 양의 정수 중 랜덤하게(균등하게) 선택되며, 해당 값이 범위 내에 있어야 합니다.

예를 들어, random(100px, 300px, by 50px)100px, 150px, 200px, 250px, 300px 중 하나만 반환합니다.

최소값은 항상 가능한 결과가 되지만, 최대값은 step이 정확히 맞아떨어지지 않으면 포함되지 않을 수 있습니다. 예) random(100px, 300px, by 30px)의 최대값은 280px (최소값에서 6 step)입니다.

반올림 이슈가 영향을 줄 수 있습니다: random(100px, 200px, by 100px / 3)에서는 값이 세 개(100px, 약 133.33px, 166.67px)로 딱 맞아떨어집니다. 그러나 200px이 포함될 수 있는지는 반올림 정밀도에 따라 다릅니다. 안전하게 하려면 최대값을 실제 마지막 step보다 조금 높게 잡으세요: random(100px, 201px, by 100px / 3).

round() 정의에서 설명한 것처럼, CSS에는 "자연스러운" 값 정밀도가 없지만, step 값을 들려 정밀도를 할당할 수 있습니다.

예) random(100px, 500px, by 1px)는 whole px값만, random(1, 10, by 1)은 정수만 반환할 수 있습니다.

참고: step 정의는 단순히 범위 내에서 난수를 생성한 후 가장 가까운 step 값으로 반올림하는 것을 허용하지 않습니다. 이는 값이 동일한 비율로 등장하지 않게 만듭니다. 예) random(100px, 200px, by 50px)로 1/3 확률로 각각 세 값이 나와야 하지만, 단순 반올림 방식에서는 150px이 경계값보다 두 배 자주 등장합니다.

모든 계산값 인자는 <number>, <dimension>, <percentage> 어느 쪽으로든 해석될 수 있으나, 동일한 타입이어야 하며, 그렇지 않으면 함수는 무효입니다. 결과의 타입도 인자와 동일합니다.

예) random(50px, 100%, by 1em)는 유효합니다 (여기서 percentages가 이 context에서 유효하고, <length>로 계산된다면), 세 인자 모두 길이로 해석됩니다.

하지만 random(50px, 180deg)은 무효입니다. 길이와 각도는 동일한 타입이 아니기 때문입니다.

random() 함수는 인자 계산값 들이 숫자로 단순화될 수 있을 때 곧 바로 단순화될 수 있습니다.

참고: random()대개 computed value 시간에 해석되어 그 값은 상속값으로 전달됩니다. 단, 인자 계산값used value 시간에 해석되어야 하는 경우(예: 레이아웃 정보가 필요한 <percentage>가 포함된 경우)는, 상속random() 함수를 그대로 전달하게 됩니다. (이는 <percentage> 자체가 상속되는 상황과 동일하며, 자식 요소별로 값이 달라질 수도 있습니다.)

이론적으로는 per-element가 지정되지 않은 한 random()을 비속성(context)에서도 써도 괜찮아야 할 것 같습니다. 예를 들어 @media (max-width: random(100px, 500px)) {...} 같은 경우 명확하게 정의되어 있습니다. 그래도 막아야 할까요?

8.1.1. 인자 범위

random(A, B, by C)에서 A 또는 B가 무한대(infinity)라면, 결과는 NaN입니다. C가 무한대라면, 결과는 A입니다.

(C가 0이거나 음수이면, 결과는 A이며, 이는 표준 정의에서 자연스럽게 도출됩니다.)

참고: 수학 함수에서 항상 그렇듯, 어떤 인자 계산 결과가 NaN이라면, 결과도 NaN입니다.

8.2. 리스트에서 임의 항목 선택: random-item() 함수

random-item() 함수는 인자로 받은 아이템 목록 중에서 하나를 무작위로 선택해 반환합니다.

<random-item()> = random-item( <random-caching-options> , [ <declaration-value>? ]# )

필수 <random-caching-options>random()과 동일하게 해석됩니다. (자세한 내용은 § 8.3 난수 생성/캐싱: <random-caching-options> 값을 참조하세요.)

random()와 마찬가지로, <dashed-ident>를 사용하면 비슷한 random-item() 함수들이 서로 다른 무작위 값을 강제로 생성하게 만들 수 있고, per-element를 사용하면 각 요소별로 값이 달라집니다.

이 외에는, random-item() 함수 집합의 "동일함" 판별이 더 간단합니다: 인자 개수만 중요합니다.

즉, random-item(--x, red, blue, green)random-item(--x, 1, 2, 3)은 항상 동일한 인덱스의 인자를 선택하며, 결과적으로 red1, 또는 blue2, green3 중 한 쌍이 선택됩니다. 즉, 여러 속성 그룹에서 같은 무작위 인덱스를 활용할 수 있습니다.

반면, random-item(--x, red, blue, green)random-item(--x, 1, 2, 3, 4)는 서로 연동되지 않으며, 총 12가지 조합이 모두 가능합니다.

참고: <random-caching-options> 인자는 random-item()에서 필수이며, random()에서는 선택입니다. (파싱 문제 때문이기도 하고, random-item()의 구분이 인자 개수에 의존하기 때문입니다.)

나머지 인자들은 임의의 CSS 값 시퀀스입니다. random-item() 함수는 이 중 하나를 균등하게 무작위로 선택해 반환합니다.

random-item() 함수도 임의 치환 함수이며, var()와 유사합니다.

즉, random-item()을 사용할 때:

임의 치환 함수 정의를 Variables에서 해야 할 것 같습니다. 앞으로 여러 함수가 이 기능에 의존할 예정입니다.

random-item() 이 var()처럼 동작하므로 아마 속성에서만 사용 가능하게 제한해야 할 것입니다. (이 패턴은 이런 류의 함수 전체에 적용될 가능성이 높습니다.) random() 은 근본적으로 다르지만, 일관성을 위해 아마 이것도 제한하는 것이 맞을 것입니다.

8.3. 난수 생성/캐싱: <random-caching-options>

JavaScript와 같은 프로그래밍 언어에서는 시간(실행) 순서가 명확하므로, Math.random() 호출이 언제 평가되는지 알 수 있습니다. 변수에 결과를 저장해 여러 곳에서 같은 난수값을 재사용할지, 각기 다른 무작위값을 쓸지 쉽게 조절할 수 있습니다.

반면 CSS는 선언형 언어이기 때문에 (코드가 특별한 순서로 "실행"되지 않고, "실행" 횟수도 제어할 수 없음) 동일 스타일을 여러 요소에 손쉽게 적용할 수 있는 대신, 요소별로 값을 다르게 지정하기는 어렵습니다. (즉, random()을 썼을 때 모든 요소에 같은 값이 적용될지, 각기 다른 값이 적용될지 불명확합니다.) 또한 "변수" 기능도 제한적이어서, 특정 난수 생성값을 여러 위치에서 의도적으로 재사용하기도 어렵습니다.

이 문제들을 해결하기 위해, random()random-item() 함수는 아래와 같은 캐싱 조건으로 난수를 생성합니다:

"요소나 의사요소별 고유값"은 JavaScript 참조와 동일한 수명(lifetime)을 가져야 하며, (또는 기원 요소를 유일하게 식별할 수 있는 추가 정보를 포함) 서로 다른 문서(페이지 새로고침 포함)에서는 서로 달라야 합니다. (완전 강제는 아니지만, 값 생성이 충분히 무작위적이면 서로 다른 결과가 나오므로, 작성자가 여러 문서 간에 같은 값이 나온다고 의존하지 않도록 해야 합니다.)

또한, 난수 생성 메서드는 다른 문서(페이지 새로고침 포함)에서 같은 연산을 해도 서로 다른 값을 생성해야 합니다.

예시: 다음 스타일시트에서,
.random-square {
  width: random(100px, 500px);
  height: random(100px, 500px);
}

두 함수의 random-caching key(100px, 500px, null, null, null)로 동일합니다. 그래서 두 속성 모두 완전히 동일한 값을 갖게 되어 100~500px 사이의 한 크기의 정사각형이 만들어집니다. 또한 모든 .random-square 요소도 같은 크기를 유지합니다.

그런데 아래 스타일시트에서는,

.random-rect {
  width: random(100px, 500px);
  height: random(--x, 100px, 500px);
}

여기서는 random-caching key가 서로 달라서, width용 함수는 (100px, 500px, null, null, null), height용 함수는 (100px, 500px, null, --x, null)입니다.

따라서 두 속성이 다른 랜덤 값을 사용하게 되어, 해당 요소가 정사각형이 아니라 사각형이 될 확률이 매우 높아집니다. 하지만 .random-rect에 해당하는 모든 요소는 동일한 랜덤 크기를 가집니다.

함수의 어떤 부분이라도 달라지면 key도 달라지므로, 아래 두 선언은 width와 height가 연동되지 않습니다:

.random-rect-2 {
  width: random(100px, 500px);
  height: random(100px, 500px, by 50px);
}

하지만 used value가 동일하게 해석된다면, 겉보기에 달라도 실제로는 동일한 결과가 될 수 있습니다. 예) 아래 코드에서는,

.random-square-2 {
  font-size: 16px;
  width: random(160px, 320px);
  height: random(10em, 20em);
}

두 함수는 인자만 보면 다르게 보여도, 실제로 길이가 해석되고 나면 같은 random-caching key가 되어 항상 동일한 값이 됩니다.

기본적으로 스타일시트 내 각 random() 인스턴스는 사실상 하나의 값으로 해석되며, 이 값이 해당 속성이 적용되는 모든 요소에서 공유됩니다. per-element 키워드로 동작을 바꿀 수 있습니다.

예시:

.foo { width: random(100px, 500px); }

.foo에 해당하는 모든 요소는 동일한 랜덤 width를 가집니다.

그러나 다음처럼 작성하면,

.foo { width: random(per-element, 100px, 500px); }

.foo에 해당하는 각 요소가 고유한 랜덤 width를 갖습니다.

이렇게 하면 각 이 아니라 각 요소별로 고유함이 부여됩니다. 예를 들어:

.random-squares {
  width: random(per-element, 100px, 500px);
  height: random(per-element, 100px, 500px);
}

.random-squares에 해당하는 각 요소는 하나의 고유한 랜덤 값을 갖지만, 해당 요소의 widthheight는 동일한 값이 됩니다(즉, 완전히 정사각형). 두 속성 모두 같은 random-caching key를 사용하기 때문입니다.

이렇게 하면 커스텀 속성 내 무작위 값도 예측 가능하게 다룰 수 있습니다. 다음처럼 작성해도 같은 효과:

.foo {
  --size: random(per-element, 100px, 500px);
  width: var(--size);
  height: var(--size);
}

9. 트리 계수 함수: sibling-count()sibling-index() 표기법

sibling-count() 함수 표기법은 상위 요소에서 이 표기법이 사용된 요소를 자식 요소 중 총 몇 개인지(<integer>)로 반환합니다.

sibling-index() 함수 표기법은 이 표기법이 사용된 요소가 상위 요소의 자식 중 몇 번째인지 (<integer>) 반환합니다. :nth-child()와 마찬가지로, sibling-index()는 1부터 셉니다.

참고: counter() 함수도 sibling-index()와 유사한 기능이 있으나, 결과를 <string>으로 반환하며 <integer>는 아닙니다.

의사 요소(pseudo-element)에서 사용될 경우, 두 함수 모두 그 최초 기원 요소에 지정된 것처럼 해석합니다.

참고: CSS(그리고 셀렉터 제외)처럼, sibling-count()sibling-index()플랫 트리를 기준으로 동작합니다.

참고: 이 함수들은 앞으로 of <selector> 인자를 받아 :nth-child()처럼 자식의 일부만 대상으로 하는 확장도 검토될 수 있습니다.

10. 내재 크기 계산: calc-size() 함수

확정 크기 간 전환이나 기존 확정 크기를 미세 조정할 때에는 calc()가 매우 효과적입니다: 100%20px의 중간값은 calc(50% + 10px), 좌우 마진이 각각 15px20%calc(20% + 15px * 2) 등으로 쓸 수 있습니다.

하지만 조정하거나 전환하려는 크기가 내재 크기일 경우 실질적·호환성 이유로 이러한 연산이 불가능해집니다. calc-size() 함수는 내재 크기에 대해 안전하고 명확하게 수식을 적용할 수 있도록 해줍니다.

<calc-size()> = calc-size( <calc-size-basis>, <calc-sum> )
<calc-size-basis> = [ <intrinsic-size-keyword> | <calc-size()> | any | <calc-sum> ]

<intrinsic-size-keyword> 생성 규칙은 해당 문맥에서 허용되는 모든 내재 크기 키워드를 매칭합니다. 예를 들어 width에서 auto, min-content, stretch 등입니다.

calc-size()는 중첩될 수 있나요?

calc-size()를 basis 인자로 허용하면 변수 (예: calc-size(var(--foo), size + 20px))를 basis로 쓸 수 있고, 해당 변수가 원래 속성에서 유효하기만 하면 항상 동작합니다.

일반 calc()로는 불가능합니다 - 예: --foo: calc-size(min-content, size + 20px)--foo: min-content와 같이 해도 calc( (var(--foo)) + 20px )은 실패합니다.

이런 중첩은 보간 과정(및 used-value 단계)에서 단순화되어, 결과적으로 basis는 항상 단순 값이 됩니다. 자세한 내용은 § 10.1 calc-size() 단순화 참고.

첫 번째 인자는 calc-size 기준, 두 번째 인자는 calc-size 계산식입니다. 어느 인자든, <calc-sum>이 들어간 경우, 해당 타입은 반드시 일치해야 하며, <length-percentage>여야 하고, <length>로 해석되어야 합니다.

calc-size 계산식 내부에서 calc-size 기준any가 아니라면, size 키워드를 쓸 수 있습니다. 이 키워드는 <length>이며, used value 단계에서 해석됩니다.

calc-size()내재 크기에 해당합니다. 이는 <length>아니며, calc-size()를 허용하려면 구문에서 별도로 명시해야 합니다.

calc()에 내재 키워드를 허용하지 않나요?

이론적으로 calc-size()를 도입하지 않고 calc(auto * .5)와 같이 정의할 수도 있겠으나, 이 경우 보간이 항상 정상적으로 동작하지 않습니다.

이 방식은 키워드 혼합이 여전히 허용되지 않는다는 작은 문제도 있지만, 표면적으로는 자연스러워 보일 수 있습니다 (예: calc((min-content + max-content)/2)는 합리적으로 보이지만 실제론 허용되지 않음).

더 큰 문제는 퍼센테이지의 부드러운 전환이 불가능하다는 점입니다. calc(50%)는 퍼센트가 해당 문맥에서 확정일 때에만 calc(100%)의 절반 사이즈가 됩니다; 아니라면 두 값이(문맥에 따라 0px 또는 auto 등) 동일해집니다.

새 함수가 계산 대상으로 지정한 크기와 계산 자체를 명시적으로 분리하도록 해주면 모든 경우에 부드러운 보간이 가능합니다.

또 많은 효과(크든 작든)가 요소가 내재 크기인지 확정 크기인지에 좌우되는 점도 있습니다. calc()로는 "이 요소가 내재 크기인가"라는 질문에 트랜지션 중간(예: calc(min-content * .2 + 20px * .8)))에는 "예", 끝(calc(20px))에는 "아니오"로 답이 달라져 레이아웃이 트랜지션 마지막에 갑자기 튀는 문제가 있습니다.

(이는 opacity:1에서 opacity: 0으로 애니메이션할 때 stacking-layer가 바뀌는 것과 비슷합니다. opacity의 경우 .999로 애니메이션하면 해결되지만, 내재 크기에서는 calc(auto * .0001)로 하라고 강제하는 건 비현실적입니다.)

다시 말해, 본질적으로 내재 크기임을 식별하는 새 함수(calc-size(auto, 20px) 등)를 사용하면 실제 크기가 확정 길이더라도 매 순간 일관된 레이아웃 동작을 유지할 수 있습니다.

10.1. calc-size() 단순화

수학 함수와 마찬가지로, 명시 값·계산 값 단계 모두에서 calc-size 계산식(및 calc-size 기준<calc-sum>일 경우 기준까지) 최대한 단순화됩니다. 단순화 방식은 CSS Values 4 § 10.10.1 Simplification에서 정의합니다.

보간을 위한 정규화(canonicalize for interpolation)calc-size() 함수에 수행하려면:
외부 함수의 calc-size 기준calc-size() 함수일 경우

외부 함수의 calc-size 기준을 내부 함수의 것으로 교체하고, 내부 함수의 calc-size 계산식을 외부 함수 calc-size 계산식대입(substitute)합니다.

그 외, calc-size 기준<calc-sum>이고 그 타입일치하고(퍼센트 없음) <length>라면

basis를 any로 바꾸고, 원래의 basis는 calc-size 계산식대입합니다.

그 외, calc-size 기준이 다른 <calc-sum>(퍼센트 포함)라면

basis를 100%로 바꾸고, 원래 basis는 de-percentifycalc-size 계산식대입합니다.

(필요하다면 위 작업을 재귀적으로 반복합니다.)

calc-size 계산식 대입이 실패를 반환하면, 전체 작업도 즉시 실패로 종료됩니다.

참고: 정규화 후 calc-size()키워드 basis100%만 basis로 쓸 수 있습니다.

퍼센트는 왜 이렇게 단순화하나요?

이런 퍼센트 단순화는 트랜지션이 선형적으로 동작함을 보장합니다.

예: 100%가 100px라고 가정해봅시다.

`calc-size(100px, size * 2)`(200px)에서 `calc-size(50%, size - 20px)`(30px)로 보간 시, 인자를 서로 보간하면 중간 단계에서 `calc-size(75px, size * 2 * .5 + (size - 20px) * .5)`(=102.5px)인데, 실제 중간값(115px)과 다릅니다. 각각 따로 보간하거나 대입 후 또 보간하면 실제로 이차 함수 형태의 보간이 됩니다.

대신 basis 인자를 계산 인자에 대입하면 `calc-size(percentage, 100px * 2)`와 `calc-size(percentage, (size * .5) - 20px)`로 볼 수 있고, 중간에선 `calc-size(percentage, 100px * 2 * .5 + ((size * .5) - 20px) * .5)`가 되어 115px(정확한 중간값)을 얻습니다. 다른 시점도 선형입니다.

calc-size 계산식 de-percentify calc의 경우:
  1. calc 내부의 모든 <percentage-token>(size * N)으로 교체(N은 퍼센트값/100). calc 반환.

참고: 예시: 50% + 20px(size * .5) + 20px.

calc-size 계산식에 대입 calcinsertion value 대입:
  1. calcsize 키워드가 없으면 아무 작업도 하지 않음.

  2. 그렇지 않으면 calc 내 모든 size 키워드를 insertion value(괄호로 감쌈)로 대체.

  3. 이 대입 결과 값이 UA 정의 한도를 넘으면 실패 반환.

    참고: 이건 변수 치환의 길이 제한과 완전히 동일한 보호입니다. 자세한 내용은 CSS Variables 1 § 3.3 매우 긴 변수 안전하게 다루기 참고. 단, calc-size()의 활용 예시가 커스텀 속성보다 훨씬 적으므로, UA는 더 짧은 제한을 둘 수 있습니다.

10.2. calc-size() 해석

calc-size()는 모든 면에서 자신의 calc-size 기준(any는 미지정 확정 크기로 취급)인 것처럼 간주됩니다.

실제 레이아웃 계산에서는, calc-size 기준이 나타내는 크기가 calc-size 계산식의 값으로 보정되며, size 키워드는 원래 calc-size 기준의 실제 크기로 평가됩니다.

(calc-size 기준any이면, calc-size()확정 길이이며, calc-size 계산식 값과 같습니다.)

예: height: calc-size(auto, round(up, size, 20px))인 요소는 height: auto인 요소와 완전히 동일하게 처리되지만, 크기는 20px의 배수로 올림 처리됩니다.

calc-size 계산식을 평가할 때 퍼센트가 해당 문맥에서 확정이 아니면 0px으로 해석됩니다. 확정이면 일반대로 해석됩니다.

(calc-size 기준의 퍼센트는 다르게 처리합니다; 단순화 과정에서 퍼센트는 calc-size 계산식으로 옮겨지고 size 참조로 대체됩니다. calc-size 기준100%가 되어, 해당 문맥의 100% 동작대로 처리됩니다. (예: auto 등)

기준에서의 퍼센트는 정상적으로 동작하므로 값이나 동작에 상관없이 항상 어떤 값으로든 부드럽게 전환이 가능합니다. calc-size() 없이 100%에서 0px로 전환 시, 퍼센트가 확정일 때만 부드럽게 처리됩니다; 그렇지 않으면 트랜지션 내내 해당 속성이 auto로 동작해 크기가 변하지 않을 수도 있습니다.

반면 계산식 내부의 퍼센트는, 확정이 아니면 0으로 해석합니다. calc-size()가 두 가지 방식으로 동작하는 걸 방지하려는 목적입니다. 실제 min-content 크기는 100%와 다를 수 있으므로, calc-size()는 반드시 한 가지 형태로 동작해야 합니다.

10.3. calc-size() 보간

calc-size() 함수는 (보간용 정규화 후) 다음 조건에서 보간이 가능합니다:

둘 중 하나라도 보간용 정규화에서 실패 반환

보간 불가.

calc-size 기준이 동일한 경우

보간결과 calc-size 기준은 그 기준값.

둘 중 하나의 calc-size 기준any인 경우

결과 calc-size 기준은 비-any 기준값.

결과 calc-size 계산식은 두 입력 calc-size 계산식의 보간 값입니다.

참고: 이 보간 제약 덕분에 calc-size()가 두 가지 방식을 동시에 동작하지 못하게 합니다. (예를 들면 min-contentmax-content는 레이아웃 효과가 다를 수 있음). 즉 calc-size()가 반드시 한 종류의 동작만 해야 합니다. 그렇기 때문에 키워드간(예: auto에서 min-content 등) 전환은 불가합니다.

일부 calc-size() 값은 또 <length-percentage> 또는 <intrinsic-size-keyword>와도 보간할 수 있습니다. 보간 가능성 및 방법을 정할 때 non-calc-size() 값이 <calc-sum>라면 calc-size(any, value)로, 아니라면 calc-size(value, size)로 간주해 위 규칙 적용.

예시: calc-size() 덕분에 height: auto로의 전환이 가능합니다:
details {
  transition: height 1s;
}
details::details-content {
  display: block;
}
details[open]::details-content {
  height: auto;
}
details:not([open])::details-content {
  height: calc-size(any, 0px);
}

이는 암묵적으로 calc-size(auto, size)calc-size(any, 0px)의 보간이 되며, details를 열고 0.5초 후 details 내 ::details-content 래퍼의 heightcalc-size(auto, size * .5), 즉 열린 높이의 절반이 되며, 전환 기간 내내 부드럽게 높이가 애니메이션됩니다.

참고: calc-size()calc-size(any, 확정 길이)로 어디서나 매끄럽게 전환할 수 있도록 설계됐습니다.

참고: "일반 값을 calc-size()로 자동 승급" 동작은 <length-percentage> 값을 calc-size 계산식에 둡니다. 이로써 퍼센트 포함 값도 내재 키워드와 보간할 수 있지만, 퍼센트가 확정이 아닐 땐 항상 0으로 해석됨에 유의하세요. 퍼센트가 만드는 실제 크기로 해석하고 싶다면, calc-size(50%, size)처럼 아예 basis에 넣으세요.

10.4. 크기 키워드 보간: interpolate-size 속성

참고: 타임머신이 있었다면 이 속성은 필요하지 않았을 것입니다. 이 속성은 많은 기존 스타일 시트에서 내재적 크기 키워드 (예: auto, min-content 등) 는 애니메이션이 불가능하다고 가정하기 때문에 존재합니다. 따라서 이 속성은 스타일 시트가 예상 동작을 선택할 수 있도록 존재합니다. 루트 요소에 interpolate-size: allow-keywords를 지정하면 전체 페이지에서 새 동작을 선택하게 됩니다. 호환성 문제가 없다면 이렇게 하길 권장합니다.

이름: interpolate-size
값: numeric-only | allow-keywords
초기값: numeric-only
적용 대상: 모든 요소
상속:
백분율: 해당 없음
계산값: 지정한 대로
정규 순서: 문법에 따름
애니메이션 타입: 애니메이션 불가
numeric-only
<intrinsic-size-keyword>는 보간할 수 없습니다.
allow-keywords
두 값 중 한쪽이 <intrinsic-size-keyword>이고 다른 한쪽이 <length-percentage>일 때 보간이 가능합니다. 이때는 <intrinsic-size-keyword> keywordcalc-size(keyword, size)와 같이 처리하여 § 10.3 Interpolating calc-size()의 규칙을 적용합니다. 그 외의 경우에는 <intrinsic-size-keyword>는 여전히 보간할 수 없습니다.

interpolate-size의 유효 값은 애니메이션이 시작될 수 있는 시점의 요소의 계산값입니다. CSS 전환에서는 변경 후 스타일의 값을 의미합니다. 애니메이션은 interpolate-size가 변경되었다고 해서 중간에 중지되거나 새로 시작하지 않습니다.

부록 A: 임의 대체 함수

임의 대체 함수함수 표기법으로, 해석될 때, 구문 분석 시점에 알 수 없는 값으로 자기 자신을 대체합니다. 따라서 그 계산값을 해석하는 과정에서 분석되어야 합니다.

참고: 임의 대체 함수계산값 시점에 해석되므로, 대체 후 값이 유효하지 않으면 해당 속성은 unset 동작으로 (사실상) 대체되며, 구문 오류로 인해 즉시 대체되는 경우처럼 앞의 값을 사용하지 않습니다. 잘못된 대체를 참고하세요.

별도 명시가 없다면 임의 대체 함수는 어떠한 속성 값의 일부(다른 함수 표기법 내부 포함)를 대체하여 사용할 수 있습니다. 그리고 다른 맥락에서는 유효하지 않습니다.

이 함수들이 속성 이외의 문맥에서 유효해야 할까요?

예를 들어, 다음 코드는 변수를 속성 이름으로 잘못 사용하려 합니다:
.foo {
  --side: margin-top;
  var(--side): 20px;
}

이것은 margin-top: 20px;을 지정하는 것과 같지 않습니다. 오히려 두 번째 선언은 올바르지 않은 속성 이름으로 인해 구문 오류로서 단순히 무시됩니다.

만약 하나 이상의 임의 대체 함수가 속성 값에 포함되어 있고 이 함수들이 구문상으로 유효하다면, 해당 전체 값의 문법이 구문 분석 시점에 유효한 것으로 간주됩니다.

임의 대체 함수는 스타일 대체 단계에서 계산 도중에 치환되며, 다른 값 변환이나 검사보다 먼저 수행됩니다. 만약 속성이 대체 이후 선언된 문법에 맞지 않는다면, 선언은 계산값 시점에서 무효가 됩니다.

만약 대체 이후 속성 값이 CSS-전역 키워드 단 하나만(공백/주석 가능) 포함한다면, 그 값은 마치 해당 키워드가 처음부터 지정값이었던 것처럼 동작합니다.

예를 들어, 아래 사용은 구문상으론 괜찮지만, 변수가 대체되면 의미 없는 결과를 초래합니다:
:root { --looks-valid: 20px; }
p { background-color: var(--looks-valid); }

20pxbackground-color에 유효한 값이 아니므로, 해당 속성은 계산값 시점에서 무효가 되며, 대신 transparent로 처리됩니다(초기값). background-color의 초기값입니다.

속성이 기본적으로 상속되는 것이라면, 예: color라면, 초기값 대신 상속값으로 계산됩니다.

var() 함수는 CSS-전역 키워드사용자 속성 자체에서 가져올 순 없지만, 만약 --foo: initial;처럼 지정하면, 그 속성에는 명시적 디폴트만 적용됩니다. 하지만 대체값 fallback에는 CSS-전역 키워드가 들어갈 수 있습니다:
p { color: var(--does-not-exist, initial); }

위 코드의 경우 --does-not-exist 속성이 존재하지 않거나 계산값 시점에 무효라면, var()는 fallback으로 initial 키워드를 대체로 넣어 해당 속성은 처음부터 color: initial과 같이 동작하게 됩니다. 이로 인해 문서의 초기 color 값이 적용되며, fallback이 없으면 상속값이 적용되는 것과는 다릅니다.

임의 대체 함수는 직접 임의 대체 함수 해석 방법을 정의해야 하며, 반환값 resultfallback 을 선택적으로 리턴해야 합니다. result보장된-무효 값을 포함하지 않는 한 함수 자리에 대체해서 사용하고, fallback는 그렇지 않은 경우 사용됩니다. (fallback은 별도 해석 과정 없이 그대로 사용되며, 대체에서 실제로 필요할 경우 대응합니다.)

참고: 예시로 var() 함수 해석을 참고하세요.

임의 대체 함수 대체(substitute arbitrary substitution functions)value에서 수행하려면:
  1. 모든 임의 대체 함수 funcvalue에 대해:

    1. Resolve func. result를 반환값으로, fallback을 fallback 반환값으로 한다.

      result가 없다면, result보장된-무효 값을 지정한다. fallback이 없다면, fallback보장된-무효 값을 지정한다.

    2. 만약 result보장된-무효 값이 없다면

      value에서 funcresult로 대체한다.

      그렇지 않고 fallback보장된-무효 값이 없다면

      value에서 funcfallback으로 대체한다.

      둘 다 아니면

      value 전체를 보장된-무효 값으로 교체한다. 이 알고리즘을 종료한다.

  2. 아직 임의 대체 함수value(대체 결과)에 더 있다면, 이전 단계를 반복한다.

  3. value를 문맥에 맞게 정상적으로 문법 검사한다. 만약 이 시점에서 유효하지 않으면, value보장된-무효 값으로 교체한다.

대체는 CSS 토큰 수준[css-syntax-3]에서 일어난다는 것에 유의하세요. 문자 단위로 이루어지는 게 아니므로, 변수로 토큰의 일부만 조합할 수는 없습니다:
.foo {
  --gap: 20;
  margin-top: var(--gap)px;
}

이것은 margin-top: 20px; (길이)로 지정하는 것과 같지 않습니다. 오히려 margin-top: 20 px; (숫자와 식별자 순서)과 같아져, margin-top 속성에 유효하지 않은 값이 됩니다. 하지만 calc()를 사용하면 정상적으로 처리할 수 있습니다:

.foo {
  --gap: 20;
  margin-top: calc(var(--gap) * 1px);
}

이것은 대체 이후 값이 바로 직렬화(serialized)되지 않을 수도 있음을 시사합니다. 비슷한 또 다른 예시는 다음과 같습니다:

.foo {
  --gap: 20;
  --not-px-length: var(--gap)px;
}

(대체 이후)--not-px-length의 계산값 직렬화 결과는 20px아니고, 왜냐하면 그럴 경우 합쳐진 치수 단위로 해석될 것이기 때문입니다. 대신 두 토큰이 분리되어 있다는 점을 보장하기 위해, 재파싱 시에도 별개의 토큰임을 유지하도록 직렬화 시 주석을 삽입해 px처럼 표현됩니다.

잘못된 대체

대체 결과로 속성 값에 보장된-무효 값이 포함되면, 이 선언은 계산값 시점에서 무효로 간주됩니다. 이때 속성 타입에 따라 참조되는 계산 값은 다음 중 하나입니다:

속성이 미등록 사용자 속성인 경우
속성이 등록된 사용자 속성이면서 범용 문법인 경우

계산값은 보장된-무효 값이 됩니다.

그 외의 경우

그 속성이 상속속성이면 상속된 값, 아니면 초기값으로, 마치 unset 키워드가 지정된 것처럼 처리됩니다.

예를 들어 다음과 같은 코드에서:
:root { --not-a-color: 20px; }
p { background-color: red; }
p { background-color: var(--not-a-color); }

<p> 요소들은 background-color의 초기값(투명)인 투명 배경을 가지게 됩니다. 이는 빨간색이 아니라 투명입니다. 만약 사용자 속성 자체가 unset이거나, 잘못된 var() 함수였다 해도 마찬가지입니다.

이는 개발자가 단순히 background-color: 20px를 직접 사용했다면 정상 구문 오류로 해당 규칙이 무시되어 background-color: red가 적용되는 것과 다릅니다.

참고: 계산값 시점에서 무효라는 개념은 임의 대체 함수는 다른 구문 오류처럼 "즉시 실격" 처리가 되지 않고, 사용자 에이전트가 속성 값을 잘못되었다고 인지하는 시점에는 이미 다른 cascade된 값이 폐기된 상태이기 때문에 존재합니다.

축약 속성에서의 대체

임의 대체 함수축약 속성을 개별 롱핸드로 분해하거나 개별 롱핸드로부터 축약 속성을 직렬화할 때 복잡함을 유발할 수 있습니다.

만약 축약 속성 값에 임의 대체 함수가 포함돼 있으면, 관련 롱핸드 속성에는 특별하고 개발자에겐 보이지 않는 pending-substitution 값이 할당되어, 축약 속성에 임의 대체 함수가 있다는 점만 표시합니다. 따라서 롱핸드 값은 대체 완료 전까지는 결정할 수 없습니다.

이 값은 이후 평소처럼 cascade되고, 계산값 단계에서 대체가 이뤄진 뒤에 축약 속성이 분해되어 그 시점에서 롱핸드에 올바른 값이 지정됩니다.

참고: 축약 속성을 임의 대체 함수 없이 작성하면, 파싱 시점에 분해되어 각 롱핸드 속성으로 옮겨집니다. 롱핸드는 cascade에 참여하며, 축약 속성은 거의 폐기됩니다. 그러나 축약 속성에 var()가 포함됐을 때는 var()에 무엇이 대체될지 모르므로 분해가 불가능합니다.

pending-substitution 값은 API에서 관찰될 수 있을 경우 빈 문자열로 직렬화되어야 합니다.


축약 속성은 그에 속하는 롱핸드 속성의 값을 모아, 똑같이 파싱될 수 있는 값을 합성해 직렬화합니다.

특정 축약 속성에 속하는 모든 롱핸드 속성이 같은 원본(임의 대체 함수 포함 값)의 pending-substitution 값이라면, 해당 축약 속성은 원본(임의 대체 함수 포함) 값으로 직렬화해야 합니다.

그 외에도, 하나라도 롱핸드 속성pending-substitution 값이거나, 아직 임의 대체 함수가 대체되지 않은 상태라면 해당 축약 속성은 빈 문자열로 직렬화해야 합니다.

너무 긴 치환 안전하게 다루기

단순하게 구현하는 경우, 일부 임의 대체 함수 (예: var()) 는 "십억 번 웃음 공격"의 변형에 사용될 수 있습니다:

.foo {
  --prop1: lol;
  --prop2: var(--prop1) var(--prop1);
  --prop3: var(--prop2) var(--prop2);
  --prop4: var(--prop3) var(--prop3);
  /* 등등 */
}

이 짧은 예시에서, --prop4의 계산값은 lol lol lol lol lol lol lol lol이 되어 원래 lol이 8번 반복됩니다. 단계가 하나씩 추가될 때마다 식별자 개수는 2배로 늘어나며, 겨우 30단계만 추가해도, 손으로 몇 분만 투자해도, --prop30에는 십억 개에 가까운 식별자가 포함됩니다.

이런 종류의 공격을 방지하기 위해, UA는 임의 대체 함수가 확장하는 토큰 스트림 길이에 UA가 정의하는 제한을 둬야 합니다. 만약 임의 대체 함수가 제한보다 더 긴 토큰 스트림으로 확장된다면, 대신 보장된-무효 값으로 대체되어야 합니다.

이 명세는 제한 크기가 얼마여야 하는지 정의하지 않습니다. 하지만 1킬로바이트 이상의 텍스트를 담는 사용자 정의 속성의 타당한 사용 사례가 있기 때문에, 이 제한은 꽤 높게 설정할 것이 권장됩니다.

참고: 리소스 제한으로 인해 UA가 표준을 위반할 수도 있다는 일반 원칙은 이 경우에도 대체로 적용됩니다; UA는 별도로 지원 가능한 사용자 속성 크기나 지원 가능한 식별자 길이에 제한을 둘 수 있습니다. 이 절에서는 이 공격이 오랜 역사가 있고, 처음 보면 각 요소가 별로 커 보이지 않아도 가능하다는 점에서 따로 명시합니다.

부록 B: 불리언 논리

CSS의 미래 확장을 수용하기 위해, <boolean-expr[]> 생성 규칙은 일반적으로 그 <general-enclosed> 문법 분기를 미지정으로 보고, 논리 연산은 3값 Kleene 논리를 사용해 해석합니다. 일부 경우(예: @supports)에는 <general-enclosed>을 거짓으로 정의하기도 하며; 이런 경우 논리가 표준 불리언 대수로 단순화됩니다.

3값 불리언 논리는 불리언 조건 test에 재귀적으로 다음과 같이 적용됩니다:

“최상위” <boolean-expr[]>가 unknown인 경우, 그리고 그 컨텍스트가 별도의 unknown 처리 방법을 정의하지 않았다면, 그 결과는 false로 평가합니다.

참고: 즉, unknown 값은 명시적으로 처리되지 않는 이상 3값 불리언 식에서 “빠져나가지” 않습니다. 이는 NaN최상위 계산에서 “빠져나가지” 않는 것과 유사합니다.

감사의 말

우선, 편집자들은 이 모듈의 이전 단계에 기여한 모든 분들께 감사를 전합니다.

두 번째로, 우리는 특히 Guillaume Lebas, L. David Baron, Mike Bremford, Sebastian Zartner, 그리고 특히 Scott Kellum의 아이디어, 의견, 제안에 감사를 전합니다(Level 5 기준);

변경 이력

2024년 9월 17일 워킹 드래프트 이후 변경 사항:

첫 번째 공개 워킹 드래프트 이후 변경 사항:

Level 4 이후 추가 사항

CSS Values and Units Level 4 이후 추가된 내용:

보안 고려 사항

이 명세는 CSS <url> 값의 다양한 요청 방식을 수정할 수 있도록 허용합니다. 이것은 CSS에 새롭게 도입된 기능이지만, 모든 동작은 이미 img 또는 link 태그, 그리고 JavaScript로도 가능합니다.

attr() 함수는 HTML 속성값을 CSS 값에서 사용할 수 있도록 허용합니다. 이로 인해 기존에는 CSS에서 접근할 수 없었던 민감 정보가 노출될 수도 있습니다. § 7.7.2 보안 참고.

프라이버시 고려 사항

이 명세는 사용자의 화면 크기 및 기본 글꼴 크기를 노출하는 단위를 정의합니다. 하지만 이는 JS에서 너무 쉽게 확인할 수 있기 때문에 새로운 프라이버시 위험은 아닙니다. 마찬가지로 media-progress() 표기는 이미 미디어 쿼리로 관찰 가능한 사용자의 환경 및 선호 정보를 노출합니다.

attr() 함수는 HTML 속성값을 CSS 값에서 사용할 수 있어, 기존에는 CSS에서 접근할 수 없었던 민감 정보가 노출될 위험이 있습니다. § 7.7.2 보안 참고.

적합성

문서 관례

적합성 요구 사항은 설명적 진술과 RFC 2119 용어의 조합으로 표현됩니다. 반드시 지켜야 할 단어는 “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, “OPTIONAL” 이며 규범적인 부분에서는 RFC 2119에서 설명한 방식대로 해석해야 합니다. 단, 가독성 향상을 위해 본 명세에서는 해당 단어들이 모두 대문자로 쓰이지 않습니다.

이 명세서의 전체 내용은 특별히 비규범임을 명시하거나, 예시, 참고(note) 구문이 아닌 한 규범적입니다. [RFC2119]

이 명세의 예시는 “for example”로 시작하거나, class="example"처럼 규범 내용과 구분해 제공합니다:

이것은 참고용 예시입니다.

참고용 노트는 “Note”로 시작하며 class="note"로 구분해 제공합니다:

Note, 이것은 참고용 노트입니다.

권고 조언(advisement)은 규범적 문단으로 특별히 주의를 끌 수 있도록 스타일이 다르고 <strong class="advisement">로 구분됩니다: UA는 반드시 접근성 대안을 제공해야 합니다.

적합성 클래스

본 명세에 대한 적합성은 세 가지 적합성 클래스로 정의됩니다:

스타일 시트
CSS 스타일 시트.
렌더러
스타일 시트의 의미를 해석하고 이를 적용하는 UA. 해당 문서를 렌더링합니다.
작성 도구
스타일 시트를 작성하는 UA.

스타일 시트는 이 모듈에서 정의된 문법을 사용하는 모든 선언이 제네릭 CSS 문법 및 각 기능의 개별 문법에 따라 유효해야 본 명세에 적합한 것입니다.

렌더러는 스타일 시트 해석 외에도 명세에서 정의한 모든 기능을 올바르게 파싱/적용하며 문서를 렌더링해야 본 명세에 적합합니다. 단, 디바이스 한계로 인해 UA가 정확히 렌더링하지 못해도 비적합한 UA가 되는 것은 아닙니다. (예: 단색 모니터에서 색을 표시하지 않는 것은 필수 아님)

작성 도구는 제네릭 CSS 문법 및 이 모듈에서 정의된 기능의 개별 문법에 맞게 문법적으로 올바른 시트를 작성하며, 다른 스타일 시트 관련 적합성 요구사항도 모두 충족해야 본 명세에 적합합니다.

부분적 구현

저자들이 forward-compatible 파싱 규칙을 활용해 fallback 값을 지정할 수 있도록, CSS 렌더러는 반드시 지원불가(at-rule, 속성, 값, 키워드, 기타 문법 구조) 는 모두 무효로 취급(그리고 적합하게 무시)해야 합니다. 특히, UA는 지원하지 않는 구성값만 골라서 무시하고 지원하는 값만 인식하는 multi-value 선언을 절대 허용해서는 안 됩니다. 어떤 값이 무효라면 (지원 못하는 값은 무효), 해당 선언 전체를 CSS는 무시해야 합니다.

불안정/독점적 기능 구현

미래의 CSS 표준 안정화와 충돌을 피하려면 CSSWG는 최선 사례에 따라 불안정 기능 및 독점 확장을 구현할 것을 권고합니다.

비실험적 구현

명세가 Candidate Recommendation 단계에 도달하면, 비실험적 구현이 가능해지며 구현자는 CR 수준의 기능을 규격에 맞게 올바르게 구현했음을 입증할 수 있다면 접두어 없는(unprefixed) 구현체를 배포해야 합니다.

CSS 상호운용성을 확보하기 위해 CSSWG는 비실험적 CSS 렌더러가 구현 보고서(필요시 테스트케이스 포함)를 W3C에 제출한 뒤 접두어 없는 구현체를 배포하기를 요청합니다. W3C에 제출된 테스트케이스는 CSSWG의 검토와 수정 대상이 될 수 있습니다.

테스트케이스 및 구현 보고서 제출에 관한 자세한 정보는 CSS Working Group 웹사이트 https://www.w3.org/Style/CSS/Test/에서 확인할 수 있습니다. 문의사항은 public-css-testsuite@w3.org 메일링리스트로 보내주세요.

색인

이 명세서에서 정의한 용어

참조로 정의된 용어

참고 문헌

규범적인 참고문헌

[CSS-ALIGN-3]
Elika Etemad; Tab Atkins Jr.. CSS Box Alignment Module Level 3. 2023년 2월 17일. WD. URL: https://www.w3.org/TR/css-align-3/
[CSS-ANIMATIONS-1]
David Baron; 외. CSS Animations Level 1. 2023년 3월 2일. WD. URL: https://www.w3.org/TR/css-animations-1/
[CSS-ANIMATIONS-2]
David Baron; Brian Birtles. CSS Animations Level 2. 2023년 6월 2일. WD. URL: https://www.w3.org/TR/css-animations-2/
[CSS-BACKGROUNDS-3]
Elika Etemad; Brad Kemper. CSS Backgrounds and Borders Module Level 3. 2024년 3월 11일. CR. URL: https://www.w3.org/TR/css-backgrounds-3/
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS Cascading and Inheritance Level 5. 2022년 1월 13일. CR. URL: https://www.w3.org/TR/css-cascade-5/
[CSS-COLOR-5]
Chris Lilley; 외. CSS Color Module Level 5. 2024년 2월 29일. WD. URL: https://www.w3.org/TR/css-color-5/
[CSS-CONDITIONAL-3]
Chris Lilley; David Baron; Elika Etemad. CSS Conditional Rules Module Level 3. 2024년 8월 15일. CR. URL: https://www.w3.org/TR/css-conditional-3/
[CSS-CONDITIONAL-5]
Chris Lilley; 외. CSS Conditional Rules Module Level 5. 2024년 11월 5일. WD. URL: https://www.w3.org/TR/css-conditional-5/
[CSS-CONTAIN-3]
Tab Atkins Jr.; Florian Rivoal; Miriam Suzanne. CSS Containment Module Level 3. 2022년 8월 18일. WD. URL: https://www.w3.org/TR/css-contain-3/
[CSS-DISPLAY-3]
Elika Etemad; Tab Atkins Jr.. CSS Display Module Level 3. 2023년 3월 30일. CR. URL: https://www.w3.org/TR/css-display-3/
[CSS-EASING-1]
Brian Birtles; Dean Jackson; Matt Rakow. CSS Easing Functions Level 1. 2023년 2월 13일. CR. URL: https://www.w3.org/TR/css-easing-1/
[CSS-EASING-2]
CSS Easing Functions Level 2. 2024년 8월 29일. WD. URL: https://www.w3.org/TR/css-easing-2/
[CSS-FONTS-4]
Chris Lilley. CSS Fonts Module Level 4. 2024년 2월 1일. WD. URL: https://www.w3.org/TR/css-fonts-4/
[CSS-IMAGES-3]
Tab Atkins Jr.; Elika Etemad; Lea Verou. CSS Images Module Level 3. 2023년 12월 18일. CR. URL: https://www.w3.org/TR/css-images-3/
[CSS-IMAGES-4]
Tab Atkins Jr.; Elika Etemad; Lea Verou. CSS Images Module Level 4. 2023년 2월 17일. WD. URL: https://www.w3.org/TR/css-images-4/
[CSS-PROPERTIES-VALUES-API-1]
Tab Atkins Jr.; Alan Stearns; Greg Whitworth. CSS Properties and Values API Level 1. 2024년 3월 26일. WD. URL: https://www.w3.org/TR/css-properties-values-api-1/
[CSS-SIZING-3]
Tab Atkins Jr.; Elika Etemad. CSS Box Sizing Module Level 3. 2021년 12월 17일. WD. URL: https://www.w3.org/TR/css-sizing-3/
[CSS-SIZING-4]
Tab Atkins Jr.; Elika Etemad; Jen Simmons. CSS Box Sizing Module Level 4. 2021년 5월 20일. WD. URL: https://www.w3.org/TR/css-sizing-4/
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin. CSS Syntax Module Level 3. 2021년 12월 24일. CR. URL: https://www.w3.org/TR/css-syntax-3/
[CSS-TRANSFORMS-1]
Simon Fraser; 외. CSS Transforms Module Level 1. 2019년 2월 14일. CR. URL: https://www.w3.org/TR/css-transforms-1/
[CSS-TRANSFORMS-2]
Tab Atkins Jr.; 외. CSS Transforms Module Level 2. 2021년 11월 9일. WD. URL: https://www.w3.org/TR/css-transforms-2/
[CSS-TRANSITIONS-1]
David Baron; 외. CSS Transitions. 2018년 10월 11일. WD. URL: https://www.w3.org/TR/css-transitions-1/
[CSS-TYPED-OM-1]
Tab Atkins Jr.; François Remy. CSS Typed OM Level 1. 2024년 3월 21일. WD. URL: https://www.w3.org/TR/css-typed-om-1/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. 2024년 3월 12일. WD. URL: https://www.w3.org/TR/css-values-4/
[CSS-VALUES-5]
Tab Atkins Jr.; Elika Etemad; Miriam Suzanne. CSS Values and Units Module Level 5. 2024년 9월 17일. WD. URL: https://www.w3.org/TR/css-values-5/
[CSS-VARIABLES-1]
Tab Atkins Jr.. CSS Custom Properties for Cascading Variables Module Level 1. 2022년 6월 16일. CR. URL: https://www.w3.org/TR/css-variables-1/
[CSS-WRITING-MODES-4]
Elika Etemad; Koji Ishii. CSS Writing Modes Level 4. 2019년 7월 30일. CR. URL: https://www.w3.org/TR/css-writing-modes-4/
[CSS21]
Bert Bos; 외. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 2011년 6월 7일. REC. URL: https://www.w3.org/TR/CSS21/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.es/ecma262/multipage/
[FETCH]
Anne van Kesteren. Fetch Standard. Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; 외. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[MEDIAQUERIES-4]
Florian Rivoal; Tab Atkins Jr.. Media Queries Level 4. 2021년 12월 25일. CR. URL: https://www.w3.org/TR/mediaqueries-4/
[MEDIAQUERIES-5]
Dean Jackson; 외. Media Queries Level 5. 2021년 12월 18일. WD. URL: https://www.w3.org/TR/mediaqueries-5/
[REFERRER-POLICY]
Jochen Eisinger; Emily Stark. Referrer Policy. 2017년 1월 26일. CR. URL: https://www.w3.org/TR/referrer-policy/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. 1997년 3월. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[SELECTORS-3]
Tantek Çelik; 외. Selectors Level 3. 2018년 11월 6일. REC. URL: https://www.w3.org/TR/selectors-3/
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. Selectors Level 4. 2022년 11월 11일. WD. URL: https://www.w3.org/TR/selectors-4/
[WEB-ANIMATIONS-1]
Brian Birtles; 외. Web Animations. 2023년 6월 5일. WD. URL: https://www.w3.org/TR/web-animations-1/
[WEB-ANIMATIONS-2]
Brian Birtles; Robert Flack. Web Animations Level 2. 2023년 2월 21일. WD. URL: https://www.w3.org/TR/web-animations-2/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL Standard. Living Standard. URL: https://webidl.spec.whatwg.org/

참고용 참고문헌

[CSS-BOX-4]
Elika Etemad. CSS Box Model Module Level 4. 2024년 8월 4일. WD. URL: https://www.w3.org/TR/css-box-4/
[CSS-CASCADE-4]
Elika Etemad; Tab Atkins Jr.. CSS Cascading and Inheritance Level 4. 2022년 1월 13일. CR. URL: https://www.w3.org/TR/css-cascade-4/
[CSS-CASCADE-6]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS Cascading and Inheritance Level 6. 2024년 9월 6일. WD. URL: https://www.w3.org/TR/css-cascade-6/
[CSS-COLOR-4]
Chris Lilley; Tab Atkins Jr.; Lea Verou. CSS Color Module Level 4. 2024년 2월 13일. CR. URL: https://www.w3.org/TR/css-color-4/
[CSS-LISTS-3]
Elika Etemad; Tab Atkins Jr.. CSS Lists and Counters Module Level 3. 2020년 11월 17일. WD. URL: https://www.w3.org/TR/css-lists-3/
[CSS-SCOPING-1]
Tab Atkins Jr.; Elika Etemad. CSS Scoping Module Level 1. 2014년 4월 3일. WD. URL: https://www.w3.org/TR/css-scoping-1/
[CSS22]
Bert Bos. Cascading Style Sheets Level 2 Revision 2 (CSS 2.2) Specification. 2016년 4월 12일. WD. URL: https://www.w3.org/TR/CSS22/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS Object Model (CSSOM). 2021년 8월 26일. WD. URL: https://www.w3.org/TR/cssom-1/

속성 색인

이름 초기값 적용 대상 상속 백분율 애니메이션 타입 문법 기준 정렬 계산값
interpolate-size numeric-only | allow-keywords numeric-only all elements yes n/a not animatable per grammar as specified

이슈 색인

이곳은 CSS Values and Units Level 4와의 차이점을 명시한 명세(diff spec)입니다.
이 문법이 예를 들어 일부(혹은 전부) background-position 구성요소에 var()를 사용할 경우 롱핸드로 어떻게 확장될지 정의가 필요함. [이슈 #9690]
이 절은 실험적 초안이며, 아직 CSSWG의 승인을 받지 않았습니다. [이슈 #6245]
percent-progress() 표기가 필요한지, 아니면 충분한 곳에서 자동 변환이 일어나서 불필요한지 확인해야 합니다.
이 기능은 여러 개의 브레이크포인트 처리를 잘못함, 그리고 다시 설계가 필요할 수도 있음. [이슈 #6245]
mix() 표기법에는 keyframe 집합을 받는 변형이 있습니다. 해당 방식을 @keyframes 규칙을 참조하여, 거기서 해당 속성 선언을 추출하는 식으로 처리합니다. 다른 mix 표기법도 keyframe을 받을 수 있게 하면 좋겠으나, component value(전체 속성값이 아닌)에 대해 keyframe 집합을 어떻게 표현할지 정의가 필요합니다.
<progress> 는 0-100% 범위를 넘는 백분율을 반환할 수 있지만, color-mix()는 그런 값을 허용하지 않으므로, 그 처리 방식을 정의해야 함.
이름을 다르게 해야 할까? 이 기능을 추가하기로 했을 때 완전히 결정하진 않았습니다.
이론상으론 random()을 속성 외의 문맥에서 써도 괜찮아야 하긴 하나, per-element가 지정되지 않는 한 @media (max-width: random(100px, 500px)) {...} 등에서 동작이 명확하기 때문입니다. 하지만 사용금지하는 게 맞을지?
임의 대체 함수 정의가 필요함, 아마도 Variables에서 다룰 예정, 곧 여러 함수가 이 기능을 의존하게 될 전망.
random-item()는 var()-과 유사하므로, 속성에서만 사용 가능하도록 제한하는 것이 적절할 듯합니다. (비슷한 모든 함수에도 해당 방식을 적용할 계획.) 다만 random()은 근본적으로 다른 종류의 값이므로, 일관성 차원에서 마찬가지 제한을 권고할 수도 있음.
이 함수들 중 일부가 속성 이외 문맥에서 유효해야 할까?