╱╱╭╮╱╱╱╱╱╱╭━━━╮╱╱╱╭╮╱╭╮╱╱╱╱╱╱ ╱╱┃┃╱╱╱╱╱╱┃╭━╮┃╱╱╱┃┃╱┃┃╱╱╱╱╱╱ ╱╱┃┣━━┳━━╮┃┃╱┃┣━╮╱┃╰━╯┣━━┳━╮╱ ╭╮┃┃╭╮┃┃━┫┃╰━╯┃╭╮╮┃╭━╮┃╭╮┃╭╮╮ ┃╰╯┃╭╮┃┃━┫┃╭━╮┃┃┃┃┃┃╱┃┃╭╮┃┃┃┃ ╰━━┻╯╰┻━━╯╰╯╱╰┻╯╰╯╰╯╱╰┻╯╰┻╯╰╯

Frontend/기본기

[CSS] CSS만으로도 렌더링 속도 높이기 contain, content-visibility, contain-intrinsic-size

재안안 2025. 3. 8. 19:58

개요

[1] contain

[2] content-visibility

[3] contain-intrinsic-size

[4] reference

 

이번 주제의 속성을 이해하려면, 브라우저 렌더링 프로세스에 관한 기본 지식이 바탕되어야 한다.


[1] contain

 

contain이란?

  document dom tree에서 특정 dom의 하위 섹션을 격리할 수 있게 하는 css 속성이다.

이렇게 격리된 서브트리 내에서는 레이아웃, 스타일, 페인트, 사이즈 계산 등이 외부와 분리되어 이루어진다.


1. `contain: size;`

  해당 요소의 박스를 하위 요소들을 검사할 필요 없이 레이아웃 할 수 있도록 보장한다. 이를 통해 브라우저는 하위 요소들을 검사하지 않고 해당 요소의 크기를 결정할 수 있게 된다.

  레이아웃은 브라우저가 각 요소의 크기와 위치를 결정하는 과정으로, 요소의 박스(크기+ 위치)를 계산할 때 자손 요소들의 크기와 콘텐츠도 고려하게 되는데, `contain: size;`가 적용되면 브라우저는 그 요소의 자손들을 자세히 검사하지 않고도 해당 요소의 크기를 결정할 수 있다.


2. `contain: layout;`

  해당 요소의 자손들이 페이지의 다른 요소(박스)의 배치나 위치에 영향을 주지 않도록 격리하는 것을 보장한다. 해당 요소 내부에서 레이아웃에 변화가 생겨도, 이 변화가 외부(부모 요소나 형제 요소)의 레이아웃 계산에 영향을 주지 않는다. 또한, 브라우저는 다른 박스의 레이아웃을 계산할 때, 해당 요소의 서브트리 레이아웃은 생략된다.


3. `contain: style;`

  내부 스타일이 외부에 영향을 미치지 않게 하여, 다른 요소들의 스타일 계산 시 내부 스타일을 고려할 필요를 없앤다. 브라우저가 페이지의 다른 부분의 스타일을 계산할 때, `contain: style;`이 적용된 영역 내부의 스타일을 다시 계산할 필요가 없어 진다. 추가적으로, counter, quotes와 같은 속성을 공유할 때, 서브트리와 외부를 분리시킨다.


4. `contain: paint`

  해당 요소의 자식 요소들이 해당 요소의 경계 밖에 표시되지 않도록 보장한다. 적용 결과 `overflow: hidden;`과 비슷했지만, `contain: paint;`는 넘어서는 자식 요소들의 painting 자체를 스킵한다. 추가적으로, 만약 요소가 화면 밖에 있거나 다른 방식으로 보이지 않는 경우 또한 자식 요소들의 paiting을 스킵한다.

 


4. `contain: content;`, `contain: strict;`

  content는 `contain: layout paint`와 같고

  strict는 `contain: size layout paint`와 같다

 


 

[2] content-visibility

 

content-visiblity란?

  특정 요소의 layour과 paiting을 포함한 렌더링을 건너뛸 수 있게 해주는 css 속성이다. 

사용하기 어려울 것 같은데 다른 css 속성들과 똑같이 그냥 값을 넣어주면 된다.


1. content-visibility: visible;

  기본적으로 적용되는 속성으로 렌더링에 아무 영향을 미치지 않는다.


2. content-visibility: hidden;

  `display: none;`과 같은 효과를 준다.

요소에 해당 속성을 부여하면, 요소의 콘텐트는 렌더링이 스킵된다.

스킵된 콘텐트는 선택되거나 포커스될 수 없다. 요소를 숨겼다가 다시 렌더링해야 한다면, `content-visibility: hidden;`을 사용하는 방법이, `display: none;`에 비해, 비용을 줄일 수 있다. 

 

  • display: none:
    요소를 숨기면서 렌더링 상태도 완전히 파괴한다. 그래서 다시 보여주려면 처음부터 렌더링을 해야 한다.
  • visibility: hidden:
    요소는 숨기지만 렌더링 상태는 유지한다. 단, 해당 요소가 여전히 레이아웃 공간을 차지하며, 클릭 등의 상호작용이 가능할 수 있고, 필요할 때마다 렌더링 상태가 업데이트된다.
  • content-visibility: hidden:
    요소를 숨기면서 렌더링 상태는 유지하므로, 나중에 다시 보이도록 할 때 기존의 렌더링 상태를 그대로 활용할 수 있다.

 


