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