1. 소개
이 섹션은 규범적이지 않습니다.
참고: 현재 이 명세에서는 CSS 값 수준에서 동작하는 사용자 정의 함수만 정의합니다. 추후 스타일 규칙 수준에서 동작하는 "믹스인"도 정의될 예정입니다.
사용자 정의 속성은 저자가 한 곳에서 유용하고 때로는 복잡한 값을 정의하고 스타일시트 전반에 재사용할 수 있는 강력한 기능을 제공합니다. 이러한 값은 문서 전체 또는 미디어 쿼리나 기타 조건에 따라 달라질 수 있어 매우 유연하고 반응성이 높습니다.
하지만 그 값은 정의 시점에 고정되며, 이전 정의를 완전히 덮어쓰기 전에는 변경할 수 없습니다: --shadow: 2px 2px var(--shadow-color) 선언은 해당 요소에서 선언된 --shadow-color 값을 사용하고, 이후 자손 요소에서 --shadow-color를 변경해도 그 요소의 --shadow 값에는 영향을 주지 않습니다; --shadow가 정의된 위치의 그림자 색상을 계속 사용합니다. 이는 이처럼 복합 변수(composite variable)를 많이 사용하는 저자들에게 흔히 혼란을 야기합니다.
사용자 정의 함수는 사용자 정의 속성과 동일한 강력함을 제공하지만, 매개변수화가 가능합니다: 사용자 정의 속성 정의와 같은 유연성과 조건부 기능을 가지면서도, 다른 사용자 정의 속성(또는 명시적으로 인자)에서 사용 시점에 값을 가져옵니다. 예를 들어, --shadow 사용자 정의 속성 대신, --shadow() 사용자 정의 함수를 다음과 같이 정의할 수 있습니다:
@function --shadow ( --shadow-color <color> : inherit) { /* --shadow-color 인자가 전달되지 않거나, <color>로 정상적으로 파싱되지 않으면, 대신 해당 요소의 --shadow-color *속성*을 사용 */ /* var(--shadow-color)는 --shadow-color 파라미터를 참조하며, 사용자 정의 속성을 참조하는 것이 아니지만, 여전히 보통처럼 폴백 값을 사용할 수 있음 */ result:2 px 2 px var ( --shadow-color, black); } .foo{ --shadow-color : blue; box-shadow : --shadow (); /* 파란 그림자 생성 */ /* 또는 */ box-shadow:--shadow ( blue); }
2. 사용자 정의 함수 정의
사용자 정의 함수는 고급 사용자 정의 속성으로 볼 수 있습니다. 단일 고정 값으로 대체되는 대신, 함수 파라미터 및 호출 시점의 사용자 정의 속성 값을 기반으로 대체 값을 계산합니다. 사용자 정의 속성의 var() 문법 대신, 사용자 정의 함수는 <dashed-function> 문법으로 호출되며, 추가 값을 인자로 전달할 수 있습니다.
@function --negative ( --value) { result : calc ( -1 *var ( --value)); }
그리고 이 함수는 선언에서 --negative()로 참조할 수 있습니다:
html{ --gap : 1 em ; padding : --negative ( var ( --gap)); /* 또는 값을 직접 전달할 수도 있음: */ padding:--negative ( 1 em ); }
<dashed-function>은 임의 치환 함수이며, var()와 유사합니다. 속성 값에 존재하면 파싱 시점에는 유효하다고 간주되며, 임의 치환이 발생한 후 계산값(computed-value) 시점에 평가 및 파싱됩니다.
2.1. @function 규칙
@function 규칙은 사용자 정의 함수를 정의하며, 이름, 파라미터 목록, 함수 본문, 그리고 선택적으로 반환 타입(문법 정의로 기술됨)을 포함합니다.
각 함수 파라미터는 이름(<custom-property-name>), 선택적으로 파라미터 타입(문법 정의로 기술됨), 그리고 선택적으로 기본값으로 구성됩니다.
<@function> = @function <function-token> <function-parameter>#? ) [ returns <css-type> ]? { <declaration-rule-list> } <function-parameter> = <custom-property-name> <css-type>? [ : <declaration-value> ]? <css-type> = <syntax-component> | <type()> <type()> = type( <syntax> )
2.1.1. 함수 서두
<function-token> 생성식은 <dashed-ident>처럼 반드시 두 개의 하이픈(U+002D HYPHEN-MINUS)으로 시작해야 하며, 그렇지 않으면 정의가 무효입니다.
생성된 사용자 정의 함수의 이름은 <function-token>의 이름으로, 선택적 함수 파라미터는 <function-parameter> 값으로 (기본값: 빈 집합), 선택적 반환 타입은 returns 키워드 뒤의 <css-type>으로 (기본값: type(*)) 지정됩니다.
@function --foo ( --a <length>) { /* ... */ } @function --foo ( --a <color>) { /* ... */ } @function --foo ( --a <length>+) { /* ... */ }
하지만, <syntax>와 같이 <syntax-combinator>가 필요한 경우에는 type() 함수로 감싸야 합니다:
@function --foo ( --atype ( <number> | <percentage>)) { /* ... */ }
@function 규칙의 이름은 트리 범위 이름입니다. 동일한 이름의 @function이 둘 이상 존재할 경우, 더 강한 계단식 레이어의 규칙이 우선하며, 같은 레이어 내에서는 나중에 정의된 규칙이 우선합니다.
함수 파라미터에 동일한 <custom-property-name>이 두 번 이상 포함되면, 해당 @function 규칙은 무효입니다.
2.1.2. 함수 본문
@function 규칙의 본문은 조건부 그룹 규칙(예: @media)을 허용합니다. 또한 다음 기술자를 허용합니다:
-
result 기술자: 함수 평가의 결과를 결정합니다. result 기술자가 없으면 함수는 유효하지만 항상 보장된-무효 값을 반환합니다.
-
사용자 정의 속성: 지역 변수를 제공합니다.
알 수 없는 기술자는 무효로 간주되어 무시되지만, @function 규칙 자체는 무효가 아닙니다.
2.2. result 기술자
이름: | result |
---|---|
대상: | @function |
값: | <declaration-value>? |
초기값: | n/a (본문 참조) |
result 기술자는 함수를 평가할 때 사용자 정의 함수가 반환하는 결과를 정의합니다. var() 함수를 사용해 함수 파라미터, 지역 변수, 그리고 <dashed-function>을 통해 다른 사용자 정의 함수도 참조할 수 있습니다.
result 기술자 자체는 타입이 없지만, 해결된 값은 치환 시 <dashed-function>의 타입 검사를 받습니다.
2.3. 인자 및 지역 변수
이 섹션은 비규범적입니다.
사용자 정의 함수의 함수 본문 내에서 var() 함수는 지역 변수(함수 본문에 정의된 사용자 정의 속성), 함수 인자(함수에 전달된 값 또는 기본값), 그리고 호출 위치(요소 또는 다른 사용자 정의 함수)에 정의된 사용자 정의 속성에 접근할 수 있습니다.
이 목록에서, 앞에 있는 것이 같은 이름일 경우 "이깁니다" — 만약 지역 변수 --foo가 있으면 var(--foo)는 그 지역 변수로 치환되고, 인자나 외부에서 정의된 사용자 속성으로 치환되지 않습니다. 다른 값들도 접근은 가능합니다: --foo 지역 변수를 initial로 설정하면 그 인자 값으로, inherit로 설정하면 호출 위치의 --foo 사용자 속성 값으로 처리됩니다.
@function --outer ( --outer-arg) { --outer-local : 2 ; result : --inner (); } @function --inner () returns <number>{ result : calc ( var ( --outer-arg) +var ( --outer-local)); } div{ z-index : --outer ( 1 ); /* 3 */ }
이와 유사하게, 사용자 정의 속성도 자동으로 사용할 수 있습니다:
@function --double-z () returns <number>{ result : calc ( var ( --z) *2 ); } div{ --z : 3 ; z-index : --double-z (); /* 6 */ }
하지만 함수 인자가 사용자 정의 속성을 "가린다(shadow)", 그리고 지역 변수는 둘 다를 "가린다":
@function --add-a-b-c ( --b, --c) { --c : 300 ; result : calc ( var ( --a) +var ( --b) +var ( --c)); /* 호출 위치의 --a 사용자 정의 속성, 함수 인자의 --b, 그리고 지역 변수의 --c를 사용 */ } div{ --a : 1 ; --b : 2 ; --c : 3 ; z-index : --add-a-b-c ( 20 , 30 ); /* 321 */ }
3. 사용자 정의 함수 사용
사용자 정의 속성의 값이 var()로 다른 속성 값에 치환될 수 있는 것처럼, 사용자 정의 함수의 평가 결과도 <dashed-function>으로 속성 값에 치환할 수 있습니다.
<dashed-function>은 함수 이름이 두 개의 하이픈(U+002D HYPHEN-MINUS)으로 시작하는 함수형 표기입니다. 그 인자 문법은 다음과 같습니다:
<dashed-function> = --*( <declaration-value>#? )
<dashed-function>은 var()가 허용되는 위치에서만 사용할 수 있습니다.
속성에 하나 이상의 <dashed-function>이 포함되어 있으면, 해당 속성의 전체 문법은 파싱 시점에 항상 유효하다고 간주됩니다. 계산값(computed-value) 시점에 모든 <dashed-function>은 치환되어야 하고, 그 후 속성의 문법과 검증됩니다.
참고: 사용자 정의 함수의 본문 내에서 var() 함수는, <dashed-function>이 사용된 요소에서와는 다르게 해석될 수 있습니다. § 3.1 사용자 정의 함수 평가 참고.
<dashed-function>은 어떤 컨텍스트에서 평가됩니다: 요소의 속성 값에서 (또는 @keyframes 등 결국 요소의 속성처럼 처리되는 기술자에서), 혹은 다른 사용자 정의 함수의 함수 본문에서 "가상의" 요소에 대해 기술자에서. 어느 경우든, 이것은 호출 컨텍스트를 제공하며, 여기에는 <dashed-function>이 포함된 속성/기술자 이름과, 그 속성/기술자가 적용되는 요소(또는 "가상의" 요소)가 포함됩니다.
호출 컨텍스트가 <dashed-function> 평가에 의해 중첩될 때, 호출 컨텍스트의 루트 요소는 호출 컨텍스트 스택의 최상위 실제 요소입니다.
-
function을 dashed function의 이름으로 트리 범위 참조로 역참조합니다. 해당 이름이 존재하지 않으면 보장된-무효 값을 반환합니다.
-
각 arg마다 arguments에서 임의 치환 함수를 치환한 뒤 arg를 그 결과로 대체합니다.
-
dashed function이 요소의 속성에서 치환되는 경우, calling context를 해당 요소와 속성으로 구성합니다.
그 외에는 "가상의 요소"에서 다른 사용자 정의 함수를 평가할 때 기술자에서 치환됩니다. calling context를 해당 "가상의 요소"와 기술자로 구성합니다.
-
사용자 정의 함수 평가를 function, arguments, calling context로 수행하고, 결과 값의 동등 토큰 시퀀스를 반환합니다.
{}
로 감싸면 하나의 인자로 전달할 수 있습니다:
@function --max-plus-x ( --list, --x) { result : calc ( max ( var ( --list)) +var ( --x)); } div{ width : --max-plus-x ({ 1 px , 7 px , 2 px }, 3 px ); /* 10px */ }
--foo ()
는 자기 자신과 순환(cycle)을 이룹니다:
@function --foo ( --x) { result : --foo ( 10 ); }
비슷하게,
도 자기 자신과 순환되지만,
--x
지역 변수가 result에서 결코 참조되지 않아도
마찬가지입니다:
@function --bar () { --x : --bar (); result : 1 ; }
하지만
는 아래 예시에서는 자기 자신과 순환되지 않습니다.
result
선언을
규칙 내에서 평가하지
않기 때문입니다:
@function --baz ( --x) { @media ( unknown-feature) { result : --baz ( 42 ); } result:1 ; }
--baz ()
함수는 순환에 걸리지 않습니다:
var ( --x)
와 var ( --y)
가 함수 본문에 있어도,
각각 함수 인자와 지역 변수를 참조할 뿐입니다.
사용자 정의 속성 --x
와 --y
는 모두 --baz ()
함수를
참조하지만, 괜찮습니다:
해당 사용자 정의 속성은 --baz ()
함수 내에서 참조되지 않기 때문입니다.
@function --baz ( --x) { --y : 10 px ; result : calc ( var ( --x) +var ( --y)); } div{ --x : --baz ( 1 px ); --y : --baz ( 2 px ); width : var ( --x); /* 11px */ height:var ( --y); /* 12px */ }
3.1. 사용자 정의 함수 평가
사용자 정의 함수는 본질적으로 함수 본문을 스타일 규칙처럼 가상의 요소에 적용한다고 가정하고, 일반적인 스타일 해석을 수행한 뒤, 그 가상의 요소의 result 기술자 값을 반환함으로써 평가됩니다. 가상의 요소는 호출 컨텍스트의 자식처럼 모든 사용자 정의 속성 값을 "상속"하고, 함수 인자가 동일 이름의 "상속된" 사용자 속성 값을 덮어씁니다.
-
substitution context를 «"function", custom function»로 하는 치환 컨텍스트로 설정합니다.
참고: 트리-스코프로 인해, 동일 함수명이 스택에 여러 번 나타날 수 있으며 서로 다른 사용자 정의 함수를 참조할 수 있습니다. 그래서 사용자 정의 함수 그 자체가 치환 컨텍스트에 포함됩니다. 단순히 이름만이 아니라.
-
가드 substitution context로 이후 알고리즘을 진행합니다. substitution context가 순환적으로 표시되었다면, 보장된-무효 값을 반환합니다.
-
arguments의 항목 수가 custom function의 함수 인자 수보다 많으면 보장된-무효 값을 반환합니다.
-
registrations를 빈 사용자 정의 속성 등록 집합으로 설정합니다.
-
각 함수 인자마다 해당 이름으로, 인자 타입 문법, 상속 플래그 true, 초기값 없음으로 사용자 정의 속성 등록을 생성해 registrations에 추가합니다.
-
custom function에 반환 타입이 있으면, 이름 "return"(일반 등록 명명 규칙 위반), 반환 타입 문법, 상속 플래그 false, 초기값 없음으로 사용자 정의 속성 등록을 생성해 registrations에 추가합니다.
-
argument rule을 빈 스타일 규칙으로 설정합니다.
-
각 함수 인자에 대해:
-
함수 스타일 해석을 custom function, argument styles, registrations, calling context로 수행합니다. argument styles를 결과로 설정합니다.
-
registrations의 각 사용자 정의 속성 등록에 대해, 초기값을 argument styles의 해당 값으로, 문법을 universal syntax definition으로 설정하고, argument styles의 속성 이름과 값을 갖는 사용자 정의 속성을 body rule에 맨 앞에 추가합니다.
-
함수 스타일 해석을 custom function, body rule, registrations, calling context로 수행합니다. body styles를 결과로 설정합니다.
-
만약 substitution context가 순환적 치환 컨텍스트로 표시되었다면, 보장된-무효 값을 반환합니다.
참고: 중첩된 임의 치환 함수가 2단계 이후 어느 시점에 substitution context를 순환적으로 표시할 수도 있습니다. 예를 들어 result 해석 시.
-
body styles의 result 속성 값을 반환합니다.
-
"가상의 요소" el을 생성하고, el은 calling context의 요소의 자식처럼 동작한다. el은 기능 없는 요소(featureless)이며, 사용자 정의 속성과 result 기술자만 적용된다.
-
rule을 el에 지정값(specified value) 단계까지 적용하되, 다음 변경사항을 적용한다:
-
registrations에 들어 있는 사용자 정의 속성 등록만 보이고, 그 외의 사용자 정의 속성은 등록되지 않은 것으로 처리한다.
-
calling context의 속성의 상속값은 무효값(guaranteed-invalid value)이다.
-
사용자 정의 속성에서, CSS-wide 키워드 initial과 inherit는 본래 기능을 하며, 다른 CSS-wide 키워드는 모두 무효값으로 처리된다.
참고: initial은 함수 인자로 생성된 사용자 정의 속성 등록을 참조하여, 전달된 값으로 속성을 "리셋"할 수 있다. inherit은 호출 컨텍스트의 요소에서 상속된다.\
result에서는, 모든 CSS-wide 키워드가 미해결 상태로 남는다.
참고: 예를 들어 result: inherit은 <dashed-function>이 inherit 키워드로 평가되게 한다. var(--unknown, inherit)과 유사하다.
-
어떤 사용자 정의 속성 prop에 대해, 해당 속성의 속성 치환(property replacement) 단계에서는 치환 컨텍스트에 custom function도 포함된다. 즉, 치환 컨텍스트는 «"property", prop의 이름, custom function»
참고: 동적 스코프(dynamic scoping)로 인해, 동일한 속성명이 스택에 여러 번 나타날 수 있으며 서로 다른 사용자 정의 속성을 참조할 수 있다. 그래서 custom function 그 자체가 치환 컨텍스트에 포함된다. 단순히 이름만이 아니라.
-
-
모든 사용자 정의 속성과 el의 result "속성"의 계산값(computed value)을 결정한다. CSS Properties and Values API 1 § 2.4 Computed Value-Time Behavior에 정의된 대로, 앞 단계의 변경사항과 아래 사항을 적용한다:
-
사용자 정의 속성 참조(평소처럼 el의 값을 사용), 숫자/퍼센트(사용자 정의 속성 내에서는 미해결로 남음)를 제외하고, 일반적으로 스타일 대상 요소를 참조하는 값은 calling context의 루트 요소를 참조한다.
참고: 예를 들어 속성 내 attr(), 또는 규칙 내 @container 쿼리 등.
-
-
el의 스타일을 반환한다.
4. 커스텀 함수의 실행 모델
CSS의 다른 부분과 마찬가지로, 커스텀 함수도 선언적 모델을 따릅니다.
지역 변수 기술자와 result 기술자는 어떤 순서로든 나타날 수 있으며, 여러 번 작성해도 됩니다. 이런 경우, 나중에 등장한 선언이 더 앞선 선언을 덮어씁니다.
@function --circle-area ( --r) { result : calc ( pi *var ( --r2)); --r2 : var ( --r) *var ( --r); }
지역 변수 기술자는 참조보다 전에 나와도 되고 후에 나와도 됩니다.
4.1. 조건부 규칙
조건부 그룹 규칙이 @function 안에 나타나면 중첩 그룹 규칙이 되고, 추가적으로 @function 내에서 허용된 기술자만 중첩 그룹 규칙 내에 쓸 수 있습니다.
조건부 그룹 규칙은 @function 내에서 일반 규칙대로 처리되며, 조건이 true일 때 규칙 내용이 해당 위치에 있는 것처럼 동작하고, 그렇지 않으면 아무것도 없는 것처럼 동작합니다.
@function --suitable-font-size () { result : 16 px ; @media ( width >1000 px ) { result : 20 px ; } }
result 기술자 값은 미디어 쿼리 조건이 true면
이고, 아니면
입니다.
@function --suitable-font-size () { @media ( width >1000 px ) { result : 20 px ; } result:16 px ; }
위 예시에서 result 기술자 값은 항상
입니다.
@function --suitable-font-size () { --size : 16 px ; @media ( width >1000 px ) { --size : 20 px ; } result:var ( --size); }
5. CSSOM
5.1. CSSFunctionRule
인터페이스
CSSFunctionRule
인터페이스는 @function 규칙을 나타냅니다.
[Exposed =Window ]interface :
CSSFunctionRule CSSGroupingRule {readonly attribute CSSOMString name ;sequence <FunctionParameter >();
getParameters readonly attribute CSSOMString returnType ; };
name
, 타입 CSSOMString, 읽기 전용- 커스텀 함수의 이름입니다.
returnType
, 타입 CSSOMString, 읽기 전용- 커스텀 함수의 문법 문자열로 표현된 반환 타입입니다.
커스텀 함수에 반환 타입이 없는 경우,
을 반환합니다."type(*)"
dictionary {
FunctionParameter required CSSOMString ;
name required CSSOMString ;
type CSSOMString ?; };
defaultValue
- name
- 함수 인자의 이름입니다.
- type
- 함수 인자의 타입으로,
문법 문자열로 표현되며,
인자에 타입이 없으면
입니다."type(*)" - defaultValue
- 함수 인자의 기본값, 인자에 기본값이 없으면 `null`입니다.
@function 규칙 내에 선언을 직접 명시할 수 있지만,
CSSOM에서는 그렇게 표현되지 않습니다.
대신 연속된 선언 구간이 CSSFunctionDeclarations
규칙으로 래핑된 것처럼 나타납니다.
참고: 이는 @function 규칙의 맨 앞 선언(즉, 다른 중첩 규칙 뒤에 오지 않은 선언)에도 적용됩니다.
@function --bar () { --x : 42 ; result : var ( --y); @media ( width >1000 px ) { /* ... */ } --y:var ( --x); }
위는 CSSOM에서 다음처럼 나타납니다:
@function --bar () { /* CSSFunctionDeclarations { */ --x:42 ; result : var ( --y); /* } */ @media ( width >1000 px ) { /* ... */ } /* CSSFunctionDeclarations { */ --y:var ( --x); /* } */ }
-
문자열
과 단일 공백(U+0020)."@function" -
함수 이름에 대해 serialize an identifier를 수행한 결과와 단일 왼쪽 괄호(U+0028).
-
serialize a function parameter를 함수의 parameters 각각에 수행한 결과를
(COMMA U+002C, 뒤에 단일 공백 U+0020)로 연결.", " -
단일 오른쪽 괄호(U+0029).
-
함수에 반환 타입이 있고, 반환 타입이 universal syntax definition("*")이 아닌 경우:
-
단일 공백(U+0020),
문자열, 단일 공백(U+0020)."returns" -
serialize a CSS type을 해당 type에 수행한 결과와 단일 공백(U+0020).
-
-
단일 왼쪽 중괄호(U+007B), 단일 공백(U+0020).
-
serialize a CSS rule을 cssRules의 각 규칙에 대해 수행한 결과(빈 문자열은 걸러냄)를 단일 공백(U+0020)으로 연결.
참고: serialize a CSS rule은 빈
CSSFunctionDeclarations
규칙을 직렬화할 때 빈 문자열을 반환할 수 있습니다. -
단일 공백(U+0020), 단일 오른쪽 중괄호(U+007D).
-
serialize an identifier를 함수 인자의 이름에 대해 수행한 결과.
-
함수 인자에 타입이 있고, 타입이 universal syntax definition이 아니면:
-
단일 공백(U+0020), serialize a CSS type을 해당 타입에 수행한 결과.
-
-
-
단일 콜론(U+003A), 단일 공백(U+0020), serialize a CSS value를 해당 값에 수행한 결과.
-
-
<css-type>이 단일 <syntax-component>로만 구성되어 있으면, 해당 문법 문자열을 반환.
-
그 외에는, 다음을 이어붙여 반환:
-
문자열
(즉"type("
과 단일 왼쪽 괄호(U+0028))."type" -
해당 문법 문자열.
-
문자열
(즉 단일 오른쪽 괄호(U+0029)).")"
-
5.2.
CSSFunctionDeclarations
인터페이스
CSSFunctionDeclarations
인터페이스는 선언이 @function 규칙 내에서 연속적으로 나타나는 부분을 나타냅니다.
[Exposed =Window ]interface :
CSSFunctionDescriptors CSSStyleDeclaration {attribute [LegacyNullToEmptyString ]CSSOMString ; }; [
result Exposed =Window ]interface :
CSSFunctionDeclarations CSSRule { [SameObject ,PutForwards =cssText ]readonly attribute CSSFunctionDescriptors style ; };
style
속성은 해당 규칙의
CSSFunctionDescriptors
객체를 반환해야 하며, 다음 속성을 가져야 합니다:
- computed flag
-
설정 안 됨
- readonly flag
-
설정 안 됨
- declarations
- parent CSS rule
- owner node
-
null
CSSFunctionDeclarations
규칙은 CSSNestedDeclarations
와
같이,
직렬화될 때 선언 블록이 선언
블록이 직접 직렬화된 것처럼 나타납니다.
6. 프라이버시 고려사항
이 명세서에서 정의된 구조체들은 모두 CSS 내부에서만 정의되고 사용되며, 새로운 정보를 노출하지 않습니다.
7. 보안 고려사항
이 명세서에는 아직 제기된 이슈가 없습니다.