개발/Etc

Cumulative Layout Shift(누적 레이아웃 이동, CLS)

달리초이 2023. 1. 11. 11:45

 

layout shift는 영상 예시를 보면 쉽게 이해할 수 있다. 영상은 이곳에서 가져왔다.

 

 

웹에 접속해서 페이지를 로드할 때 서버에서 아직 응답을 받지 못한 데이터가 있을 수 있다. 그때 ui 상으로는 더 하단에 있더라도 더 빨리 렌더링 되는 순서대로 차곡차곡 다른 데이터들이 먼저 자리를 차지하게 된다. 결국 뒤늦게 도착한 데이터는 정해진 영역에 마치 비집고 들어가는 것처럼 보이게 된다. html 구조상에 위차한 영역에 들어가는 것 뿐인데도 말이다.

 

이 문제는 해당 영역에 공간을 별도로 설정해 두지 않아서 발생한다. 위 영상에서도 버튼 클릭처럼 중요한 이벤트를 처리하는데, 클릭 순간 갑자기 안보이던 영역이 추가로 생기면서 버튼이 밀리는 현상이 발생한다. 사용자가 전혀 원하지 않은 다른 버튼을 클릭하게 되는 부작용이 발생해 버린다. ux 측면에선 치명적인 순간이다.

 

이 문제를 lighthouse에서 Cumulative Layout Shift 라는 항목으로 점수화 시켜 보여주는 것이다.

CLS는 페이지의 전체 수명 동안 발생하는 모든 예기치 않은  레이아웃 이동에 대해 가장 큰 레이아웃 이동 점수 버스트를 뜻합니다.
- https://web.dev/

 

Cumulative Layout Shift 간단 해결 방법

이 문제를 해결하려면, 미리 영역을 지정하면 된다. 하지만 반응형 웹처럼 처음부터 고정 영역 설정을 해줄 수 없는 경우가 많다는 게 문제다. 그래서 보통 css를 이용하여 padding 꼼수를 이용하는 방법을 많이 사용한다. 예시를 보자.

<div class="item">
  <img src="item.webp" alt="" />
</div>

<style>
.item {
  position: relative;
  width: 100%;
  padding-bottom: 50%;
}
.item > img {
  position: absolute;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
}
</style>

item이라는 div태그 안에 img 요소가 하나 있다. 이때 이미지 사이즈는 반응형에 따라 달라진다. 이미지 사이즈는 알지 못하지만 이미지 비율이 가로세로 2:1로 일정하다고 가정해보자. 그렇다면 img 태그의 크기는 감싸고 있는 부모 div 크기에 맞춰 키워주게 하고 부모 div를 'padding-bottom: 50%'를 적용해서 공간을 미리 확보해 두는 식이다. 1:1 이미지라면 100%를 주면 된다.

 

(100 / 가로) x 세로 = 패딩값

 

패딩으로 넣을 퍼센트값은 간단히 '(100 / 가로) x 세로'로 계산하면 구할 수 있다. 이미지 비율을 넣어도 되고 이미지의 width, height 값을 넣어도 무방하다.

 

이렇게 넣어주면 미리 해당 영역을 비어있는 상태로 렌더링하기 때문에 데이터 호출이 늦어지더라도 레이아웃이 밀려나갈 일 자체가 발생하지 않게 된다.

 

위 방법말고도 다른 방법도 있는데,

최근에는 반응형 웹들이 2021년 초에 나온 aspect-ratio를 많이 사용하고 있다고 한다. aspect-ratio는 요소의 크기를 일관되게 조정하는 속성으로 비율이 커지거나 줄어들 때 비율대로 유지될 수 있도록 해주는 속성이다.

https://caniuse.com/?search=aspect-ratio 

 

"aspect-ratio" | Can I use... Support tables for HTML5, CSS3, etc

CSS3 object-fit/object-position Method of specifying how an object (image or video) should fit inside its box. object-fit options include "contain" (fit according to aspect ratio), "fill" (stretches object to fill) and "cover" (overflows box but maintains

caniuse.com

 

https://w3c.github.io/csswg-drafts/css-sizing-4/#aspect-ratio

 

CSS Box Sizing Module Level 4

Abstract This module extends the CSS sizing properties with keywords that represent content-based "intrinsic" sizes and context-based "extrinsic" sizes, allowing CSS to more easily describe boxes that fit their content or fit into a particular layout conte

w3c.github.io

ul {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12em, 1fr));
}
li {
  aspect-ratio: 1/1;
  overflow: auto;
}

 

728x90
반응형