1. 소개
현재 이 문서는 레벨 5에서 새롭게 추가된 항목들의 초기 초안입니다. 레벨 3과 레벨 4의 기능들은 여전히 [css-conditional-3] 및 [css-conditional-4]에 정의되어 있으며, 아직 이곳으로 복사되지 않았습니다.
CSS Conditional Level 5는 @supports 규칙과 supports query 문법을 확장하여, 커스텀 지원 조건뿐 아니라 지원되는 at-rules 및 폰트 기술에 대한 테스트를 가능하게 합니다.
또한 @when 규칙을 추가하여 조건 규칙의 개념을 일반화합니다. 기존 조건 규칙에서 표현할 수 있는 모든 것은 해당 조건의 종류를 선언하는 적절한 함수로 감싸서 @when에서도 표현할 수 있습니다. 이를 통해 저자는 미디어 쿼리와 supports 쿼리 같은 여러 유형의 쿼리를 단일 불리언 표현식으로 쉽게 결합할 수 있습니다. 이 기능이 없으면 저자는 별도의 조건 규칙을 중첩하는 방식에 의존해야 하며, 이는 읽고 쓰기 어려울 뿐 아니라 조건들이 “and” 불리언 관계로 결합된다고 가정하게 만들고(다르게 표시하기도 쉽지 않음), 제안된 조건 규칙 체인에서의 활용도를 제한합니다.
또한 @else 규칙을 추가합니다. 이는 다른 조건 규칙 바로 뒤에 이어지며, 직전 규칙의 조건의 반대를 자동으로 적용하여, 조건 규칙 체인에서 일치하는 첫 번째 규칙만 적용되도록 합니다.
또한 컨테이너 쿼리를 추가합니다. 이는 개념적으로 미디어 쿼리와 유사하지만, 문서 전체가 아니라 문서 내 요소(예: 박스 치수 또는 계산된 스타일)의 특성을 테스트할 수 있도록 합니다.
2. @supports 규칙의 확장
이 레벨의 명세는 <supports-feature> 문법을 다음과 같이 확장합니다:
<supports-feature> = <supports-selector-fn>
| <supports-font-tech-fn> | <supports-font-format-fn>
| <supports-at-rule-fn>
| <supports-decl>
<supports-decl> = ( [ <declaration> | <supports-condition-name> ] )
<supports-font-tech-fn> = font-tech( <font-tech> )
<supports-font-format-fn> = font-format( <font-format> )
<supports-at-rule-fn> = at-rule( <at-keyword-token> )
- <supports-condition-name>
-
UA가 명명된 조건을 지원하면 결과는 true입니다. 이름을 인식하지 못하면 결과는 false입니다.
- <supports-font-tech-fn>
-
UA가 함수 인자로 제공된 폰트 기술을 지원하면 결과는 true입니다.
- <supports-font-format-fn>
-
UA가 함수 인자로 제공된 폰트 포맷을 지원하면 결과는 true입니다.
- <supports-at-rule-fn>
-
UA가 함수 인자로 제공된 at-rule을 지원하면 결과는 true입니다.
2.1. 지원 정의의 확장
2.1.1. 폰트 기술 및 형식
CSS 프로세서는 레이아웃과 렌더링에서 지정된 CSS Fonts 4 § 11.1 Font tech를 활용할 수 있을 때 폰트 기술을 지원한다고 간주됩니다.
CSS 프로세서는 레이아웃과 렌더링에서 CSS Fonts 4 § 11.2 Font formats에 지정된 형식을 활용할 수 있고, 이 형식이 <string>으로 지정되지 않았을 때 폰트 포맷을 지원한다고 간주됩니다.
2.1.2. At-규칙
CSS 프로세서는 어떤 컨텍스트에서든 지정된 at-keyword로 시작하는 at-rule을 허용한다면 at-rule을 지원한다고 간주됩니다.
참고: @charset은 유효한 at-rule이 아니므로, 이 정의에 따라 지원되는 것으로 간주되지 않습니다.
2.1.3. 이름이 있는 조건
CSS 프로세서는 관련된 명명된 supports 조건이 true를 반환할 때 이름이 있는 조건을 지원한다고 간주됩니다.
3. 일반화된 조건 규칙: @when 규칙
@when at-rule은 조건부 그룹 규칙으로서, @media 및 @supports 같은 개별 조건부 그룹 규칙을 일반화합니다. 정의는 다음과 같습니다:
@when <boolean-condition>{ <rule-list>}
여기서 <boolean-condition>은 Media Queries 4 § 3 Syntax의 불 대수와 유사하되, 잎(leaf)으로 media()와 supports() 함수가 사용됩니다.
Conditional에서 "잎이 X인 불 대수"를 일반적인 방식으로 정의하여, 모든 조건 규칙이 이를 직접 참조할 수 있도록 하고 각 규칙이 불 대수를 개별적으로 재정의하지 않도록 해야 합니다.
media() 및 supports() 함수는 다음과 같이 정의됩니다:
media () =media ( [ <mf-plain> | <mf-boolean> | <mf-range>] ) supports () =supports ( <declaration>)
media() 또는 supports() 함수는 그 안에 포함된 조건이 연관되는 불리언 결과와 연관됩니다.
4. 연쇄 조건: @else 규칙
일반적으로 조건부 그룹 규칙은 서로 독립적입니다. 각 규칙은 다른 규칙에 직접 의존하지 않는 별도의 조건을 가지며, 자신의 조건에만 근거하여 내부 규칙을 적용할지 여부를 결정합니다.
이는 단순한 조건에는 괜찮지만, 상호 배타적이어야 하는 조건 모음을 작성하기는 어렵게 만듭니다: 저자는 다른 규칙이 활성화되어야 할 때 자신이 활성화되지 않도록 매우 신중하게 조건을 구성해야 하며, 조건 모음이 실수로 모두 어떤 상황을 배제하여 그 상황이 스타일 없이 남지 않도록 보장해야 합니다.
@else 규칙은 조건부 그룹 규칙을 연결한 조건 규칙 체인을 구성하는 데 사용되며, 여러 조건부 그룹 규칙을 연관시켜 일치하는 첫 번째 규칙만 자신의 조건을 true로 평가하도록 보장합니다. 정의는 다음과 같습니다:
@else <boolean-condition>?{ <rule-list>}
@else는 @when과 동일하게 해석됩니다. <boolean-condition>이 생략되면 항상 true인 조건을 가진 것으로 취급됩니다.
조건 규칙 체인은 연속된 조건부 그룹 규칙의 시퀀스로서, @else가 아닌 조건부 그룹 규칙으로 시작하고 그 뒤에 0개 이상의 @else 규칙이 따릅니다. 연속된 조건부 그룹 규칙들 사이에는 공백 및/또는 주석 외에는 어떤 것도 올 수 없으며, 그 외의 토큰이 있으면 체인이 “끊어집니다”.
체인에서 마지막 @else만 조건 생략을 허용하도록 요구해야 할까요? 디버깅 시 if-else 체인의 하나를 "true"로 설정해 단락시키는 일은 흔하며, CSS에서도 비슷하게 유용할 것입니다. 조건을 실수로 생략했을 때도 잘못되었음을 비교적 쉽게 알아볼 수 있습니다.
조건 규칙 체인 내에서 각 조건부 그룹 규칙의 조건은 순서대로 평가됩니다. 그중 하나가 true이면, 체인에서 그 이후의 모든 조건부 그룹 규칙의 조건은 명시된 조건과 상관없이 false로 평가됩니다.
@else 규칙이 조건 규칙 체인의 일부가 아니면 유효하지 않으며 무시되어야 합니다.
@when media ( width >=400 px ) andmedia ( pointer: fine) andsupports ( display: flex) { /* A */ } @else supports ( caret-color: pink) andsupports ( background:double-rainbow ()) { /* B */ } @else { /* C */ }
위 규칙들 중 정확히 하나만 선택됩니다. 두 번째 규칙이 큰 너비, 정밀 포인터, 또는 플렉스박스 지원을 배제하지 않더라도, 그리고 마지막 규칙이 아무 것도 지정하지 않더라도 마찬가지입니다.
조건 규칙 체인 없이 동일한 결과를 얻으려면 다음처럼 작성해야 합니다:
@media ( width >=400 px ) and( pointer: fine) { @supports ( display: flex) { /* A */ } @supports not( display: flex) { @supports ( caret-color: pink) and( background:double-rainbow ()) { /* B */ } @supports not(( caret-color: pink) and( background:double-rainbow ())) { /* C */ } } } @media not(( width >=400 px ) and( pointer: fine)) { @supports ( caret-color: pink) and( background:double-rainbow ()) { /* B */ } @supports not(( caret-color: pink) and( background:double-rainbow ())) { /* C */ } }
이는 동시에 읽기 어렵고, 조건과 내용의 상당한 중복을 요구하며, 올바르게 작성하기가 매우 어렵습니다. 조건이 더 복잡해지면(실제 컨텐츠에서는 흔함) 예시는 훨씬 더 나빠질 것입니다.
폴백은 테스트 조건이 없으므로, 앞선 조건 중 하나가 충족되지 않으면 항상 선택됩니다.
@when font-tech ( color-COLRv1) andfont-tech ( variations) { @font-face { font-family : icons; src : url ( icons-gradient-var.woff2 ); } } @else font-tech ( color-SVG) { @font-face { font-family : icons; src : url ( icons-gradient.woff2 ); } } @else font-tech ( color-COLRv0) { @font-face { font-family : icons; src : url ( icons-flat.woff2 ); } } @else { @font-face { font-family : icons; src : url ( icons-fallback.woff2 ); } }
이 예에서 가변 컬러 폰트는 COLRv1이 지원되고 폰트 가변도 지원되는 경우에만 다운로드됩니다.
또한 사용 가능한 옵션 중 하나만 다운로드됩니다. 다음 예에서 보이듯이 @when 및 @else가 없으면 그렇지 않습니다.
일부 문자에 대해서는 여전히 폴백이 사용될 수 있습니다. 예를 들어, 컬러 폰트가 라틴 문자만 지원하고 폴백은 라틴과 그리크를 지원하는 경우가 그렇습니다.
@font-face { font-family : icons; src : url ( icons-fallback.woff2 ); @supports font-tech ( color-COLRv1) { @font-face { font-family : icons; src : url ( icons-gradient-var.woff2 ); } }
5. 컨테이너 쿼리
미디어 쿼리가 문서가 표시되는 사용자 에이전트나 기기 환경(뷰포트 치수 또는 사용자 선호 등)의 측면을 질의하는 방법을 제공하는 반면, 컨테이너 쿼리는 문서 내 요소의 측면(박스 치수나 계산된 스타일 등)을 테스트할 수 있게 합니다.
기본적으로, 모든 요소는 컨테이너 스타일 쿼리를 위한 쿼리 컨테이너이며, 컨테이너 크기 쿼리 및 컨테이너 스크롤 상태 쿼리에 대해서는 container-type 속성 (또는 container 약식)을 사용하여 추가 쿼리 유형을 지정함으로써 쿼리 컨테이너로 설정할 수 있습니다. 쿼리 컨테이너의 플랫 트리 하위에 적용되는 스타일 규칙은 @container 조건부 그룹 규칙을 사용하여 해당 컨테이너를 대상으로 한 쿼리로 조건을 걸 수 있습니다.
main, aside{ container : my-layout / inline-size; } .media-object{ display : grid; grid-template : 'img' auto'content' auto /100 % ; } @container my-layout( inline-size >45 em ) { .media-object{ grid-template : 'img content' auto / auto1 fr ; } }
메인과 사이드바 영역의 미디어 오브젝트는 각자의 컨테이너 문맥에 반응할 것입니다.
::part() 및 ::slotted() 의사 요소 선택자는 DOM 트리의 실제 요소를 나타내므로, 해당 요소들의 플랫 트리 조상들에 의해 쿼리 컨테이너가 설정될 수 있습니다. 다른 의사 요소의 경우, 발생 원소의 포함적 플랫 트리 조상들에 의해 쿼리 컨테이너가 설정될 수 있습니다.
-
::before, ::after, ::marker, ::backdrop은 자신의 발생 원소를 대상으로 쿼리합니다
-
::first-letter 및 ::first-line은 가상의 태그 시퀀스가 상속과 렌더링 목적상
::first-line을 다른 요소 너머로 밀어낼 수 있더라도 자신의 발생 원소를 대상으로 쿼리합니다 -
::slotted() 선택자는 슬롯 자체를 포함하여 섀도 트리 내부의 컨테이너를 쿼리할 수 있습니다
-
::slotted()::before 선택자는 슬롯된 섀도 호스트 자식을 쿼리할 수 있습니다
-
::part() 선택자는 섀도 트리 내부의 컨테이너를 쿼리할 수 있습니다
-
::placeholder 및 ::file-selector-button은 입력 요소를 쿼리할 수 있지만, 입력 요소가 섀도 트리로 구현된 경우 내부 컨테이너는 노출하지 않습니다
< style > # container { width : 100 px ; container-type : inline - size ; } @ container ( inline-size < 150px ) { # inner :: before { content : "BEFORE" ; } } </ style > < div id = container > < span id = inner ></ span > </ div >
< div id = host style = "width:200px" > < template shadowroot = open > < style > # container { width : 100 px ; container-type : inline - size ; } @ container ( inline-size < 150px ) { :: slotted ( span ) { color : green ; } } </ style > < div id = container > < slot /> </ div > </ template > < span id = slotted > Green</ span > </ div >
5.1. 쿼리 컨테이너 생성: container-type 속성
| 이름: | container-type |
|---|---|
| 값: | normal | [ [ size | inline-size ] || scroll-state ] |
| 초깃값: | normal |
| 적용 대상: | 모든 요소 |
| 상속: | no |
| 백분율: | n/a |
| 계산값: | 지정된 키워드 |
| 표준 순서: | 문법에 따름 |
| 애니메이션 유형: | 애니메이션 불가 |
container-type 속성은 특정 유형의 쿼리에 대해 요소를 쿼리 컨테이너로 설정합니다. 특정 형태의 containment가 필요한 크기 컨테이너 쿼리의 경우 이 속성을 통해 요소를 명시적으로 쿼리 컨테이너로 만듭니다. 다른 유형의 쿼리 컨테이너의 경우에는, 컨테이너 스타일 쿼리처럼 어떤 요소든 쿼리 컨테이너가 될 수 있습니다.
값의 의미는 다음과 같습니다:
- size
- 쿼리 컨테이너를 컨테이너의 인라인 축과 블록 축 모두에 대한 컨테이너 크기 쿼리의 대상으로 설정합니다. 스타일 컨테인먼트와 사이즈 컨테인먼트를 주 박스에 적용하고, 독립적인 포맷팅 컨텍스트를 설정합니다.
- inline-size
- 컨테이너 자신의 인라인 축에 대한 컨테이너 크기 쿼리의 대상으로 쿼리 컨테이너를 설정합니다. 스타일 컨테인먼트와 인라인-사이즈 컨테인먼트를 주 박스에 적용하고, 독립적인 포맷팅 컨텍스트를 설정합니다.
- scroll-state
- 컨테이너 스크롤 상태 쿼리를 위한 쿼리 컨테이너를 설정합니다
- normal
- 이 요소는 어떤 컨테이너 크기 쿼리나 컨테이너 스크롤 상태 쿼리에 대해서도 쿼리 컨테이너가 아니지만, 컨테이너 스타일 쿼리에 대해서는 여전히 쿼리 컨테이너로 남습니다.
aside, main{ container-type : inline-size; } h2{ font-size : 1.2 em ; } @container ( width >40 em ) { h2{ font-size : 1.5 em ; } }
쿼리 조건에 사용된 40em 값은 해당 계산값 기준의 font-size에 대해 관련 쿼리 컨테이너를 기준으로 합니다.
@container style ( --cards: small) { article{ border : thin solid silver; border-radius : 0.5 em ; padding : 1 em ; } }
#sticky{ container-type : scroll-state; position : sticky; } @container scroll-state ( stuck: top) { #sticky-child{ background-color : lime; } }
5.2. 쿼리 컨테이너 이름 지정: container-name 속성
| 이름: | container-name |
|---|---|
| 값: | none | <custom-ident>+ |
| 초깃값: | none |
| 적용 대상: | 모든 요소 |
| 상속: | no |
| 백분율: | n/a |
| 계산값: | none 키워드 또는 식별자의 순서 있는 목록 |
| 표준 순서: | 문법에 따름 |
| 애니메이션 유형: | 애니메이션 불가 |
container-name 속성은 쿼리 컨테이너 이름 목록을 지정합니다. 이 이름들은 @container 규칙에서 어떤 쿼리 컨테이너를 대상으로 할지 필터링하는 데 사용할 수 있습니다. 컨테이너 이름은 트리 범위 이름이 아닙니다.
- none
- 쿼리 컨테이너에는 쿼리 컨테이너 이름이 없습니다.
- <custom-ident>
- 쿼리 컨테이너 이름을 식별자로 지정합니다. none, and, not, or 키워드는 이 <custom-ident>에서 제외됩니다.
main{ container-type : size; container-name : my-page-layout; } .my-component{ container-type : inline-size; container-name : my-component-library; } @container my-page-layout( block-size >12 em ) { .card{ margin-block : 2 em ; } } @container my-component-library( inline-size >30 em ) { .card{ margin-inline : 2 em ; } }
이름만을 기준으로 컨테이너를 질의하는 것도 가능합니다.
@container my-page-layout{ .card{ padding : 1 em ; } }
5.3. 이름 있는 컨테이너 생성: container 단축 속성
| 이름: | container |
|---|---|
| 값: | <'container-name'> [ / <'container-type'> ]? |
| 초깃값: | 각 속성별 참조 |
| 적용 대상: | 각 속성별 참조 |
| 상속: | 각 속성별 참조 |
| 백분율: | 각 속성별 참조 |
| 계산값: | 각 속성별 참조 |
| 애니메이션 유형: | 각 속성별 참조 |
| 표준 순서: | 문법에 따름 |
테스트
- animation-container-size.html (실시간 테스트) (소스)
- animation-container-type-dynamic.html (실시간 테스트) (소스)
- animation-nested-animation.html (실시간 테스트) (소스)
- animation-nested-transition.html (실시간 테스트) (소스)
- aspect-ratio-feature-evaluation.html (실시간 테스트) (소스)
- at-container-parsing.html (실시간 테스트) (소스)
- at-container-serialization.html (실시간 테스트) (소스)
- at-container-style-parsing.html (실시간 테스트) (소스)
- at-container-style-serialization.html (실시간 테스트) (소스)
- auto-scrollbars.html (실시간 테스트) (소스)
- backdrop-invalidation.html (실시간 테스트) (소스)
- calc-evaluation.html (실시간 테스트) (소스)
- canvas-as-container-001.html (실시간 테스트) (소스)
- canvas-as-container-002.html (실시간 테스트) (소스)
- canvas-as-container-003.html (실시간 테스트) (소스)
- canvas-as-container-004.html (실시간 테스트) (소스)
- canvas-as-container-005.html (실시간 테스트) (소스)
- canvas-as-container-006.html (실시간 테스트) (소스)
- change-display-in-container.html (실시간 테스트) (소스)
- chrome-legacy-skip-recalc.html (실시간 테스트) (소스)
- column-spanner-in-container.html (실시간 테스트) (소스)
- conditional-container-status.html (실시간 테스트) (소스)
- container-computed.html (실시간 테스트) (소스)
- container-for-cue.html (실시간 테스트) (소스)
- container-for-shadow-dom.html (실시간 테스트) (소스)
- container-inheritance.html (실시간 테스트) (소스)
- container-inner-at-rules.html (실시간 테스트) (소스)
- container-inside-multicol-with-table.html (실시간 테스트) (소스)
- container-longhand-animation-type.html (실시간 테스트) (소스)
- container-name-computed.html (실시간 테스트) (소스)
- container-name-invalidation.html (실시간 테스트) (소스)
- container-name-parsing.html (실시간 테스트) (소스)
- container-name-tree-scoped.html (실시간 테스트) (소스)
- container-nested.html (실시간 테스트) (소스)
- container-parsing.html (실시간 테스트) (소스)
- container-selection-unknown-features.html (실시간 테스트) (소스)
- container-selection.html (실시간 테스트) (소스)
- container-size-invalidation-after-load.html (실시간 테스트) (소스)
- container-size-invalidation.html (실시간 테스트) (소스)
- container-size-nested-invalidation.html (실시간 테스트) (소스)
- container-size-shadow-invalidation.html (실시간 테스트) (소스)
- container-type-computed.html (실시간 테스트) (소스)
- container-type-containment.html (실시간 테스트) (소스)
- container-type-invalidation.html (실시간 테스트) (소스)
- container-type-layout-invalidation.html (실시간 테스트) (소스)
- container-type-parsing.html (실시간 테스트) (소스)
- container-units-animation.html (실시간 테스트) (소스)
- container-units-basic.html (실시간 테스트) (소스)
- container-units-computational-independence.html (실시간 테스트) (소스)
- container-units-content-box.html (실시간 테스트) (소스)
- container-units-gradient-invalidation.html (실시간 테스트) (소스)
- container-units-gradient.html (실시간 테스트) (소스)
- container-units-in-at-container-dynamic.html (실시간 테스트) (소스)
- container-units-in-at-container-fallback.html (실시간 테스트) (소스)
- container-units-in-at-container.html (실시간 테스트) (소스)
- container-units-ineligible-container.html (실시간 테스트) (소스)
- container-units-invalidation.html (실시간 테스트) (소스)
- container-units-media-queries.html (실시간 테스트) (소스)
- container-units-rule-cache.html (실시간 테스트) (소스)
- container-units-selection.html (실시간 테스트) (소스)
- container-units-shadow.html (실시간 테스트) (소스)
- container-units-sharing-via-rule-node.html (실시간 테스트) (소스)
- container-units-small-viewport-fallback.html (실시간 테스트) (소스)
- container-units-svglength.html (실시간 테스트) (소스)
- container-units-typed-om.html (실시간 테스트) (소스)
- counters-flex-circular.html (실시간 테스트) (소스)
- counters-in-container-dynamic.html (실시간 테스트) (소스)
- counters-in-container.html (실시간 테스트) (소스)
- br-crash.html (실시간 테스트) (소스)
- canvas-as-container-crash.html (실시간 테스트) (소스)
- chrome-bug-1289718-000-crash.html (실시간 테스트) (소스)
- chrome-bug-1289718-001-crash.html (실시간 테스트) (소스)
- chrome-bug-1346969-crash.html (실시간 테스트) (소스)
- chrome-bug-1362391-crash.html (실시간 테스트) (소스)
- chrome-bug-1429955-crash.html (실시간 테스트) (소스)
- chrome-bug-1505250-crash.html (실시간 테스트) (소스)
- chrome-bug-346264227-crash.html (실시간 테스트) (소스)
- chrome-bug-372358471-crash.html (실시간 테스트) (소스)
- chrome-custom-highlight-crash.html (실시간 테스트) (소스)
- chrome-layout-root-crash.html (실시간 테스트) (소스)
- chrome-quotes-crash.html (실시간 테스트) (소스)
- chrome-remove-insert-evaluator-crash.html (실시간 테스트) (소스)
- columns-in-table-001-crash.html (실시간 테스트) (소스)
- columns-in-table-002-crash.html (실시간 테스트) (소스)
- container-in-canvas-crash.html (실시간 테스트) (소스)
- container-type-change-chrome-legacy-crash.html (실시간 테스트) (소스)
- dialog-backdrop-crash.html (실시간 테스트) (소스)
- dirty-rowgroup-crash.html (실시간 테스트) (소스)
- flex-in-columns-000-crash.html (실시간 테스트) (소스)
- flex-in-columns-001-crash.html (실시간 테스트) (소스)
- flex-in-columns-002-crash.html (실시간 테스트) (소스)
- flex-in-columns-003-crash.html (실시간 테스트) (소스)
- focus-inside-content-visibility-crash.html (실시간 테스트) (소스)
- force-sibling-style-crash.html (실시간 테스트) (소스)
- grid-in-columns-000-crash.html (실시간 테스트) (소스)
- grid-in-columns-001-crash.html (실시간 테스트) (소스)
- grid-in-columns-002-crash.html (실시간 테스트) (소스)
- grid-in-columns-003-crash.html (실시간 테스트) (소스)
- iframe-init-crash.html (실시간 테스트) (소스)
- inline-multicol-inside-container-crash.html (실시간 테스트) (소스)
- inline-with-columns-000-crash.html (실시간 테스트) (소스)
- inline-with-columns-001-crash.html (실시간 테스트) (소스)
- input-column-group-container-crash.html (실시간 테스트) (소스)
- input-placeholder-inline-size-crash.html (실시간 테스트) (소스)
- marker-gcs-after-disconnect-crash.html (실시간 테스트) (소스)
- math-block-container-child-crash.html (실시간 테스트) (소스)
- mathml-container-type-crash.html (실시간 테스트) (소스)
- orthogonal-replaced-crash.html (실시간 테스트) (소스)
- pseudo-container-crash.html (실시간 테스트) (소스)
- remove-dom-child-change-style.html (실시간 테스트) (소스)
- reversed-ol-crash.html (실시간 테스트) (소스)
- size-change-during-transition-crash.html (실시간 테스트) (소스)
- svg-layout-root-crash.html (실시간 테스트) (소스)
- svg-resource-in-container-crash.html (실시간 테스트) (소스)
- svg-text-crash.html (실시간 테스트) (소스)
- table-in-columns-000-crash.html (실시간 테스트) (소스)
- table-in-columns-001-crash.html (실시간 테스트) (소스)
- table-in-columns-002-crash.html (실시간 테스트) (소스)
- table-in-columns-003-crash.html (실시간 테스트) (소스)
- table-in-columns-004-crash.html (실시간 테스트) (소스)
- table-in-columns-005-crash.html (실시간 테스트) (소스)
- top-layer-crash.html (실시간 테스트) (소스)
- top-layer-nested-crash.html (실시간 테스트) (소스)
- custom-layout-container-001.https.html (실시간 테스트) (소스)
- custom-property-style-queries.html (실시간 테스트) (소스)
- custom-property-style-query-change.html (실시간 테스트) (소스)
- deep-nested-inline-size-containers.html (실시간 테스트) (소스)
- dialog-backdrop-create.html (실시간 테스트) (소스)
- dialog-backdrop-remove.html (실시간 테스트) (소스)
- display-contents-dynamic-style-queries.html (실시간 테스트) (소스)
- display-contents.html (실시간 테스트) (소스)
- display-in-container.html (실시간 테스트) (소스)
- display-none.html (실시간 테스트) (소스)
- fieldset-legend-change.html (실시간 테스트) (소스)
- flex-basis-with-container-type.html (실시간 테스트) (소스)
- font-relative-calc-dynamic.html (실시간 테스트) (소스)
- font-relative-units-dynamic.html (실시간 테스트) (소스)
- font-relative-units.html (실시간 테스트) (소스)
- fragmented-container-001.html (실시간 테스트) (소스)
- get-animations.html (실시간 테스트) (소스)
- grid-container.html (실시간 테스트) (소스)
- grid-item-container.html (실시간 테스트) (소스)
- idlharness.html (실시간 테스트) (소스)
- iframe-in-container-invalidation.html (실시간 테스트) (소스)
- iframe-invalidation.html (실시간 테스트) (소스)
- ineligible-containment.html (실시간 테스트) (소스)
- inheritance-from-container.html (실시간 테스트) (소스)
- inline-size-and-min-width.html (실시간 테스트) (소스)
- inline-size-bfc-floats.html (실시간 테스트) (소스)
- inline-size-containment-vertical-rl.html (실시간 테스트) (소스)
- inline-size-containment.html (실시간 테스트) (소스)
- inner-first-line-non-matching.html (실시간 테스트) (소스)
- layout-dependent-focus.html (실시간 테스트) (소스)
- multicol-container-001.html (실시간 테스트) (소스)
- multicol-inside-container.html (실시간 테스트) (소스)
- nested-query-containers.html (실시간 테스트) (소스)
- nested-size-style-container-invalidation.html (실시간 테스트) (소스)
- never-match-container.html (실시간 테스트) (소스)
- no-layout-containment-abspos-dynamic.html (실시간 테스트) (소스)
- no-layout-containment-abspos.html (실시간 테스트) (소스)
- no-layout-containment-baseline.html (실시간 테스트) (소스)
- no-layout-containment-fixedpos-dynamic.html (실시간 테스트) (소스)
- no-layout-containment-fixedpos.html (실시간 테스트) (소스)
- no-layout-containment-scroll.html (실시간 테스트) (소스)
- no-layout-containment-subgrid-crash.html (실시간 테스트) (소스)
- orthogonal-wm-container-query.html (실시간 테스트) (소스)
- percentage-padding-orthogonal.html (실시간 테스트) (소스)
- pseudo-elements-001.html (실시간 테스트) (소스)
- pseudo-elements-002.html (실시간 테스트) (소스)
- pseudo-elements-002b.html (실시간 테스트) (소스)
- pseudo-elements-003.html (실시간 테스트) (소스)
- pseudo-elements-004.html (실시간 테스트) (소스)
- pseudo-elements-005.html (실시간 테스트) (소스)
- pseudo-elements-006.html (실시간 테스트) (소스)
- pseudo-elements-007.html (실시간 테스트) (소스)
- pseudo-elements-008.html (실시간 테스트) (소스)
- pseudo-elements-009.html (실시간 테스트) (소스)
- pseudo-elements-010.html (실시간 테스트) (소스)
- pseudo-elements-011.html (실시간 테스트) (소스)
- pseudo-elements-012.html (실시간 테스트) (소스)
- pseudo-elements-013.html (실시간 테스트) (소스)
- query-content-box.html (실시간 테스트) (소스)
- query-evaluation-style.html (실시간 테스트) (소스)
- query-evaluation.html (실시간 테스트) (소스)
- reattach-container-with-dirty-child.html (실시간 테스트) (소스)
- registered-color-style-queries.html (실시간 테스트) (소스)
- resize-while-content-visibility-hidden.html (실시간 테스트) (소스)
- at-container-scrollable-parsing.html (실시간 테스트) (소스)
- at-container-scrollable-serialization.html (실시간 테스트) (소스)
- at-container-snapped-parsing.html (실시간 테스트) (소스)
- at-container-snapped-serialization.html (실시간 테스트) (소스)
- at-container-stuck-parsing.html (실시간 테스트) (소스)
- at-container-stuck-serialization.html (실시간 테스트) (소스)
- container-type-scroll-state-computed.html (실시간 테스트) (소스)
- container-type-scroll-state-containment.html (실시간 테스트) (소스)
- container-type-scroll-state-parsing.html (실시간 테스트) (소스)
- scroll-state-initially-scrollable.html (실시간 테스트) (소스)
- scroll-state-initially-snapped.html (실시간 테스트) (소스)
- scroll-state-initially-stuck.html (실시간 테스트) (소스)
- scroll-state-scrollable-change.html (실시간 테스트) (소스)
- scroll-state-scrollable-container-type-change.html (실시간 테스트) (소스)
- scroll-state-scrollable-layout-change.html (실시간 테스트) (소스)
- scroll-state-scrollable-wm.html (실시간 테스트) (소스)
- scroll-state-snapped-change.html (실시간 테스트) (소스)
- scroll-state-snapped-container-type-change.html (실시간 테스트) (소스)
- scroll-state-snapped-layout-change.html (실시간 테스트) (소스)
- scroll-state-snapped-none.html (실시간 테스트) (소스)
- scroll-state-snapped-snap-changing.html (실시간 테스트) (소스)
- scroll-state-snapped-wm.html (실시간 테스트) (소스)
- scroll-state-stuck-container-type-change.html (실시간 테스트) (소스)
- scroll-state-stuck-layout-change.html (실시간 테스트) (소스)
- scroll-state-stuck-writing-direction.html (실시간 테스트) (소스)
- scroll-state-target-query-change.html (실시간 테스트) (소스)
- scrollbar-container-units-block.html (실시간 테스트) (소스)
- scrollbar-container-units-inline.html (실시간 테스트) (소스)
- sibling-layout-dependency.html (실시간 테스트) (소스)
- size-container-no-principal-box.html (실시간 테스트) (소스)
- size-container-with-quotes.html (실시간 테스트) (소스)
- size-container-writing-mode-change.html (실시간 테스트) (소스)
- size-feature-evaluation.html (실시간 테스트) (소스)
- style-change-in-container.html (실시간 테스트) (소스)
- style-container-for-shadow-dom.html (실시간 테스트) (소스)
- style-container-invalidation-inheritance.html (실시간 테스트) (소스)
- style-not-sharing-float.html (실시간 테스트) (소스)
- style-query-document-element.html (실시간 테스트) (소스)
- style-query-no-cycle.html (실시간 테스트) (소스)
- style-query-with-unknown-width.html (실시간 테스트) (소스)
- svg-foreignobject-child-container.html (실시간 테스트) (소스)
- svg-foreignobject-no-size-container.html (실시간 테스트) (소스)
- svg-g-no-size-container.html (실시간 테스트) (소스)
- svg-root-size-container.html (실시간 테스트) (소스)
- table-inside-container-changing-display.html (실시간 테스트) (소스)
- top-layer-dialog-backdrop.html (실시간 테스트) (소스)
- top-layer-dialog-container.html (실시간 테스트) (소스)
- top-layer-dialog.html (실시간 테스트) (소스)
- top-layer-nested-dialog.html (실시간 테스트) (소스)
- transition-scrollbars.html (실시간 테스트) (소스)
- transition-style-change-event-002.html (실시간 테스트) (소스)
- transition-style-change-event.html (실시간 테스트) (소스)
- unsupported-axis.html (실시간 테스트) (소스)
- viewport-units-dynamic.html (실시간 테스트) (소스)
- viewport-units.html (실시간 테스트) (소스)
- whitespace-update-after-removal.html (실시간 테스트) (소스)
container 단축 속성은 container-type과 container-name을 동시에 설정합니다. <'container-type'>이 생략되면, 초깃값으로 재설정됩니다.
main{ container : my-layout / size; } .grid-item{ container : my-component / inline-size; }
5.4. 컨테이너 쿼리: @container 규칙
@container 규칙은 조건부 그룹 규칙의 하나로, 그 조건에 컨테이너 쿼리를 포함합니다. 컨테이너 쿼리는 컨테이너 크기 쿼리와/또는 컨테이너 스타일 쿼리의 불리언 조합입니다. <block-contents> 블록 안의 스타일 선언은 @container 규칙의 조건에 따라 해당 컨테이너 쿼리가 해당 요소의 쿼리 컨테이너에 대해 true일 때만 적용됩니다.
@container 규칙의 문법은 다음과 같습니다:
@container <container-condition>#{ <block-contents>}
설명:
<container-condition> =[ <container-name>? <container-query>?] ! <container-name> = <custom-ident> <container-query> = not <query-in-parens> | <query-in-parens>[ [ and <query-in-parens>] * |[ or <query-in-parens>] *] <query-in-parens> =( <container-query>) |( <size-feature>) |style ( <style-query>) |scroll-state ( <scroll-state-query>) | <general-enclosed> <style-query> = not <style-in-parens> | <style-in-parens>[ [ and <style-in-parens>] * |[ or <style-in-parens>] *] | <style-feature> <style-in-parens> =( <style-query>) |( <style-feature>) | <general-enclosed> <style-feature> = <style-feature-plain> | <style-feature-boolean> | <style-range> <style-feature-plain> = <style-feature-name> : <style-feature-value> <style-feature-boolean> = <style-feature-name> <style-range> = <style-range-value> <mf-comparison> <style-range-value> | <style-range-value> <mf-lt> <style-range-value> <mf-lt> <style-range-value> | <style-range-value> <mf-gt> <style-range-value> <mf-gt> <style-range-value> <style-range-value> = <custom-property-name> | <style-feature-value> <scroll-state-query> = not <scroll-state-in-parens> | <scroll-state-in-parens>[ [ and <scroll-state-in-parens>] * |[ or <scroll-state-in-parens>] *] | <scroll-state-feature> <scroll-state-in-parens> =( <scroll-state-query>) |( <scroll-state-feature>) | <general-enclosed>
테스트
- container-ident-function.html (실시간 테스트) (소스)
- container-ident-function.html (실시간 테스트) (소스)
- multiple-size-containers-comma-separated-queries.html (실시간 테스트) (소스)
- multiple-style-containers-comma-separated-queries.html (실시간 테스트) (소스)
- query-container-name.html (실시간 테스트) (소스)
- at-container-scrolled-parsing.html (실시간 테스트) (소스)
- multiple-scroll-state-containers-comma-separated-queries.html (실시간 테스트) (소스)
- scroll-state-query-with-var.html (실시간 테스트) (소스)
- size-query-with-var.html (실시간 테스트) (소스)
none, and, not, or 키워드는 위 <custom-ident>에서 제외됩니다.
각 요소마다, 쿼리할 쿼리 컨테이너는 해당 요소의 조상 쿼리 컨테이너 중 <container-query>에 사용된 모든 컨테이너 기능에 대해 유효하게 설정된 쿼리 컨테이너에서 선택됩니다. <container-query>에 알 수 없거나 지원되지 않는 컨테이너 기능이 포함되어 있으면, 해당 <container-condition>에 대해 쿼리 컨테이너가 선택되지 않습니다. <container-name>은 고려되는 쿼리 컨테이너 집합을 일치하는 쿼리 컨테이너 이름을 가진 컨테이너로만 필터링합니다.
요소에 대해 적합한 쿼리 컨테이너가 선택되면, <container-query>의 각 컨테이너 기능이 해당 쿼리 컨테이너에 대해 평가됩니다. 조상에 적합한 쿼리 컨테이너가 없으면, 해당 요소에 대해 컨테이너 쿼리는 unknown이 됩니다. 미디어 쿼리와 마찬가지로, <general-enclosed>는 unknown으로 평가됩니다. <container-query>가 생략된 경우, <container-name>만 일치하면 쿼리 컨테이너는 적합한 것으로 간주됩니다.
컨테이너 쿼리에 여러 <container-condition>이 포함되어 있을 때, 각 조건은 자체 쿼리 컨테이너를 선택하여 독립적으로 평가합니다. 컨테이너 쿼리는 구성 요소 <container-condition> 중 하나라도 true이면 true가 되고, 모두 false일 때만 false가 됩니다.
@container card( inline-size >30 em ) andstyle ( --responsive: true) { /* styles */ }
위 스타일은 조상 컨테이너 중 "card"라는 이름을 가진 컨테이너가 inline-size와 style 조건을 모두 충족할 때만 적용됩니다.
여러 조건을 리스트로 결합해 각 조건이 서로 다른 컨테이너에 대해 평가되도록 할 수도 있습니다:
@container card( inline-size >30 em ), style ( --large: true) { /* styles */ }
위 스타일은 조상 컨테이너 중 "card"라는 이름을 가진 컨테이너가 inline-size 조건을 만족하거나 혹은 가장 가까운 스타일 컨테이너가 style 조건을 만족할 때 적용됩니다.
여러 중첩된 컨테이너 쿼리 내부의 요소에 정의된 스타일 규칙은 모든 바깥 컨테이너 쿼리가 true일 때 적용됩니다.
참고: 중첩된 컨테이너 쿼리는 서로 다른 컨테이너를 기준으로 평가될 수 있으므로, 개별 <container-condition>을 하나의 쿼리로 합치는 것이 항상 가능하지는 않습니다.
@container card( inline-size >30 em ), style ( --responsive: true) { /* styles */ }
위 스타일은 요소의 조상 중 하나라도 "card"라는 이름의 컨테이너가 inline-size 조건을 만족하거나, 혹은 해당 style 조건을 만족하는 컨테이너가 있는 경우 적용됩니다.
여러 컨테이너를 쿼리하면서 모든 조건을 충족해야 한다면, 여러 쿼리를 중첩해야 합니다:
@container card( inline-size >30 em ) { @container style ( --responsive: true) { /* styles */ } }
위 스타일은 "card"라는 이름의 조상 컨테이너가 inline-size 조건을 만족하고, 또 조상 컨테이너 중 하나가 style 조건을 만족해야만 적용됩니다.
전역 이름 정의 at-rule (예: @keyframes, @font-face, @layer 등)이 컨테이너 쿼리 내부에 정의되더라도, 컨테이너 쿼리 조건에 의해 제한되지 않습니다.
5.5. 애니메이션 컨테이너
컨테이너 쿼리의 평가 결과가 변하면, 그 변화는 스타일 변경 이벤트의 일부가 되어야 하며, 이 변화가 애니메이션 효과로 인해 발생했더라도 마찬가지입니다.
main{ display : flex; width : 300 px ; } #container{ container-type : inline-size; flex : 1 ; } /* Resolved width is initially 200px, but changes as the transition on #sibling progresses. */ #inner{ transition : 1 s background-color; background-color : tomato; } /* When this container query starts (or stops) applying, a transition must start on background-color on #inner. */ @container ( width <=150 px ) { #inner{ background-color : skyblue; } } #sibling{ width : 100 px ; transition : width1 s ; } #sibling:hover{ width : 200 px ; }
< main > < div id = container > < div id = inner > Inner</ div > </ div > < div id = sibling > Sibling</ div > </ main >
계산값이 컨테이너 쿼리 길이 단위로 인해 변경될 때도 반드시 스타일 변경 이벤트의 일부가 되어야 합니다.
6. 컨테이너 기능
컨테이너 기능은 쿼리 컨테이너의 특정 속성을 질의합니다.
컨테이너 기능은 미디어 기능과 동일한 규칙으로 불리언 문맥에서 평가됩니다.
6.1. 사이즈 컨테이너 기능
컨테이너 크기 쿼리는 쿼리 컨테이너의 주 박스(principal box)의 크기를 질의할 수 있도록 해줍니다. 이는 개별 사이즈 기능 (<size-feature>) 들의 불리언 조합이며, 각각은 쿼리 컨테이너의 하나의 특정 치수 속성을 질의합니다. <size-feature>의 문법은 미디어 기능과 동일합니다: 기능명, 비교 연산자, 그리고 값의 형태입니다. [mediaqueries-5] 불리언 문법과 사이즈 기능을 크기 쿼리로 조합하는 논리는 CSS 기능 쿼리와 동일합니다. (@supports 참고. [css-conditional-3])
쿼리 컨테이너에 주 박스가 없거나, 주 박스가 레이아웃 컨테인먼트 박스가 아니거나, 쿼리 컨테이너가 해당 축에서 컨테이너 크기 쿼리를 지원하지 않으면, 사이즈 기능의 평가 결과는 unknown입니다.
상대 길이 단위 (컨테이너 쿼리 길이 단위 포함) 및 커스텀 속성은 컨테이너 쿼리 조건 내에서 계산값을 쿼리 컨테이너 기준으로 평가합니다.
트리 카운팅 함수(CSS Values 5 § 9 Tree Counting Functions: sibling-count() 및 sibling-index() 표기)는 컨테이너 요소를 기준으로 평가됩니다.
참고: 이것은 미디어 쿼리에서의 상대 단위 처리와 다릅니다.
참고: 커스텀 속성 치환 결과가 사이즈 기능에 대해 잘못된 값이라면, 다른 잘못된 기능 값과 동일하게 처리되며, 해당 사이즈 기능의 결과는 unknown이 됩니다.
aside, main{ container-type : inline-size; } aside{ font-size : 16 px ; } main{ font-size : 24 px ; } @container ( width >40 em ) { h2{ font-size : 1.5 em ; } }
쿼리 조건에 사용된 40em 값은 해당 계산값 기준의 font-size에 대해 관련 쿼리 컨테이너를 기준으로 합니다:
-
aside 안의 h2의 경우, 쿼리 조건은 640px을 초과할 때 true가 됩니다.
-
main 안의 h2의 경우, 쿼리 조건은 960px을 초과할 때 true가 됩니다.
aside, main{ container-type : inline-size; } aside{ --query : 300 px ; } main{ --query : 500 px ; } @container ( width >var ( --query)) { h2{ font-size : 1.5 em ; } }
쿼리 조건에 사용된 var(--query) 값은 관련 쿼리 컨테이너의 --query 커스텀 속성 계산값으로 치환됩니다:
-
aside 안의 h2의 경우, 쿼리 조건은 300px을 초과할 때 true가 됩니다.
-
main 안의 h2의 경우, 쿼리 조건은 500px을 초과할 때 true가 됩니다.
6.1.1. 너비: width 기능
| 이름: | width |
|---|---|
| 대상: | @container |
| 값: | <length> |
| 유형: | range |
width 컨테이너 기능은 너비를 쿼리 컨테이너의 content box 기준으로 질의합니다.
6.1.2. 높이: height 기능
| 이름: | height |
|---|---|
| 대상: | @container |
| 값: | <length> |
| 유형: | range |
height 컨테이너 기능은 높이를 쿼리 컨테이너의 content box 기준으로 질의합니다.
6.1.3. 인라인-사이즈: inline-size 기능
| 이름: | inline-size |
|---|---|
| 대상: | @container |
| 값: | <length> |
| 유형: | range |
inline-size 컨테이너 기능은 사이즈를 쿼리 컨테이너의 content box 중 쿼리 컨테이너의 인라인 축 기준으로 질의합니다.
6.1.4. 블록-사이즈: block-size 기능
| 이름: | block-size |
|---|---|
| 대상: | @container |
| 값: | <length> |
| 유형: | range |
block-size 컨테이너 기능은 사이즈를 쿼리 컨테이너의 content box 중 쿼리 컨테이너의 블록 축 기준으로 질의합니다.
6.1.5. 종횡비: aspect-ratio 기능
| 이름: | aspect-ratio |
|---|---|
| 대상: | @container |
| 값: | <ratio> |
| 유형: | range |
aspect-ratio 컨테이너 기능은 width 컨테이너 기능 값을 height 컨테이너 기능 값으로 나눈 비율로 정의됩니다.
6.1.6. 방향: orientation 기능
| 이름: | orientation |
|---|---|
| 대상: | @container |
| 값: | portrait | landscape |
| 유형: | discrete |
- portrait
- orientation 컨테이너 기능은 portrait로, height 컨테이너 기능의 값이 width 컨테이너 기능의 값보다 크거나 같은 경우입니다.
- landscape
- 그 외의 경우 orientation은 landscape입니다.
6.2. 스타일 컨테이너 기능
컨테이너 스타일 쿼리는 쿼리 컨테이너의 계산값을 질의할 수 있게 해줍니다. 이는 개별 스타일 기능 (<style-feature>)의 불리언 조합이며, 각각은 쿼리 컨테이너의 하나의 특정 속성을 질의합니다. <style-feature>의 문법은 유효한 선언[CSS-SYNTAX-3]이나, <style-feature-name> 또는 유효한 스타일 범위(<style-range>)와 동일합니다. <style-feature-name>은 지원되는 CSS 속성이거나 유효한 <custom-property-name>일 수 있습니다. <style-feature-value>는 <declaration-value>에 맞는 어떤 값도 허용하지만, <mf-lt>, <mf-gt> 그리고 <mf-eq> 토큰은 포함할 수 없습니다.
테스트
<style-feature-plain>은 쿼리 컨테이너에서 주어진 속성의 계산값이 (해당 쿼리 컨테이너 기준으로 계산된) 지정된 값과 일치하면 true, 그렇지 않으면 false로 평가됩니다.
값이 없는 스타일 기능 (<style-feature-boolean>)은 해당 계산값이 초깃값과 다를 경우 true가 됩니다.
-
<style-range-value>가 <custom-property-name>이면, <custom-property-name>을 var()로 감싼 것처럼 치환해야 합니다.
-
임의 치환 함수를 <style-range-value> 내에서 치환합니다.
-
<style-range-value>를 <number>, <percentage>, <length>, <angle>, <time>, <frequency> 또는 <resolution>로 파싱합니다. 파싱이 안 되면 false로 평가합니다.
-
범위의 각 <style-range-value>가 동일한 타입이면, 각각을 계산하고 비교 평가합니다. 단위 없는 0은 <length>와 비교 시 0-<length>로 처리합니다.
-
그 외의 경우 false로 평가합니다.
불리언 문법과 논리로 스타일 기능을 스타일 쿼리로 조합하는 것은 CSS 기능 쿼리와 동일합니다. (@supports 참고. [css-conditional-3])
스타일 기능이 약식 속성(shorthand property)을 질의하는 경우, 모든 롱핸드 속성(longhand property)의 계산값이 일치하면 true, 그렇지 않으면 false입니다.
캐스케이드 의존 키워드(예: revert, revert-layer)는 스타일 기능에서 값으로 사용할 수 없으며, 컨테이너 스타일 쿼리를 false로 만듭니다.
참고: 나머지 비-캐스케이드-의존 CSS-와이드 키워드는 쿼리 컨테이너 기준으로 다른 값과 마찬가지로 계산됩니다.
6.3. 스크롤 상태 컨테이너 기능
컨테이너 스크롤 상태 쿼리는 스크롤 위치에 따라 달라지는 상태를 컨테이너에서 질의할 수 있도록 합니다. 이는 각 스크롤 상태 기능 (<scroll-state-feature>)을 불리언으로 조합한 것이며, 각각은 쿼리 컨테이너의 단일 기능을 질의합니다. <scroll-state-feature>의 문법은 미디어 기능과 동일하며, 기능 이름, 비교자, 값으로 이루어집니다.
스크롤 상태 기능은 스크롤러 자체의 상태에 일치할 수도 있고, 조상 스크롤 컨테이너의 스크롤포트의 스크롤 위치에 의해 영향을 받는 요소의 상태에 일치할 수도 있습니다. 전자의 예는 scrollable 기능이며, 후자의 예는 snapped입니다.
6.3.1. 스크롤 상태 업데이트
스크롤 상태는, 질의된 스크롤 상태가 스타일 변화를 유발하고, 그 결과 레이아웃에 의해 스크롤 상태가 다시 변할 수 있기 때문에, 레이아웃 사이클을 야기할 수 있습니다.
이러한 레이아웃 사이클을 방지하기 위해, scroll-state 쿼리 컨테이너는 스냅샷 post-layout 상태 단계 실행의 일부로 현재 상태를 업데이트하며, 이 단계는 HTML 이벤트 루프 처리 모델의 특정 지점에서만 실행됩니다.
스냅샷 post-layout 상태 단계 실행이 요청되면, 모든 scroll-state 쿼리 컨테이너의 현재 상태를 업데이트합니다. 이렇게 스냅샷된 상태는 이 단계가 다음에 실행될 때까지 이루어지는 모든 스타일 및 레이아웃 업데이트에 사용됩니다.
6.3.2. 스티키 포지셔닝: stuck 기능
| Name: | stuck |
|---|---|
| For: | @container |
| Value: | none | top | right | bottom | left | block-start | inline-start | block-end | inline-end |
| Type: | discrete |
stuck 컨테이너 기능은 sticky 포지션이 적용된 컨테이너가, 주어진 edge에 대해 sticky 뷰 사각형 안에 머물도록 시각적으로 이동되었는지를 질의합니다. 논리적 edge는 쿼리 컨테이너의 direction 및 writing-mode에 따라 물리적 edge로 매핑됩니다. 쿼리 컨테이너가 sticky 포지션이 아니면 어떤 값도 일치하지 않습니다.
서로 다른 축에 속한 두 값은 동시에 일치할 수 있으나, 동일한 축의 반대쪽 edge가 동시에 일치하는 일은 없습니다.
@container scroll-state (( stuck: top) and( stuck: left)) { ...}
절대 일치하지 않음:
@container scroll-state (( stuck: left) and( stuck: right)) { ...}
- none
- sticky 컨테이너는 어떤 방향으로도 이동되지 않았습니다.
- top
- sticky 컨테이너가 위쪽 edge 안에 있도록 이동되었습니다.
- right
- sticky 컨테이너가 오른쪽 edge 안에 있도록 이동되었습니다.
- bottom
- sticky 컨테이너가 아래쪽 edge 안에 있도록 이동되었습니다.
- left
- sticky 컨테이너가 왼쪽 edge 안에 있도록 이동되었습니다.
- block-start
- sticky 컨테이너가 block-start edge 안에 있도록 이동되었습니다.
- inline-start
- sticky 컨테이너가 inline-start edge 안에 있도록 이동되었습니다.
- block-end
- sticky 컨테이너가 block-end edge 안에 있도록 이동되었습니다.
- inline-end
- sticky 컨테이너가 inline-end edge 안에 있도록 이동되었습니다.
6.3.3. 스크롤 스냅: snapped 기능
| Name: | snapped |
|---|---|
| For: | @container |
| Value: | none | x | y | block | inline | both |
| Type: | discrete |
Tests
snapped 컨테이너 기능은
snap target이
주어진 축에서 자신의 스크롤 스냅 컨테이너에 스냅되어 있거나 스냅될 것인지를 질의합니다.
즉, scrollsnapchanging
이벤트가 발생하는 모든 snap target과 일치합니다.
- none
- 쿼리 컨테이너는 snap target이 아닙니다.
- x
- snapped 컨테이너 기능은, 쿼리 컨테이너가 자신의 snap target이며 수평 방향일 때 x와 일치합니다. 그 대상 스크롤 컨테이너는 scroll container입니다.
- y
- snapped 컨테이너 기능은, y와 일치하며, 쿼리 컨테이너가 자신의 snap target이고 수직 방향일 때 해당합니다. 대상 스크롤 컨테이너는 scroll container입니다.
- block
- snapped 컨테이너 기능은 block과 일치하며, 쿼리 컨테이너가 자신의 snap target이고 scroll container의 block 방향에서 해당합니다. 또한 이는 scroll snap container의 block 방향을 가리킵니다.
- inline
- snapped 컨테이너 기능은 inline과 일치하며, 쿼리 컨테이너가 자신의 snap target이고 scroll container의 inline 방향에서 해당합니다. 이는 scroll snap container의 inline 방향을 의미합니다.
- both
- snapped 컨테이너 기능은 both와 일치하며, 쿼리 컨테이너가 자신의 snap target이고 scroll container의 양 방향에서 해당합니다. 이는 scroll snap container의 두 방향 모두를 의미합니다.
6.3.4. 스크롤 가능: scrollable 기능
| Name: | scrollable |
|---|---|
| For: | @container |
| Value: | none | top | right | bottom | left | block-start | inline-start | block-end | inline-end | x | y | block | inline |
| Type: | discrete |
Tests
- scroll-state-scrollable-axis.html (live test) (source)
- scroll-state-scrollable-body-001.html (live test) (source)
- scroll-state-scrollable-body-002.html (live test) (source)
- scroll-state-scrollable-layout-change-002.html (live test) (source)
- scroll-state-scrollable-pseudo.html (live test) (source)
- scroll-state-scrollable-root.html (live test) (source)
scrollable 컨테이너 기능은 스크롤 컨테이너가, 사용자에 의해 시작된 스크롤 동작으로 접근 가능한, 주어진 방향의 잘린 스크롤 가능 오버플로우 사각형 콘텐츠를 가지는지를 질의합니다. 즉, scrollable은 컨테이너나, 음수 스크롤 가능 오버플로우 영역에는 일치하지 않습니다.
논리 값들은 쿼리 컨테이너의 direction 및 writing-mode에 따라 물리적 값으로 매핑됩니다. 컨테이너가 스크롤 컨테이너가 아니면 어떤 값도 일치하지 않습니다.
- none
- 스크롤 컨테이너는 어떤 방향으로도 스크롤 가능 오버플로우가 없습니다.
- top
- 스크롤 컨테이너는 위쪽 edge를 넘어서는 스크롤 가능 오버플로우가 있습니다.
- right
- 스크롤 컨테이너는 오른쪽 edge를 넘어서는 스크롤 가능 오버플로우가 있습니다.
- bottom
- 스크롤 컨테이너는 아래쪽 edge를 넘어서는 스크롤 가능 오버플로우가 있습니다.
- left
- 스크롤 컨테이너는 왼쪽 edge를 넘어서는 스크롤 가능 오버플로우가 있습니다.
- block-start
- 스크롤 컨테이너는 block-start edge를 넘어서는 스크롤 가능 오버플로우가 있습니다.
- inline-start
- 스크롤 컨테이너는 inline-start edge를 넘어서는 스크롤 가능 오버플로우가 있습니다.
- block-end
- 스크롤 컨테이너는 block-end edge를 넘어서는 스크롤 가능 오버플로우가 있습니다.
- inline-end
- 스크롤 컨테이너는 inline-end edge를 넘어서는 스크롤 가능 오버플로우가 있습니다.
- x
- 스크롤 컨테이너는 수평 방향의 스크롤 가능 오버플로우를 가집니다.
- y
- 스크롤 컨테이너는 수직 방향의 스크롤 가능 오버플로우를 가집니다.
- block
- 스크롤 컨테이너는 자신의 block 방향으로 스크롤 가능 오버플로우를 가집니다.
- inline
- 스크롤 컨테이너는 자신의 inline 방향으로 스크롤 가능 오버플로우를 가집니다.
6.3.5. 스크롤됨: scrolled 기능
| Name: | scrolled |
|---|---|
| For: | @container |
| Value: | none | top | right | bottom | left | block-start | inline-start | block-end | inline-end | x | y | block | inline |
| Type: | discrete |
Tests
- scroll-state-scrolled-arrow-key-scroll.html (live test) (source)
- scroll-state-scrolled-home-end-scroll.html (live test) (source)
- scroll-state-scrolled-hv.html (live test) (source)
- scroll-state-scrolled-keyboard-scroll-on-body.html (live test) (source)
- scroll-state-scrolled-keyboard-scroll-on-root.html (live test) (source)
- scroll-state-scrolled-mouse-drag-scroll.html (live test) (source)
- scroll-state-scrolled-multiple-scrollers.html (live test) (source)
- scroll-state-scrolled-programmatic-absolute-scrolls.html (live test) (source)
- scroll-state-scrolled-programmatic-relative-scrolls.html (live test) (source)
- scroll-state-scrolled-pu-pd-scroll.html (live test) (source)
- scroll-state-scrolled-scrollbar-button-clicks.html (live test) (source)
- scroll-state-scrolled-scrollbar-track-clicks.html (live test) (source)
- scroll-state-scrolled-spacebar-scroll.html (live test) (source)
- scroll-state-scrolled-user-touch-scroll.html (live test) (source)
- scroll-state-scrolled-wheel-scroll.html (live test) (source)
- scroll-state-scrolled-wm.html (live test) (source)
- at-container-scrolled-parsing.html (live test) (source)
- at-container-scrolled-serialization.html (live test) (source)
쿼리 컨테이너가 스크롤 컨테이너인 경우, scrolled 컨테이너 기능은 가장 최근의 상대 스크롤(relative scroll)의 방향을 질의합니다. 논리 값은 쿼리 컨테이너의 direction 및 writing-mode에 따라 물리적으로 매핑됩니다. 컨테이너가 스크롤 컨테이너가 아니면 어떤 값도 일치하지 않습니다.
- none
- 쿼리 컨테이너에서는 아직 상대 스크롤이 발생하지 않았습니다.
- top
- 가장 최근의 상대 스크롤이 위쪽으로 일어났습니다.
- right
- 가장 최근의 상대 스크롤이 오른쪽으로 일어났습니다.
- bottom
- 가장 최근의 상대 스크롤이 아래쪽으로 일어났습니다.
- left
- 가장 최근의 상대 스크롤이 왼쪽으로 일어났습니다.
- block-start
- 가장 최근의 상대 스크롤이 block-start 방향으로 일어났습니다.
- inline-start
- 가장 최근의 상대 스크롤이 inline-start 방향으로 일어났습니다.
- block-end
- 가장 최근의 상대 스크롤이 block-end 방향으로 일어났습니다.
- inline-end
- 가장 최근의 상대 스크롤이 inline-end 방향으로 일어났습니다.
- x
- 가장 최근의 상대 스크롤이 수평 방향으로 일어났습니다.
- y
- 가장 최근의 상대 스크롤이 수직 방향으로 일어났습니다.
- block
- 가장 최근의 상대 스크롤이 block 방향으로 일어났습니다.
- inline
- 가장 최근의 상대 스크롤이 inline 방향으로 일어났습니다.
7. 컨테이너 상대 길이: cqw, cqh, cqi, cqb, cqmin, cqmax 단위
컨테이너 쿼리 길이 단위는 쿼리 컨테이너의 크기에 상대적인 길이를 지정합니다. 컨테이너 쿼리 길이 단위를 사용하는 스타일 시트는 하나의 쿼리 컨테이너에서 다른 컨테이너로 컴포넌트를 더 쉽게 옮길 수 있습니다.
컨테이너 쿼리 길이 단위는 다음과 같습니다:
| 단위 | 기준 |
|---|---|
| cqw | 쿼리 컨테이너의 너비의 1% |
| cqh | 쿼리 컨테이너의 높이의 1% |
| cqi | 쿼리 컨테이너의 인라인 크기의 1% |
| cqb | 쿼리 컨테이너의 블록 크기의 1% |
| cqmin | cqi 또는 cqb 중 더 작은 값 |
| cqmax | cqi 또는 cqb 중 더 큰 값 |
각 요소에 대해 컨테이너 쿼리 길이 단위는 해당 단위로 설명되는 축(또는 축들)에 대해 컨테이너 크기 쿼리로 평가됩니다. 각 축의 쿼리 컨테이너는 해당 축에서 컨테이너 크기 쿼리를 허용하는 가장 가까운 상위 컨테이너입니다. 사용 가능한 쿼리 컨테이너가 없다면, 해당 축에 대해 작은 뷰포트 크기를 사용합니다.
참고: 어떤 경우에는 동일한 요소에서 cqi 및 cqb 단위가 서로 다른 쿼리 컨테이너를 기준으로 평가될 수 있습니다. 마찬가지로 cqmin 및 cqmax 단위는 cqi와 cqb 단위 중 큰 값 또는 작은 값을 나타내며, 이 때 해당 크기가 서로 다른 쿼리 컨테이너에서 올 수 있습니다.
자식 요소는 부모에 대해 지정된 상대값을 상속하지 않고, 계산된 값을 상속합니다.
/* 대체값은 containment에 의존하지 않습니다 */ h2{ font-size : 1.2 em ; } @container ( inline-size >=0 px ) { /* 인라인 크기 컨테이너가 있을 때만 적용 */ h2{ font-size : calc ( 1.2 em +1 cqi ); } }
8. 사용자 정의 지원 쿼리 정의: @supports-condition 규칙
@supports-condition at-rule은 작성자가 나중에 재사용할 수 있도록 supports 쿼리를 정의하고 이름을 지정할 수 있게 해주는 조건부 그룹 규칙입니다. 이를 통해 복잡하거나 자주 사용하는 기능 쿼리를 이름으로 참조할 수 있어, 유지보수성과 가독성이 향상됩니다.
@supports-condition <supports-condition-name>{ <block-contents>}
테스트
여기서 <supports-condition-name>은 <extension-name>으로, supports 쿼리의 이름을 정의합니다.
블록 내부의 모든 내용은 사용자 에이전트가 사용된 기능을 지원하는지 테스트하기 위해 평가됩니다. 이 내용은 문서 렌더링에는 영향을 주지 않습니다.
한 번 정의된 named supports 조건은 이후 @supports 또는 @when 조건에서 사용할 수 있습니다.
동일한 이름으로 여러 @supports-condition 규칙이 정의된 경우, 문서 순서상 마지막 규칙이 적용되며 그 이전 것은 모두 무시됩니다.
@supports-condition --thicker-underlines{ text-decoration-thickness : 0.2 em ; text-underline-offset : 0.3 em ; } /* (text-decoration-thickness: 0.2em) 및 (text-underline-offset: 0.3em)과 동일 */ @supports ( --thicker-underlines) { a{ text-decoration : underline; text-decoration-thickness : 0.2 em ; text-underline-offset : 0.3 em ; } }
@supports-condition 규칙은 @import 및 @namespace 규칙 앞에 올 수 있습니다 (@charset 규칙(있다면) 다음).
@supports-condition --nesting{ &{ } } @import url ( "nested-styles.css" ) supports ( --nesting);
@supports-condition --stuck-container-feature{ @container scroll-state ( stuck: top) { } } @supports ( --stuck-container-feature) { div{ border-color : navy; } }
at-rule의 이름은 논의 중입니다. 대안으로 @supports-query, @supports-test, @custom-supports 등이 있습니다. 이 이름은 사용자 정의 미디어 쿼리의 명명과 일관되어야 합니다.
9. API
9.1.
CSSContainerRule 인터페이스
CSSContainerRule
인터페이스는 @container 규칙을 나타냅니다.
[Exposed =Window ]interface :CSSContainerRule CSSConditionRule {readonly attribute CSSOMString ;containerName readonly attribute CSSOMString ; };containerQuery
conditionText타입CSSOMString(CSSContainerRule 전용, CSSConditionRule 속성에 대한 정의)-
conditionText속성(CSSConditionRule상위 규칙에서 정의됨)은, 조회 시 다음과 같은 값을 반환해야 합니다:- @container 규칙에 <container-name>이 연관된 경우
containerName과containerQuery속성 값을 공백 하나로 이어 붙인 결과입니다.- 그 외의 경우
containerQuery속성 값을 반환합니다.
containerName타입CSSOMString-
containerName속성 조회 시, 다음과 같은 값을 반환해야 합니다:- @container 규칙에 <container-name>이 연관된 경우
- 해당 <container-name>의 직렬화 결과입니다.
- 그 외의 경우
- 빈 문자열입니다.
containerQuery타입CSSOMStringcontainerQuery속성은, 지정된 <container-query>를 논리적 단순화 없이 반환해야 하며, 반환된 쿼리는 이 명세의 모든 호환 구현에서(향후 확장 포함) 지정된 쿼리와 동일한 결과로 평가되어야 합니다. 즉, 토큰 스트림 단순화(공백 하나로 축소, 선택적으로 생략 등)는 허용되지만, 논리적 단순화(불필요한 괄호 제거, 결과 평가 기반 단순화 등)는 허용되지 않습니다.
컨테이너 쿼리는 matchContainer 메서드를 가져야 합니다.
이 메서드는 matchMedia()
및 MediaQueryList
인터페이스를 모델로 하되,
Window가 아닌 Element에 적용됩니다.
레이아웃 크기 측정 시 resizeObserver와 유사하게 동작하지만,
추가적인 컨테이너 쿼리 구문 및 기능을 제공합니다. [이슈 #6205]
9.2.
CSSSupportsConditionRule 인터페이스
CSSSupportsConditionRule
인터페이스는 @supports-condition 규칙을 나타냅니다.
[Exposed =Window ]interface :CSSSupportsConditionRule CSSGroupingRule {readonly attribute CSSOMString ; };name
name타입CSSOMString- 이 속성은 named supports condition의 이름입니다.
보안 고려사항
이 문서에 대해 제기된 보안 이슈는 없습니다.
프라이버시 고려사항
font-tech()와 font-format() 함수는 사용자의 소프트웨어에 대한 정보(버전, 특정 기능 활성화/비활성화 등)를 제공할 수 있습니다.
이 정보는 다른 API를 통해서도 파악할 수 있습니다. 하지만, 본 명세의 기능들은 이 정보가 웹에서 노출되는 여러 방법 중 하나입니다.
이 정보는 집계될 경우 사용자의 핑거프린팅 정확도를 높이는 데 사용될 수 있습니다.
변경사항
2024년 11월 5일 Working Draft 이후 변경사항
- 문서 내 마지막 @supports-condition 규칙이 적용됨을 명확히 함 (#12973)
- supports 쿼리가 at-rule 기능을 at-rule()로 표현할 수 있도록 확장 (#2463, #6966, #11116, #11117)
- @supports-condition at-rule 및 관련
CSSSupportsConditionRule인터페이스 추가 (#12622) - container-names는 트리 범위가 아님을 명확히 함 (#12090)
- scroll-state() 쿼리의 direction 기능 정의 (#6400)
- 조건식에서 0과 0px이 동등함을 명확히 함 (#12236)
- 스타일 컨테이너 쿼리의 범위 구문 정의 (#8376)
- 트리 카운팅 함수 명시적 허용 (#10982)
- 치수 컨테이너는 더 이상 레이아웃 컨테인먼트를 적용하지 않음 (#10544)
- snapped 쿼리에 "both" 값 추가 (#11181)
- overflowing 쿼리에 축 키워드 추가 (#11183)
- overflowing을 scrollable로 이름 변경 (#11182)
- <container-query>를 선택적으로 만듦 (#9192)
2024년 7월 23일 Working Draft 이후 변경사항
- none-키워드를 scroll-state() 기능에 추가 (#10874)
- container-type:scroll-state, stuck/snapped/scrollable 기능의 scroll-state() 쿼리 추가 (#6402, #10784, #10796)
- 예시 수정(컨테이너 타입 style은 없음)
- 컨테이너 쿼리는 flat tree를 사용함을 명시 (#5984)
2021년 12월 21일 최초 Working Draft 이후 변경사항
- 컨테이너 쿼리를 본 명세로 이동(CSS Contain 3에서 이동) (#10433)
- <font-format> 및 <font-tech> 정의를 명세 내 복제 대신 CSS Fonts 4에서 가져옴(#8110)
- 새 파싱 알고리즘 및 블록 production 이름 사용으로 업데이트
- <font-format> 문법 오타 수정
- font-tech, font-format production 내 불필요한 공백 수정 (#7369)
Level 4 이후 추가사항
- @when 및 @else 추가
- supports 쿼리에 font-tech() 및 font-format()로 폰트 기능 표현 확장
- supports 쿼리에 at-rule()로 at-rule 기능 표현 확장
- 컨테이너 쿼리를 [CSS-CONTAIN-3]에서 본 명세로 이동 (진화 과정은 CSS Containment 3 § A Changes 참조)
- @supports-condition at-rule 및 관련
CSSSupportsConditionRule인터페이스 추가
감사의 글
@when 및 @else 규칙은 Tab Atkins의 제안에 기반합니다.
다음 사람들의 의견과 선행 작업에 감사드립니다: Adam Argyle, Amelia Bellamy-Royds, Anders Hartvoll Ruud, Brian Kardell, Chris Coyier, Christopher Kirk-Nielsen, David Herron, Eric Portis, Ethan Marcotte, Florian Rivoal, Geoff Graham, Gregory Wild-Smith, Ian Kilpatrick, Jen Simmons, Kenneth Rohde Christiansen, Lea Verou, Martin Auswöger, Martine Dowden, Mike Riethmuller, Morten Stenshorne, Nicole Sullivan, Rune Lillesveen, Scott Jehl Scott Kellum, Stacy Kvernmo, Theresa O’Connor, Una Kravets, 그리고 많은 분들이 본 명세에 기여해 주셨습니다.