CSS의 object-fit 속성으로 이미지를 왜곡없이 보여주기

예전에는 웹에서 너비와 높이가 제한된 상황에서 이미지를 효과적으로 보여주는 것이 쉽지가 않았는데요. 그래서 이미지의 왜곡을 피하기 위해서 어쩔 수 없이 대신 배경 이미지를 사용해서 처리해야 하는 경우가 많았습니다.

하지만 다행히도 최근 몇 년 동안 CSS에서 이미지 요소를 다루는 방식이 상당히 개선되었습니다. 이번 포스팅에서는 이미지를 보여주는 방식을 결정하는 CSS의 object-fit 속성에 대해서 다양한 예제를 통해 최대한 쉽게 설명드리겠습니다.

이미지 본래 크기

HTML에서 <img> 요소를 사용할 때 너비나 높이를 지정해주지 않으면 브라우저는 이미지의 본래(intrinsic) 크기대로 보여줍니다.

<!-- 본래 너비 100px / 본래 높이 200px -->
<img src="https://dummyimage.com/100x200.png" />

하지만 이미지가 너무 넓거나 높은 경우 웹 페이지의 레이아웃을 깨뜨리거나 원치 않는 스크롤바가 생길 수 있는 위험이 있는데요. 그래서 보통 width 속성이나 height 속성을 통해서 이미지의 크기를 제한해주는 경우가 대부분이죠.

이 때 두 속성 중에 하나만 지정해줄 경우 브라우저는 이미지의 본래 가로 세로 비율을 유지한 채로 이미지를 표시해줍니다.

<!-- 너비를 2배인 200px로 지정하면 높이도 2배인 400px 자동 증가 -->
<img src="https://dummyimage.com/100x200.png" width="200px" />

<!-- 높이를 0.5배인 100px로 지정하면 너비도 0.5배인 50px로 자동 축소 -->
<img src="https://dummyimage.com/100x200.png" height="100px" />

이렇게 브라우저는 가급적 이미지를 본래 크기대로 보여주려고 하며 최대한 이미지의 본래 비율을 유지시키려고 노력합니다.

object-fit: fill

만약에 width 속성과 height 속성을 동시에 지정해주면 어떻게 될까요? 그러면 브라우저에서 이미지의 본래 비율이 깨지면서 이미지가 왜곡되어 보이는 문제가 발생할 수 있는데요.

예를 들어, 가로 세로 비율이 다른 3개의 이미지의 너비와 높이를 모두 200px로 지정해보겠습니다.

<img src="https://dummyimage.com/150x150.png" width="200px" height="200px" />
<img src="https://dummyimage.com/300x100.png" width="200px" height="200px" />
<img src="https://dummyimage.com/100x300.png" width="200px" height="200px" />

첫 번째 정사각형 모양의 이미지의 경우 이미지의 본래 비율이 width 속성과 height 속성으로 지정된 비율과 일치하기 때문에 이미지가 자연스럽게 표시됩니다. 그러나 두 번째 이미지는 가로가 더 긴 직사각형 모양이기 때문에 위아래로 잡아당긴 것처럼 보이며, 세 번째 이미지는 세로가 더 긴 직사강형 모양이라서 마치 위아래로 압축한 것처럼 왜곡되어 보입니다.

브라우저가 어떻게든 <img> 요소에 지정된 너비와 높이의 공간에 이미지를 채우려고 할 때 어쩔 수 없이 본래 이미지의 가로 세로 비율이 깨지면서 이러한 현상이 발생하게 되는데요. 이것이 CSS의 object-fit 속성을 명시해주지 않았을 때 기본적으로 적용되는 fill의 특성입니다.

의도적으로 이미지가 이렇게 왜곡되어 보이게 하고 싶은 경우가 아니라면 대부분의 UI를 구현할 때 피하게 되는 옵션입니다.

object-fit: cover

만약에 이미지의 본래 비율을 지키고 싶다면 우리는 어쩔 수 없이 다른 부분을 포기해야되는데요.

첫 번째 옵션은 object-fit 속성 값으로 cover를 사용하는 것입니다. 이 때 우리는 이미지의 일부가 짤릴 수 있는 댓가를 치뤄야 하죠.

img {
  object-fit: cover;
}

예를 들어, 아래에서 첫 번째 이미지는 본래 가로 세로 비율이 width 속성과 height 속성으로 지정한 비율과 일치하므로 짤리는 부분이 없는데요. 두 번째 이미지는 본래 가로가 세로보다 길어서 좌우로 짤리고요. 세 번째 이미지는 본래 세로가 가로보다 더 길어서 상하가 짤리게 됩니다.

정사각형 모양의 첫 번째 이미지의 경우 너비와 높이가 150px로 동일하여 확대가 약간 일어나지만, 두 번째와 세 번째 이미지의 경우 모두 너비와 높이 중 짧은 100px를 기준으로 확대가 되므로 좀 더 많이 일어나는 것도 볼 수 있습니다.

이 옵션은 유용한 경우가 상당히 많지만 특히 썸네일(thumbnail)이나 미리보기 그리고 이미지를 포함하고 있는 카드(card)나 여러 이미지로 이루어진 그리드(grid)를 만들 때 많이 사용되는데요. 이러한 UI는 보통 클릭(click)하거나 호버(hover) 하면 이미지 전체를 볼 수 있게 해주므로 이미지가 좀 짤려도 큰 문제가 되지 않는 경우가 많습니다.

