CSS contain 속성 정리
CSS contain 속성은 특정 요소와 그 하위 요소를 외부 렌더링 계산에서 격리시킨다. 페이지 일부가 바뀌어도 그 변화가 페이지 전체로 번지지 않게 막아주기 때문에, 복잡한 페이지나 SPA에서 부분 업데이트가 잦을 때 효과가 크다.
렌더링은 네 단계를 거친다
브라우저가 화면을 그릴 때는 다음 단계를 거친다.
Style → Layout → Paint → Composite 네 단계다. JavaScript에서 어떤 속성을 바꾸느냐에 따라 어느 단계부터 다시 계산되는지가 달라지고, 그게 곧 렌더 비용이다. contain은 이 재계산 범위를 줄여주는 도구다.
출처: web.dev — Rendering performance
contain의 네 가지 값
layout — 내부 레이아웃 변화가 외부 레이아웃 계산에 영향을 주지 않는다.
size — 요소의 본래 크기(intrinsic size, 콘텐츠 기반으로 결정되는 자기 크기)를 계산할 때 하위 요소를 무시한다. 하위 요소가 없는 것처럼 자기 크기를 결정한다는 뜻이다. contain: size만 걸고 width/height를 명시하지 않으면 요소가 0으로 잡힐 수 있어서, 크기를 같이 지정해야 한다.
paint — 하위 요소가 컨테이너의 padding edge 바깥으로 그려지지 않게 클리핑된다. ink overflow와 scrollable overflow가 모두 포함된다. 컨테이너 자체가 화면 밖에 있으면 하위 요소도 페인트되지 않는 부수 효과가 있다.
style — CSS counters, quotes처럼 트리 전체로 퍼질 수 있는 효과가 해당 서브트리 안에 묶인다.
출처: MDN — contain, W3C css-contain-1
단축값 — content와 strict
| 단축값 | 동일한 값 |
|---|---|
content | layout paint style (size는 빠져 있음) |
strict | size layout paint style (전부 적용) |
초기 css-contain-1 명세에서는 style이 빠진 정의였다가 css-contain-2 이후 현행 정의로 바뀐 이력이 있다.
출처: W3C css-contain-2, drafts.csswg.org/css-contain
.widget처럼 strict를 쓰는 경우엔 width/height를 같이 지정해야 효과가 있다.
.card {
contain: content;
}
.widget {
contain: strict;
width: 320px;
height: 240px;
}화면 밖 요소를 안 그리는 건 content-visibility의 일
contain: paint가 걸린 컨테이너가 화면 밖이면 하위 요소가 페인트되지 않는 부수 효과는 있다. 다만 화면 밖 요소의 렌더링을 적극적으로 건너뛰고 싶다면 content-visibility: auto가 더 직접적인 도구다. contain은 격리, content-visibility는 렌더링 건너뛰기. 역할이 다르다.
출처: web.dev — content-visibility
배경색은 명세 요건이 아니지만 챙겨두면 안전하다
W3C 명세는 contain을 쓸 때 배경색을 요구하지 않는다. 다만 CSS-Tricks의 deep dive에서 "컨테이너 배경이 투명하면 브라우저가 별도 paint 레이어로 분리하지 못해 스크롤 단계 이점이 줄어든다"는 관찰이 보고됐다. 명세상 필수는 아니지만, paint containment 이점을 노린다면 배경색을 명시해 두는 게 안전하다.
출처: CSS-Tricks — Deep dive into CSS contain
어디에 쓰면 잘 맞는가
- 무한 스크롤·가상 리스트의 각 아이템 — 스크롤 중 부분 업데이트가 페이지 전체로 번지지 않게
- 독립적인 카드·기사·위젯 컴포넌트
- 광고·소셜 버튼처럼 외부에서 들어오는 서드파티 콘텐츠
- 사용자 상호작용으로 자주 바뀌는 동적 영역
모든 요소에 contain: strict를 거는 식의 과사용은 효과가 없거나 오히려 손해다. 실제 측정을 보고 적용 범위를 정해야 한다.
2022년부터 모든 브라우저에서 안정 지원
caniuse 기준 Safari 15.4+에서 완전 지원되며, MDN은 "Baseline Widely available, 2022년 3월부터 모든 브라우저에서 사용 가능"으로 표기한다. Chrome, Firefox, Edge, Safari(데스크탑·iOS 모두) 동일하게 안정 지원이다.
Speed Kit 필드 테스트로 본 실제 효과
Speed Kit의 필드 테스트 보고서가 contain의 실제 효과를 다룬 공개 측정치에 가장 가깝다.
- 로컬 렌더링 시간: 한 케이스에서 825ms → 172ms로 약 80% 감소
- INP: Chrome 클라이언트 렌더링 카테고리 페이지에서 27ms 개선, Samsung Browser에서 47~120ms 개선
- LCP: 모바일 Samsung Browser에서 148ms 개선
같은 보고서가 "일률적인 효과는 아니다(not a one-size-fits-all)"라고 결론을 낸다. 같은 contain이라도 페이지 구조·DOM 깊이·페인트 레이어 상태에 따라 효과 차이가 크다. 자기 페이지에서 직접 측정해서 적용 여부를 정해야 한다.
출처: Speed Kit — Field testing CSS containment
contain과 content-visibility를 같이 알아둔다
contain은 격리 도구, content-visibility는 렌더링 건너뛰기 도구다. 둘 다 챙겨둬야 쓸모가 있다.