복잡한 레이아웃에서 상호작용 최적화

웹 기능: content-visibility

칸반 보드나 대규모 데이터 그리드와 같은 복잡한 다중 열 레이아웃에서 드래그 앤 드롭 또는 대규모 변형 중에 높은 프레임 속도 (60FPS)를 유지하고 상호작용 지연 시간을 없앱니다.

개요

복잡한 레이아웃에서는 카드 드래그나 셀 수정과 같이 단일 항목을 약간 변경하면 스타일 및 레이아웃 계산의 연쇄 반응이 트리거되어 브라우저가 전체 페이지를 리플로우할 수 있습니다. 이로 인해 프레임이 누락되고 다음 페인트에 대한 상호작용 (INP) 지연 시간이 길어집니다.

자체 포함된 레이아웃 영역 (예: Kanban 보드의 열)에 content-visibility: auto를 적용하면 렌더링 작업을 격리할 수 있습니다.

화면 요소 메커니즘

content-visibility: auto가 이미 화면에 표시된 요소에 어떤 이점을 주는지 이해하는 것이 중요합니다.

  • 표시되는 요소의 경우 브라우저에서 렌더링을 건너뛰지 않습니다.
  • 대신 성능 이점은 속성이 자동으로 적용하는 CSS 포함(즉, 레이아웃, 스타일, 페인트)에서 전적으로 발생합니다.
  • 이러한 포함은 경계 역할을 합니다. 격리가 적용된 컨테이너 내부에서 변형이 발생하면 브라우저는 변경사항이 해당 컨테이너 외부 요소의 도형이나 스타일에 영향을 미칠 수 없음을 인식합니다. 페이지 리플로우가 격리되어 전역 레이아웃 재계산이 방지됩니다.

구현

1. 억제 영역 식별

격리된 레이아웃 단위 (예: 그리드 열, 보드 목록)를 나타내는 대규모 독립형 컨테이너에 content-visibility: auto를 적용합니다.

.board-column {
  /* Apply containment boundaries */
  content-visibility: auto;
  
  /* Mandatory: Provide a placeholder size to prevent layouts shifts.
     For a vertical column, define a reasonable width and height. 
     - 'auto' is optional and enables the browser to remember the actual size
       once rendered. It must be paired with a <length> value to be used for
       the first render.
     - '300px' is the estimated width of this element. This can be any valid
      CSS <length> value. Replace it with the expected width of your
      component.
     - '800px' is the estimated height of this element. This can be any valid
      CSS <length> value. Replace it with the expected height of your
      component.
   */
  contain-intrinsic-size: auto 300px auto 800px;
}

2. 상호작용 관리

열 내부에서 발생하는 상호작용이 포함의 이점을 누릴 수 있도록 합니다.

// Example: Drag and drop item movement
function moveItemToColumn(itemId, columnId) {
  const item = document.getElementById(itemId);
  const column = document.getElementById(columnId);
  
  // The browser will only reflow this specific column, 
  // not the entire board layout!
  column.appendChild(item);
}

대체 전략

속성이 점진적으로 저하됩니다. 지원되지 않는 브라우저:

  • 속성이 무시되고 변형으로 인해 표준 전역 리플로우가 발생합니다.
  • 이전 브라우저에서 유사한 격리 효과를 얻으려면 수동으로 격리를 적용하면 됩니다.
@supports not (content-visibility: auto) {
  .board-column {
    /* Manual fallback for containment */
    contain: layout style paint;
  }
}