Logo

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 속성 값을 고르시는데 도움이 되었으면 좋겠습니다.