3. content-visibility: auto;

  `content-visibility: auto`가 적용된 요소는  조건에 따라 콘텐트의 렌더링을 스킵한다.

하지만 `content-visibility: hidden`과는 다르게 스킵된 요소는 선택되거나 포커스될 수 있다.

조건에 따라 콘텐트에 `contain: layout style paint;`가 적용된다.

  `contain: layout style paint;`는 요소 내부의 변화가 페이지 전체에 영향을 미치지 않고, 해당 영역 내에서만 처리되도록 격리하는 것과 같다. 간단히 말하자면, `content-visibility: auto;`를 적용한 요소는 화면 밖에 있다면 그 자식 요소들은 렌더링되지 않는다.

  그런데 이때, 화면에는 렌더링 되지 않지만, 문서 객체 모델과 접근성 트리에는 그대로 남아있기 때문에 필요하다면 `aria-hidden: true;`을 직접 넣어줘야한다.

 

부여 조건은 다음과 같다.

  1) 요소가 뷰포트 안에 나타나거나, 사용자 에이전트가 정의한 뷰포트 주변 여백(뷰포트 크기의 50%)을 차지할 때

  2) 요소 또는 그 내부의 콘텐츠가 포커스를 받을 때

  3) 요소 또는 그 내부의 콘텐츠가 선택될 때

  4) 요소 또는 그 내부의 콘텐츠가 최상위 레이어에 배치될 때

 

 

 

격리된 서브트리에서는 layout과 reflow를 발생시키지 않아야 한다.

  content-visibility가 적용된 요소 내부에서는 렌더링을 유발하는 DOM API를 호출하지 않아야 성능 향상의 이점을 누릴 수 있다. 호출하지 않아야 하는 DOM API는 다음과 같다.

 

  1. 박스 메트릭 측정 (Box Metrics)
    • offset 관련 프로퍼티:
        elem.offsetLeft, elem.offsetTop, elem.offsetWidth, elem.offsetHeight, elem.offsetParent
    • client 관련 프로퍼티:
        elem.clientLeft, elem.clientTop, elem.clientWidth, elem.clientHeight
    • DOMRect 관련 메서드:
        elem.getClientRects(), elem.getBoundingClientRect()
  2. 스크롤 관련 API (Scroll APIs)
    • 스크롤 이동 메서드:
        elem.scrollBy(), elem.scrollTo()
    • 뷰포트로 스크롤:
        elem.scrollIntoView(), elem.scrollIntoViewIfNeeded()
    • 스크롤 크기 및 위치:
        elem.scrollWidth, elem.scrollHeight, elem.scrollLeft, elem.scrollTop
  3. 포커스 및 추가 속성 (Focus and Additional Properties)
    • 포커스 설정:
        elem.focus()
    • 추가 속성:
        elem.computedRole, elem.computedName
    • 텍스트 관련:
        elem.innerText
  4. 윈도우 및 뷰포트 크기 (Window Dimensions)
    • 윈도우 스크롤 위치:
        window.scrollX, window.scrollY
    • 윈도우 크기:
        window.innerHeight, window.innerWidth
    • 시각적 뷰포트 정보:
        window.visualViewport.height, width, offsetTop, offsetLeft
  5. 문서 관련 API (Document APIs)
    • 스크롤링 요소:
        document.scrollingElement
    • 요소 위치 확인:
        document.elementFromPoint
  6. 폼 및 선택 관련 (Forms & Selection)
    • 포커스 및 선택 처리:
        inputElem.focus()
    • 내용 선택:
        inputElem.select(), textareaElem.select()
  7. 마우스 이벤트 오프셋 (Mouse Event Offsets)
    • 오프셋 데이터 읽기:
        mouseEvt.layerX, mouseEvt.layerY, mouseEvt.offsetX, mouseEvt.offsetY
  8. 스타일 및 레이아웃 강제 (getComputedStyle)
    • 스타일 계산:
        window.getComputedStyle()
  9. 범위 관련 API (Range APIs)
    • Range 치수 측정:
        range.getClientRects(), range.getBoundingClientRect()

 

[3] contain-intrinsic-size

 

contain-intrinsic-size란?

  로드되지 않았거나 off-screen일 때 해당 요소가 차지할 공간의 크기를 미리 정해두어 레이아웃이 안정적으로 유지되게 하는 속성이다. 콘텐츠가 렌더링되지 않을 때 요소가 차지할 기본 크기를 브라우저에게 알려주어 레이아웃 안정성과 렌더링 성능을 동시에 향상할 수 있다.추가적으로 `contain-intrinsic-size: auto;`를 사용하면, 브라우저가 요소의 마지막 렌더링된 실제 크기를 기억한다.

 


 

[4] reference

https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility

 

content-visibility - CSS: Cascading Style Sheets | MDN

The content-visibility CSS property controls whether or not an element renders its contents at all, along with forcing a strong set of containments, allowing user agents to potentially omit large swathes of layout and rendering work until it becomes needed

developer.mozilla.org

 

https://web.dev/articles/content-visibility

 

콘텐츠 가시성: 렌더링 성능을 향상시키는 새로운 CSS 속성  |  Articles  |  web.dev

CSS content-visibility 속성을 사용하면 화면 밖에 있는 콘텐츠의 렌더링을 건너뛰어 웹 콘텐츠 렌더링 성능을 개선할 수 있습니다. 이 도움말에서는 auto 키워드를 사용하여 초기 로드 시간을 단축하

web.dev