1. 소개
[css-variables-1] 명세는 "계단식 변수(cascading variables)"의 개념을 정의하였습니다. 이는 사용자 정의 속성(custom properties)의 값을 기반으로 작성자가 정의한 변수로, var() 함수를 통해 임의의 다른 속성에 치환될 수 있습니다.
이 명세서는 이와 연관되지만 더 단순한 환경 변수의 개념을 정의합니다. "계단식 변수"는 해당 사용자 정의 속성이 여러 값으로 바뀌면서 페이지 전체에서 값이 변할 수 있지만, 환경 변수는 특정 문서 전체에 "전역적"으로 적용되며 값이 어디서나 동일합니다. env() 함수를 사용하여 이 값을 임의의 위치에 치환할 수 있으며, var() 함수와 유사하게 동작합니다.
이러한 "전역" 변수는 계단식 변수에 비해 장점과 단점을 모두 가지고 있습니다:
-
많은 변수들은 페이지 내에서 변하지 않으며, 테마를 설정하거나 특정 숫자 값을 위한 도구로 사용됩니다. 환경 변수를 사용자 정의 속성 대신 정의하면, 그 의도를 명확히 전달할 수 있습니다. 이는 문서 작성자(특히 여러 명이 협업할 때)와 사용자 에이전트 모두에게 좋으며, 사용자 에이전트가 이러한 변수를 더 효율적으로 저장할 수 있게 해줍니다.
-
환경 변수는 특정 요소에서 가져온 값을 기반으로 하지 않기 때문에, 명확한 요소가 없는 곳(예: @media 규칙 등)에서도 사용할 수 있습니다. 이 경우 var() 함수는 사용할 수 없습니다.
-
사용자 에이전트 자체의 정보(예: 기본적으로 레이아웃이 배치되지 않도록 뷰포트의 마진—예를 들어 화면의 "노치"와 겹치지 않게 하는 영역 등)는 env()로 가져올 수 있습니다. 반면 var()는 요소별 특성 때문에 이런 정보를 전달하기에 적합하지 않습니다.
대부분의 환경
변수는 한 번에 하나의 값만 가집니다.
하지만 일부는 "인덱스"를 가지며, 여러 값을 동시에 나타냅니다.
예를 들어 viewport-segment-* 변수는 여러 개의 고유한 콘텐츠 패널의 크기와 위치를 나타냅니다.
이러한 인덱스가 필요한 변수에 접근하려면 변수명과 함께 하나 이상의 정수값을 제공해야 하며,
예를 들어 viewport-segment-width 1 0처럼 사용하여
가능성 목록이나 그리드에서 하나의 값을 선택합니다.
이는 전통적인 프로그래밍 언어에서 values[0]
와 같이 리스트에서 하나의 요소를 선택하는 방식과 유사합니다.
2. 환경 변수
CSS 환경 변수는 <declaration-value> (0개 이상의 CSS 토큰 시퀀스로, 어떤 토큰이든 거의 제한 없이 올 수 있음)과 연관된 이름입니다. 이는 사용자 정의 속성과 유사합니다. 환경 변수는 사용자 에이전트 또는 사용자가 정의할 수 있습니다. (후자의 경우, 이름은 <custom-property-name>이며, 사용자 정의 식별자 표준에 따라 `--`로 시작합니다.)
UA가 정의한
환경 변수의
집합이 스크립트에서 보이나요?
그렇다면, Document
에 해당 변수를 노출하는 API를 정의하세요.
저자가 환경 변수를 추가할 수 있는 방법을 정의하세요. JS와 CSS 모두를 통해 정의할 수 있으면 좋습니다. CSS 규칙과 JS로 정의한 값이 혼합될 경우 쉽게 복잡해질 수 있으니 주의하세요. (CSSFontFaceRule과 FontFace의 사례 참고)
아래의 UA 정의 환경 변수는 공식적으로 정의되어 있으며 반드시 지원되어야 합니다. 추가적으로 UA에서 정의한 환경 변수는 이 목록에 추가되기 전까지 지원해서는 안 됩니다.
2.1. 세이프 영역 인셋 변수
이름 | 값 | 차원 수 |
---|---|---|
safe-area-inset-top | <length> | 0 (스칼라) |
safe-area-inset-right | <length> | 0 (스칼라) |
safe-area-inset-bottom | <length> | 0 (스칼라) |
safe-area-inset-left | <length> | 0 (스칼라) |
세이프 영역 인셋은 네 개의 환경 변수로, 뷰포트의 상단, 우측, 하단, 좌측 인셋을 통해 사각형을 정의합니다. 직사각형 디스플레이에서는 모두 0이어야 하지만, 비직사각형 디스플레이에서는 사용자 에이전트가 선택한 사각형을 형성해야 하며, 사각형 내부의 모든 콘텐츠가 보이도록 하고, 인셋 중 하나라도 줄어들면 비직사각형 디스플레이의 특성상 내부 콘텐츠 일부가 보이지 않아야 합니다. 이를 통해 작성자는 중요한 콘텐츠의 레이아웃을 세이프 영역 내부에 제한할 수 있습니다.
2.2. 세이프 영역 최대 인셋 변수
이름 | 값 | 차원 수 |
---|---|---|
safe-area-max-inset-top | <length> | 0 (스칼라) |
safe-area-max-inset-right | <length> | 0 (스칼라) |
safe-area-max-inset-bottom | <length> | 0 (스칼라) |
safe-area-max-inset-left | <length> | 0 (스칼라) |
세이프 영역 최대 인셋은 네 개의 환경 변수로, 세이프 영역 인셋 변수와 연동되어 있습니다. 세이프 영역 인셋 변수가 동적인 값인 것과 달리, 세이프 영역 최대 인셋은 동적 값의 최대값을 나타내는 정적 값입니다. 동적 UA 인터페이스가 숨겨질 때의 최대값을 의미하며, 레이아웃 뷰포트 크기가 큰 뷰포트 크기가 됩니다.
2.3. 뷰포트 세그먼트 변수
이름 | 값 | 차원 수 |
---|---|---|
viewport-segment-width | <length> | 2 |
viewport-segment-height | <length> | 2 |
viewport-segment-top | <length> | 2 |
viewport-segment-left | <length> | 2 |
viewport-segment-bottom | <length> | 2 |
viewport-segment-right | <length> | 2 |
뷰포트 세그먼트는 환경 변수로, 뷰포트의 논리적으로 분리된 영역의 위치와 크기를 정의합니다. 뷰포트가 하나 이상의 하드웨어 특성(예: 폴드나 분리된 디스플레이 사이의 힌지)으로 분할될 때 세그먼트가 생성되며, 세그먼트는 작성자가 논리적으로 구분할 수 있는 뷰포트의 영역입니다.
뷰포트 세그먼트 환경 변수는 두 개의 차원을 가지며, 이는 하드웨어 특성으로 분리된 2차원 그리드에서 각각 x, y 위치를 나타냅니다. 왼쪽 가장자리의 세그먼트는 x 위치가 0이고, 오른쪽으로 한 칸 이동할 때마다 x 위치가 1씩 증가합니다. 마찬가지로, 위쪽 가장자리의 세그먼트는 y 위치가 0입니다.
참고: 특정 하드웨어 구성에서는 구분선 자체가 뷰포트 내 논리적 공간을 차지할 수 있습니다. 구분선의 크기는 뷰포트 세그먼트의 위치를 이용해 계산할 수 있습니다.
이 변수들은 두 개 이상의 세그먼트가 있을 때만 정의됩니다. 뷰포트를 분할하는 하드웨어 특성이 없을 때는 뷰포트 단위를 사용하는 것이 좋으며, 그렇지 않으면 다중 세그먼트 디바이스에서 콘텐츠가 의도대로 표시되지 않을 수 있습니다.
2.4. 선호 텍스트 확대
이름 | 값 | 차원 수 |
---|---|---|
preferred-text-scale | <number> | 0 (스칼라) |
preferred-text-scale 환경 변수는 사용자의 선호 텍스트 배율을 나타냅니다. 즉, 운영체제 및/또는 사용자 에이전트의 "기본" 글꼴 크기에 대해 사용자가 조정한 값을 의미합니다. (text-size-adjust가 적용되는 디바이스에서는, text-size-adjust: auto에 의해 적용되는 배율입니다.)
예를 들어, text-size-adjust:auto가 텍스트 크기를 두 배로 만든다면, env(preferred-text-scale) 값은 2가 됩니다.
참고: pem 단위는 동일한 정보를 나타냅니다. 1em은 calc(1em * env(preferred-text-scale))과 정확히 같습니다. 직접 크기를 지정할 때는 bsem이 더 편리한 길이 단위가 됩니다.
일반적으로 작성자는 다음 중 하나를 선택해야 합니다:
-
페이지의 모든 텍스트가 사용자의 선호에 따라 자동으로 확대되도록 text-size-adjust: calc(100% * env(preferred-text-scale));로 설정하고, 필요하다면 비텍스트 크기도 이 배율로 함께 조정하세요.
-
또는 text-size-adjust:none으로 설정한 뒤, 이 환경 변수 및/또는 pem 단위를 일관되게 사용하여 텍스트와 UI를 사용자의 선호에 맞게 조정하세요.
3. 환경 변수 사용: env() 표기법
환경 변수의 값을 CSS 컨텍스트에 치환하려면, env() 함수를 사용하세요:
env() = env( <custom-ident> <integer [0,∞]>*, <declaration-value>? )
env() 함수는 어떤 요소의 어떤 속성 값의 일부, 또는 어떤 at-rule의 어떤 디스크립터 값 일부 등, CSS 값이 허용되는 여러 위치에서 사용할 수 있습니다.
-
예를 들어 MQ 문법의 임의 부분을 대체할 수 있어야 합니다.
-
셀렉터도 대체할 수 있어야 할까요?
-
규칙 레벨에서 동작하여 선언 블록을 재사용하듯 임의의 내용을 삽입할 수 있어야 할까요?
env() 함수의 첫 번째 인자는 치환할 환경 변수의 이름을 지정합니다. 이어지는 인자들은, 이름이 배열 형태의 환경 변수인 경우, 해당 변수의 차원에 대한 인덱스를 나타내는 정수입니다. 쉼표 뒤에 오는 인자(있다면)는 대체 값(fallback)으로, 참조된 환경 변수가 존재하지 않을 때 사용됩니다.
참고: 사용자 정의 속성과 마찬가지로 fallback의 구문은 쉼표를 허용합니다. 예를 들어, env(foo, red, blue)는 red, blue를 대체 값으로 정의합니다. 즉, 첫 번째 쉼표부터 함수 끝까지가 모두 fallback 값으로 간주됩니다.
속성에 하나 이상의 env() 함수가 포함되어 있고, 그 함수들이 구문적으로 유효하다면, 전체 속성 문법은 파싱 시점에 유효한 것으로 간주해야 합니다. 실제 구문 검사는 env() 함수가 치환된 이후 계산 시점에만 수행됩니다.
디스크립터에 하나 이상의 env() 함수가 포함되어 있고, 그 함수들이 구문적으로 유효하다면, 전체 선언 문법은 파싱 시점에 유효한 것으로 간주해야 합니다. 실제 구문 검사는 env() 함수가 치환된 이후에만 수행됩니다.
-
env() 함수의 첫 번째 인자로 제공된 이름이 인식 가능한 환경 변수 이름이고, 제공된 정수 개수가 그 변수의 차원 수와 일치하며, 인덱스 값이 유효한 하위 값을 가리키면, 해당 이름의 env() 함수를 지정한 환경 변수의 값으로 대체합니다.
-
그렇지 않고 env() 함수에 두 번째 인자로 fallback 값이 있다면, env() 함수를 fallback 값으로 대체합니다. fallback에 env() 참조가 있으면, 그것도 치환합니다.
-
그 외의 경우, env() 함수가 포함된 속성 또는 디스크립터는 computed-value 시점에 유효하지 않음이 됩니다.
치환이 언제 발생하는지 정의하세요. var() 치환보다 먼저여야 합니다. 또는 env() 치환이 파싱 시점에 일어나서, 알 수 없는 변수명은 구문 검사 실패가 되도록 해야 할까요? var()처럼 computed-value 시점에 일어날 이유는 없습니다. 그 방식은 사용자 정의 속성이 값을 상속한 뒤 var()로 참조되도록 하기 위함이었습니다.
env()가 사용될 수 있는 다른 위치를 파악하면, 어떻게/언제 치환되는지 정의하세요.
3.1. 축약 속성에서의 환경 변수
env() 치환이 파싱 중에 발생한다면, 이 절은 불필요합니다.
env() 함수는 축약 속성에서 var() 함수와 동일한 문제를 야기할 수 있습니다. env()가 축약 속성에서 사용되면, CSS Variables 1 § 3.2 Variables in Shorthand Properties에 정의된 동일한 효과를 가집니다.
4. 개인정보 보호 고려사항
이 명세서에서 정의하는 환경 변수들은 잠재적으로 개인정보에 민감할 수 있습니다. 이는 페이지에 기존에 없던 추가 정보를 제공할 수 있기 때문입니다. 특히, 사용자가 페이지를 보는 기기에 대한 추가 정보를 노출하여 핑거프린팅 벡터가 될 수 있습니다.
지금까지 이 명세서에서 정의된 환경 변수들은 CSSWG의 검토를 거쳐 노출이 허용된 것으로 간주됩니다.
5. 보안 고려사항
이 명세서는 디바이스에 대한 새로운 유형의 정보를 읽기 전용으로 제공합니다.
이 명세서에서 정의하는 환경 변수는 보안에 민감한 정보를 노출하지 않습니다.