object-fit: contain

이미지의 본래 비율을 보존하기 위한 두 번째 옵션은 object-fit 속성을 contain로 지정하는 건데요. 이렇게 하면 이미지 전체를 짤림없이 보여줄 수는 있지만 주어진 영역을 꽉 채우는 것은 포기해야합니다.

img {
  object-fit: contain;
}

object-fit 속성을 contain으로 준 상태에서 이미지의 본래 가로 세로 비율과 width 속성과 height 속성으로 지정한 비율이 일치하지 않으면, 아래의 두 번째와 세 번째 경우와 같이 이미지가 딱 들어맞지 않아서 이미지 상하나 좌우로 눈에 거슬릴 수 있는 빈 공간이 생기게 됩니다.

약간의 확대가 일어나는 첫 번째 이미지와 다르게 두 번째와 세 번째 이미지는 너비와 높이 중 긴 300px를 기준으로 축소가 일어나는 것을 볼 수 있습니다.

이 옵션은 이미지의 본래 비율에 왜곡이 없어야하고 짤리는 부분이 없이 이미지 전체를 보여줘야할테 사용되는데요. 특히 이미지 안에 짤리면 안 되는 중요한 텍스트가 있는 경우에 유용하게 쓸 수 있습니다.

object-fit: none

<img> 요소에 지정된 width 속성과 height 속성을 무시하고 이미지를 본래 크기대로 보여주고 싶다면 object-fit 속성 값으로 none을 사용할 수 있습니다.

img {
  object-fit: none;
}

방금 살펴본 contain 속성 값과 비슷하다고 보일 수 있지만 자세히 비교해보시면 상당히 다르게 빈 공간이 생기는 것을 보실 수 있으실 거에요. none 속성 값을 사용할 때는 이미지 전체를 짤림없이 주어진 영역에 들어오게 하기 위해서 이미지의 너비나 높이를 임의로 늘리거나 줄이지 않기 때문입니다.

예를 들어, 아래에서 첫 번째 이미지 주변으로는 25px의 빈 공간이 생기는 것을 볼 수 있는데요. width 속성과 height 속성이 모두 200px로 지정되어 있고 여기서 이미지의 본래 가로 세로 길이인 150px을 빼면 50px이 남으며 이것을 상하 좌우 공백이 이 등분하여 가져가기 때문입니다.

두 번째 이미지의 높이는 본래 높이인 100px로 표시되고 좌우로는 50px 씩 이미지가 짤려서 보이지 않게 되는데요. 이미지의 본래 너비가 300px인데 여기서 width 속성 값으로 지정된 200px를 빼면 100px이 남기 때문입니다.

세 번째 이미지의 경우에는 이미지의 본래 높이가 height 속성 값보다 100px이 크기 때문에 상하로 50px 씩 이미지가 짤리게 됩니다.

이 다소 극단적인 옵션은 이미지의 본래 크기가 주어진 공간보다 크면 클수록 짤리는 부분이 점점 더 커지게 때문에 주의해서 사용해야겠습니다.

object-fit: scale-down

마지막으로 살펴볼 object-fit 속성 값은 scale-down 인데요. 이 속성 값은 이미지가 주어진 영역보다 작을 때는 none 속성 값처럼 작동하다가, 이미지가 주어진 영역보다 클 때는 contain 속성 값처럼 작동합니다.

img {
  object-fit: scale-down;
}

예를 들어, 아래 첫 번째 이미지의 경우 주어진 영역보다 작기 때문에 본래의 너비와 높이로 표시가 됩는데요. 반면에 두 번째와 세 번째 이미지의 경우 주어진 영역보다 넓거나 높기 때문에 이미지 전체를 짤림없이 보여주기 위해서 축소가 됩니다.

비교적 최근에 추가된 이 옵션은 유용한 활용 사례를 아직까지 많이 못 본 것 같은데 추후에 소개드릴 만한 좋은 사례가 발견되면 공유드리도록 하겠습니다.

마치며

지금까지 CSS의 object-fit 속성을 사용하여 가로 세로의 크기가 정해진 영역 내에서 어떤 방식으로 이미지를 보여줄 수 있는지에 대해서 살펴보았습니다.

웹에서 이미지 하나를 보여주는데도 이렇게 많은 trade-off가 있다는 게 재미있지 않나요? 이미지 전체 표시, 본래 비율 유지, 이미지 짤림 여부, 빈 공간 허용 중 무엇이 더 필요하고 무엇을 희생할 수 있는지는 구현하시는 UI의 요구사항에 따라 다를 것입니다.

본 포스팅에서 다룬 부분들을 종합적으로 잘 고려하셔서 최적의 object-fit 속성 값을 고르시는데 도움이 되었으면 좋겠습니다. object-fit과 함께 CSS aspect-ratio를 사용하면 요소의 가로세로 비율까지 고정할 수 있으니 참고하세요. 화면 크기나 포맷에 따라 아예 다른 이미지를 보여주고 싶다면 HTML의 picture 요소도 함께 살펴보세요.

This work is licensed under CC BY 4.0 CC BY

개발자를 위한 뉴스레터

달레가 정리한 AI 개발 트렌드와 직접 만든 콘텐츠를 전해드립니다.

Discord