1. 소개
웹사이트를 효율적으로 렌더링하려면 사용자 에이전트가 페이지의 어떤 부분이 표시되는지, 어떤 부분이 현재 표시된 섹션에 영향을 줄 수 있는지, 무엇을 무시할 수 있는지를 감지할 수 있어야 합니다.
주어진 서브트리가 어떤 방식으로든 페이지의 나머지와 독립적인지 추측하는 데 사용할 수 있는 다양한 휴리스틱이 있지만, 이러한 방법은 취약하여 페이지의 사소한 변경이 우연히 이러한 휴리스틱 테스트를 실패하게 만들어 렌더링이 느린 코드 경로로 빠질 수 있습니다. 또한 휴리스틱 방식으로 감지하기 어렵거나 불가능한, 격리하는 것이 바람직한 많은 상황이 있습니다.
이러한 문제를 완화하고 서브트리를 페이지의 나머지와 강력하고 예측 가능하게 격리할 수 있도록, 이 명세서는 요소와 그 자손 서브트리가 문서 트리의 나머지와 독립적임을 나타내는 contain 속성을 정의합니다.
1.1. 값 정의
이 명세서는 CSS 속성 정의 관례를 따릅니다 (출처: [CSS2]) 및 값 정의 문법을 [CSS-VALUES-3]에서 사용합니다. 이 명세서에서 정의되지 않은 값 유형은 CSS Values & Units [CSS-VALUES-3]에서 정의됩니다. 다른 CSS 모듈과의 조합으로 이러한 값 유형의 정의가 확장될 수 있습니다.
정의에 나열된 속성별 값들 외에, 이 명세서에서 정의된 모든 속성은 CSS-wide 키워드를 속성 값으로 허용합니다. 가독성을 위해 여기에는 반복해서 명시하지 않습니다.
2. 강력한 컨테인먼트: contain 속성
| Name: | contain |
|---|---|
| Value: | none | strict | content | [ size || layout || paint ] |
| Initial: | none |
| Applies to: | See below |
| Inherited: | no |
| Percentages: | n/a |
| Computed value: | the keyword none or one or more of size, layout, paint |
| Canonical order: | per grammar |
| Animation type: | not animatable |
사용자 에이전트는 비시각적 매체를 포함한 모든 매체에서 이 속성을 지원하는 것이 기대됩니다.
이 contain 속성은 작성자가 요소와 그 내용이 가능한 한 문서 트리의 나머지와 독립적임을 표시할 수 있게 합니다. 이는 사용자 에이전트가 페이지를 렌더링할 때 contain을 적절히 사용하면 훨씬 강력한 최적화를 활용할 수 있게 해주며, 작성자는 사소한 변경으로 인해 페이지가 느린 코드 경로로 빠질 우려가 줄어든다는 확신을 가질 수 있습니다.
- none
- 이 값은 속성이 아무 영향도 미치지 않음을 나타냅니다. 요소는 일반적으로 렌더링되며, 컨테인먼트 효과가 적용되지 않습니다.
- strict
- 이 값은 size layout paint로 계산되며, 따라서 요소에 대한 모든 형태의 containment를 활성화합니다.
- content
-
이 값은 layout paint로 계산되며,
따라서 요소에 대해 containment의 모든 형태를
제외하고 size
containment만 비활성화합니다.
참고: contain: content는 널리 적용하기에 비교적 "안전"합니다; 그 영향은 실제로 비교적 작고, 대부분의 콘텐츠는 그 제한에 저촉되지 않습니다. 그러나 size containment을 적용하지 않기 때문에, 요소는 여전히 자신의 내용의 크기에 반응할 수 있어서 레이아웃 무효화가 의도보다 더 위쪽 트리로 전파될 수 있습니다. 가능한 경우 최대한의 컨테인먼트를 얻기 위해 contain: strict를 사용하세요.
- size
- 이 값은 요소에 대해 size containment를 활성화합니다. 이는 containment box를 그 자손을 검사하지 않고도 레이아웃할 수 있음을 보장합니다.
- layout
- 이 값은 요소에 대해 layout containment를 활성화합니다. 이는 containment box가 레이아웃 목적상 완전히 불투명함을 보장합니다; 외부의 어떤 것도 내부 레이아웃에 영향을 미칠 수 없고, 내부도 외부에 영향을 줄 수 없습니다.
- paint
- 이 값은 요소에 대해 paint containment를 활성화합니다. 이는 containment box의 자손들이 그 경계를 벗어나 표시되지 않음을 보장하므로, 요소가 화면 밖에 있거나 보이지 않는 경우 그 자손들도 보이지 않음을 보장합니다.
이 속성은 일반적으로 모든 요소(예: CSS Pseudo-Elements 4
§ 4.1 Generated Content Pseudo-elements: ::before and ::after)에 적용됩니다,
다만 일부 유형의 컨테인먼트는 일부 요소에 대해 효과가 없으며,
이는 § 3 컨테인먼트의 유형에서 자세히 설명합니다.
또한, [SVG2]의 경우,
contain 속성은 CSS 레이아웃 박스와 연관된
svg
요소에만 적용됩니다.
예를 들어, 마이크로포스트 소셜 네트워크가 다음과 같은 마크업을 가졌다고 가정해보겠습니다:
< body >
< aside > ...</ aside >
< section >
< h2 > Messages</ h2 >
< article >
Lol, check out this dog: images.example.com/jsK3jkl
</ article >
< article >
I had a ham sandwich today. #goodtimes
</ article >
< article >
I have political opinions that you need to hear!
</ article >
…
</ section >
</ body >
사이트에 아마도 많은 메시지가 표시되겠지만, 각 메시지는 독립적이며 사이트의 다른 것들에 영향을 주지 않습니다. 따라서 각 메시지에 contain: content를 표시하여 사용자 에이전트에 이를 알릴 수 있으며, 이를 통해 페이지를 최적화하고 화면 밖에 있는 메시지들에 대한 많은 계산을 건너뛸 수 있습니다. 각 메시지의 크기를 미리 알고 있다면 contain: strict를 적용하여 추가 제한을 알릴 수 있습니다.
또한, used value가 HTML의
html
또는
body
요소에서의 contain 속성이 none이 아닌 경우,
body 요소에서 초기 포함 블록(initial containing block), 뷰포트 또는 canvas
background로의 속성 전파가 비활성화됩니다.
특히, 이는 다음에 영향을 미칩니다:
-
writing-mode, direction, 및 text-orientation (참조: CSS Writing Modes 3 § 8 The Principal Writing Mode)
-
overflow 및 그 롱핸들(참조: CSS Overflow 3 § 3.3 Overflow Viewport Propagation)
-
background 및 그 롱핸들(참조: CSS Backgrounds 3 § 2.11.2 The Canvas Background and the HTML <body> Element)
참고: initial containing block, 뷰포트 또는 canvas
background로의 전파는,
html
요소 자체에 설정된 속성에는 영향을 주지 않습니다.
3. 컨테인먼트의 유형
요소가 받을 수 있는 여러 형태의 containment가 있으며, 이는 자손이 페이지의 나머지에 미칠 수 있는 영향을 다양한 방식으로 제한합니다. Containment는 사용자 에이전트에 의해 훨씬 강력한 최적화를 가능하게 하고, 작성자가 기능 단위로 페이지를 구성하는 데 도움을 주며, 주어진 변경이 문서에 어느 정도까지 영향을 미칠 수 있는지를 제한합니다.
새 속성이나 메커니즘을 도입하는 명세 작성자는 다양한 유형의 컨테인먼트가 자신들이 도입하는 것에 어떤 영향을 미치는지 고려해야 하며, 여기에서 설명하지 않은 모든 영향을 그들의 명세에 포함시켜야 합니다.
3.1. 크기 컨테인먼트
요소에 size containment을 부여하면 그 요소의 principal box가 size containment box이 되며 다음과 같은 효과를 가집니다:
-
intrinsic sizes는 size containment box가 내용물이 없는 것처럼 결정됩니다. 이는 sizing as if empty와 동일한 논리를 따릅니다.
참고: 이는 min-content 또는 max-content 키워드의 명시적 호출뿐만 아니라, 이러한 측정에 의존하는 모든 계산(예: size contained 항목이 배치되는 grid tracks의 크기 결정), 또는 fit-content sizing이 containment box의 부모에 영향을 줄 수 있는 경우에 영향을 미칩니다.
-
size containment box와 그 내용의 레이아웃은 개념적으로 두 단계로 수행됩니다:
- 내용이 없는 것처럼 크기 결정
-
used width 및 height는 containment box의
레이아웃을 일반적으로 수행하는 것처럼 결정되지만,
그 박스는 내용물이 없는 것으로 취급됩니다—::before, ::after, ::marker 등의 가상 요소를 포함하여 아무 것도 고려하지 않습니다.
대체 요소(Replaced elements)는 자연스러운 너비와 높이를 0으로 간주하고 자연스러운 종횡비(natural aspect ratio)가 없다고 처리되어야 합니다.
참고: Size containment는 natural aspect ratio만 억제하므로, aspect-ratio과 같이 선호 종횡비(preferred aspect ratio)에 직접 영향을 주는 속성은 존중됩니다.
containment box의 모든 CSS 속성은 일반적인 레이아웃을 수행할 때와 마찬가지로 고려됩니다. 다른 명세서들은 특정 예외를 둘 수 있습니다.
참고: 요소의 sizing properties가 내재적 크기를 지정하더라도, 이것이 요소를 반드시 0 크기로 만들지는 않습니다: 요소에 설정된 속성들은 계속 고려되며, 이는 요소가 더 커지게 만들 수 있습니다.
- 제자리에 레이아웃
- 이제 고정된 크기의 containment box 안으로 해당 박스의 내용(가상 요소 포함)을 정상적으로 레이아웃해야 합니다.
참고: Size containment은 기준선 정렬(baseline alignment)을 억제하지 않습니다. 이 부분은 layout containment를 참조하세요.
-
Size containment boxes는 단일체(monolithic)입니다 (참조: CSS Fragmentation 3 § 4.1 Possible Break Points).
img{ width : 100 px ; aspect-ratio : 1 /1 ; contain : size; } < img src = "https://www.example.com/300x100.jpg" >
만약 aspect-ratio 속성이 선언되지 않았다면, 이미지의 크기는 100px x 0px가 되었을 것입니다. 이는 이미지의 natural aspect ratio가 억제되고, natural height가 0으로 처리되기 때문입니다.
그러나 요소에 size containment을 부여해도 다음 중 어느 하나에 해당하면 아무 효과가 없습니다:
-
요소가 principal box를 생성하지 않는 경우(예: display: contents 또는 display: none인 경우)
-
내부 표기(inner display type)가 table인 경우
-
principal box가 internal table box인 경우
-
principal box가 internal ruby box이거나 non-atomic inline-level 박스인 경우
참고: 내부 테이블 박스(internal table boxes)는 테이블 캡션을 포함하지 않으며 제외됩니다. 이는 테이블 레이아웃 알고리즘이 박스가 흐름 내 내용물보다 작아지는 것을 허용하지 않기 때문입니다. 셀을 내용이 없는 것처럼 크기를 정한 다음 내용물을 그 안에 레이아웃하여 크기를 변경하지 않는 것은 사실상 정의되지 않은 동작입니다. width 또는 height 속성을 수동으로 0으로 설정해도 내용보다 작아질 수는 없습니다. 이 문제는 테이블 캡션에는 적용되지 않으며, 테이블 캡션은 내용과 독립적인 고정 크기를 가질 수 있습니다.
3.1.1. 가능한 크기-컨테인먼트 최적화
이 절은 규범적이지 않습니다.
그 자체로는 크기 컨테인먼트는 많은 최적화 기회를 제공하지 않습니다. 단독으로의 주요 이점은 containment box의 크기를 기반으로 containment box의 내용을 레이아웃하려는 도구들(예: "container query" 개념을 구현한 JS 라이브러리)이 자식의 크기가 containment box의 크기에 반응하여 containment box의 크기까지 변경시키고, 그 결과로 자식의 크기 계산이 다시 바뀌어 추가적인 변경을 유발하는, 이른바 "무한 루프"를 걱정하지 않고 작업할 수 있다는 점입니다.
그러나 레이아웃 컨테인먼트와 함께 사용될 때, 활성화될 수 있는(하지만 이에 국한되지 않는) 가능한 최적화는 다음과 같습니다:
-
containment box의 자손의 스타일이나 내용이 변경될 때, DOM 트리에서 "더러워진(dirtied)" 부분을 계산하여 재레이아웃이 필요할 수 있는 지점을 판단하는 작업을 containment box에서 멈출 수 있습니다.
-
페이지를 레이아웃할 때, containment box가 화면 밖에 있거나 가려져 있다면, 그 내용의 레이아웃(즉, "제자리에 레이아웃")을 지연시키거나 우선순위를 낮춰 수행할 수 있습니다.
3.2. 레이아웃 컨테인먼트
요소에 레이아웃 컨테인먼트를 부여하면 그 요소의 principal box가 layout containment box가 되며 다음과 같은 효과가 있습니다:
-
만약 어떤 fragmentation container가 속한 fragmentation context의 적어도 하나가 레이아웃 컨테인먼트를 가지거나, 또는 동일한 fragmentation context의 어떤 fragmentation container가 layout containment box의 자손인 경우가 있고, 같은 fragmentation context의 그 이후의 다른 fragmentation container가 동일한 layout-contained 요소의 자손이 아닌 경우, 그러면 그 최초의 layout containment box는 남은 분절된 흐름(fragmented flow)을 "가둬야(trap)" 합니다: 분절(fragmentation)은 layout containment 경계를 지나 계속되어서는 안 되며, 첫 번째 layout containment 경계 내의 마지막 fragmentation container는 그 fragmentation context에서의 마지막 fragmentation container인 것처럼 취급됩니다.
만약 그 fragmentation context에서 이후에 생성되는 fragmentation containers가 분절된 흐름에 더 많은 내용이 남아 있을 때만 생성된다면, 이들은 생성되지 않습니다. 만약 어쨌든 존재할 예정이었다면, 그들은 fragmentation context의 일부로 남아있지만 분절된 흐름으로부터 어떤 내용도 받지 않습니다.
참고: 이 시점에서 작성 시점에는 이 조항에 영향을 받는 안정적인 명세는 없습니다. 일부(그러나 전부는 아닌) fragmentation containers만을 layout-contained로 만들 수 있는 메커니즘을 허용하는 명세들이 고려된 바 있으며, 그러한 경우에 이 규칙을 따르지 않으면 레이아웃 컨테인먼트가 의도한 보장이 실현되지 않습니다. 예: [CSS-REGIONS-1], ::nth-fragment() 등. 이 요구사항은 포함되어 있으며, layout containment가 regions 등에 미치는 영향은 [CSS-REGIONS-1]에 자세히 나와 있습니다.
< article > Lorem ipsum…</ article > < div id = a ></ div > < aside > < div id = b ></ div > < div id = c ></ div > </ aside > < aside > < div id = d ></ div > < div id = e ></ div > </ aside > < div id = f ></ div > article{ flow-into : foo;} #a, #b, #c, #d, #e, #f{ flow-from : foo;} aside{ contain : layout} 이 [CSS-REGIONS-1] 예제에서, 컨텐츠는
#a에서#b로,#b에서#c로 흐를 수 있습니다. 그러나#c가 최초의 layout containment box 내의 마지막 fragment container이므로 남은 모든 내용을 가두며,#d,#e,#f로는 아무것도 흐르지 않습니다. -
만약 overflow 속성의 계산된 값이 visible 또는 clip이거나 그 조합인 경우, 어떠한 오버플로우도 ink overflow로 처리되어야 합니다.
-
layout containment box는 absolute positioning containing block과 fixed positioning containing block을 설정합니다.
-
layout containment box는 stacking context를 생성합니다.
-
강제 단절(forced breaks)은 layout containment boxes 내에서 허용되지만, 부모에게 전파되지는 않습니다(자세한 내용은 CSS Fragmentation 3 § 3.1 Breaks Between Boxes: the break-before and break-after properties 참조).
참고: 이는 이전에 존재하지 않았던 가능성, 즉 박스와 그 컨테이너 사이에서 강제 단절이 발생할 수 있다는 가능성을 도입합니다 (참조: CSS Fragmentation 3 § 4.1 Possible Break Points).
-
vertical-align 속성이나, layout containment box의 기준선(baseline)을 자손 이외의 무언가와 관련시켜야 하는 다른 속성들의 목적상, containment box는 기준선이 없는 것으로 처리됩니다.
그러나 요소에 레이아웃 컨테인먼트를 부여해도 다음 중 어느 하나에 해당하면 아무 효과가 없습니다:
-
요소가 principal box를 생성하지 않는 경우(예: display: contents 또는 display: none인 경우)
-
그 요소의 principal box가 internal table box이며, 다만 table-cell이 아닌 경우
-
그 요소의 principal box가 internal ruby box이거나 non-atomic inline-level 박스인 경우
3.2.1. 가능한 레이아웃-컨테인먼트 최적화
이 절은 규범적이지 않습니다.
레이아웃 컨테인먼트로 활성화될 수 있는 가능한 최적화는 다음과 같습니다(이에 국한되지 않음):
-
페이지를 레이아웃할 때, 서로 분리된 containment boxes의 내용은 서로에게 영향을 주지 않음이 보장되므로 병렬로 레이아웃할 수 있습니다.
-
페이지를 레이아웃할 때, 만약 containment box가 화면 밖에 있거나 가려져 있고 화면의 가시적인 부분들의 레이아웃이 containment box의 크기에 의존하지 않는다면(예: containment box가 블록 컨테이너의 끝 근처에 있고 화면에는 블록 컨테이너의 시작 부분을 보고 있는 경우), 그 containment box 내용의 레이아웃은 지연되거나 우선순위가 낮게 수행될 수 있습니다.
(이 최적화는 크기 컨테인먼트와 함께 사용될 때 더 관대하게 적용될 수 있습니다.)
3.3. 페인트 컨테인먼트
요소에 페인트 컨테인먼트를 부여하면 그 요소의 principal box가 paint containment box가 되며 다음과 같은 효과가 있습니다:
-
요소의 내용(어떠한 ink 또는 스크롤 가능한 오버플로우 포함)은 padding edge를 고려하여 paint containment box의 패딩 경계 안으로 클립되어야 하며, 코너 클리핑을 고려합니다. 이는 클립된 콘텐츠의 접근이나 존재를 나타내기 위한 어떤 메커니즘의 생성 자체를 포함하지 않으며; 다른 속성들(예: overflow, resize, 또는 text-overflow)을 통해 그러한 메커니즘을 생성하는 것을 막지는 않습니다.
참고: 이 명세의 다음 단계인 [CSS-CONTAIN-2]는 이 효과를 overflow clip edge에 적용하도록 정교화하여 새로운 overflow-clip-margin 속성을 고려합니다. overflow-clip-margin을 지원하지 않는 구현에서는 효과가 동일합니다.
참고: 이 문단에 설명된 동작은 overflow-x: visible을 사용 시 overflow-x: clip으로, 그리고 overflow-y: visible을 overflow-y: clip으로 변경하는 것과 동등하며, 다른 값들은 변경하지 않습니다.
-
paint containment box는 absolute positioning containing block과 fixed positioning containing block을 설정합니다.
-
paint containment box는 stacking context를 생성합니다.
-
paint containment box는 독립적인 포매팅 컨텍스트를 형성합니다.
그러나 요소에 페인트 컨테인먼트를 부여해도 다음 중 어느 하나에 해당하면 아무 효과가 없습니다:
-
요소가 principal box를 생성하지 않는 경우(예: display: contents 또는 display: none인 경우)
-
그 요소의 principal box가 internal table box이며, 다만 table-cell이 아닌 경우
-
그 요소의 principal box가 internal ruby box이거나 non-atomic inline-level 박스인 경우
3.3.1. 가능한 페인트-컨테인먼트 최적화
이 절은 규범적이지 않습니다.
페인트 컨테인먼트로 활성화될 수 있는 가능한 최적화는 다음과 같습니다(이에 국한되지 않음):
-
만약 containment box가 화면 밖에 있거나 가려져 있다면, UA는 일반적으로 그 내용물을 페인트하려고 시도하는 것을 건너뛸 수 있습니다, 해당 내용물도 화면 밖이거나 가려져 있음이 보장되기 때문입니다.
참고: blur()와 같은 일부 페인트 효과(예: blur() 필터)는 비지역적(non-local) 효과를 가집니다. UA는 이러한 것들을 추적해야 합니다. 이러한 필터를 가진 요소의 자손이 변경되면 해당 요소의 일부를 다시 페인트해야 할 수도 있기 때문에, 비록 자손들이 페인트 컨테인먼트를 가지고 있어 건너뛸 수 있더라도 재페인트가 필요할 수 있습니다.
-
클립된 콘텐츠가 overflow, resize, 또는 text-overflow 같은 별도의 메커니즘을 통해 접근 가능하게 만들어지지 않는 한, UA는 박스의 크기와 정확히 일치하는 "캔버스" 공간을 예약할 수 있습니다. (유사한 스크롤 가능한 상황에서는, 예: overflow: hidden, 현재 클립된 콘텐츠로 스크롤하는 것이 가능하므로, UA는 스크롤이 발생하자마자 볼 수 있는 것을 미리 페인트하기 위해 다소 과잉으로 페인트할 수 있습니다.)
-
이들은 스태킹 컨텍스트임이 보장되므로, 스크롤 가능한 요소들은 하나의 GPU 레이어에 페인트될 수 있습니다.
4. 개인정보 보호 고려사항
이 명세서의 기능들에 알려진 개인정보 영향은 없습니다.
5. 보안 고려사항
이 명세서의 기능들에 알려진 보안 영향은 없습니다.
다른 CSS 명세와 마찬가지로, 이 명세는 문서의 렌더링에 영향을 주지만, 문서를 포매팅하는 행위에 본질적으로 포함되지 않는 특별히 오해를 불러일으키는 방식으로 콘텐츠를 표시할 수 있는 능력을 새로 도입하지는 않습니다.
부록 A. 변경사항
이 부록은 참고용입니다.
2022년 10월 25일 권고안으로부터의 변경사항
세 가지 제안된 수정이 규범 텍스트에 공식적으로 통합되었습니다:
- 제안 수정 1:
-
contain 속성의 계산된 값이 결정되는 방식에 약간의 조정이 이루어졌습니다: 단축형 값들(strict 및 content)은 스스로로 계산되는 대신 해당하는 키워드들로 계산됩니다. 효과가 동일하므로, 구현체가 이를 달성한 정확한 문법을 저장하지 않아도 됩니다. 또한 shortest-serialization 원칙 덕분에, 이 사소한 차이는 직렬화를 통해 관찰 불가능합니다.
- 제안 수정 2:
-
크기 컨테인먼트에 대한 설명이 다소 모호하여 구현자들이 특정 경우에 의도된 효과에 대해 약간 의문을 가졌습니다. 이를 보다 정확한 설명으로 대체하여 의도된 동작을 변경하지 않으면서 의미를 명확히 했습니다.
- 제안 수정 3:
-
CSS 워킹 그룹은 컨테인먼트가 HTML의
html및body요소에 미치는 영향, 특히 레거시 이유로 인해 일부 속성들이body요소로부터 바깥으로 전파될 수 있다는 점을 고려하는 것을 깜빡했습니다. 추가된 텍스트는 이 간과를 다룹니다.
구현 보고서는 여러 엔진에서의 구현을 자세히 설명합니다.
이전 변경사항
이 명세의 이전 변경사항에 대한 자세한 내용은 이전 발행물의 변경 섹션에서 확인할 수 있습니다.