CSS object-fit 속성 사용하기
Tags: html, css
Published: 2021-06-02 15:46:41

# CSS object-fit 속성 사용하기

&nbsp;  

오늘은 CSS의 `object-fit` 속성을 사용해볼 것입니다.

최근 프로필 컴포넌트 개발 중 정사각형 컨테이너에 프로필 이미지를 표시해야하는 일이 있었습니다. 요구사항을 구체적으로 작성해보면 아래와 같습니다.

* 만약 이미지 크기가 컨테이너 크기보다 작거나 같다면, 컨테이너에 가득 채워서 표시
* 만약 이미지 크기가 컨테이너 크기보다 크다면, 해당 이미지의 정중앙 영역을 컨테이너 크기만큼 표시

&nbsp;  

바쁘신 분들은 [샌드박스 링크](https://codesandbox.io/s/css-object-fit-property-ubwgu)에 방문하여 소스코드를 먼저 살펴봐주세요.

&nbsp;  

## 1. width 100%; height 100%; 

가장 먼저 시도해본 것은 이미지 전체를 컨테이너에 맞춰 표시해보는 것이었습니다. 아래 코드를 확인해주세요.

```html
<section>
  <h2>1. 너비가 높이보다 더 큰 이미지</h2>
  <div class="block">
    <div class="img-wrapper">
      <!-- 컨테이너 너비에 맞춤 -->
      <img class="fit-width" src="./greater-width.jpg" alt="프로필 이미지" />
    </div>
    <div class="img-wrapper">
      <!-- 컨테이너 높이에 맞춤 -->
      <img class="fit-height" src="./greater-width.jpg" alt="프로필 이미지" />
    </div>
    <div class="img-wrapper">
      <!-- 컨테이너 너비, 높이에 맞춤 -->
      <img class="fit-width-height" src="./greater-width.jpg" alt="프로필 이미지"/>
    </div>
  </div>
</section>
<section>
  <h2>2. 높이가 너비보다 더 큰 이미지</h2>
  <div class="block">
    <div class="img-wrapper">
      <!-- 컨테이너 너비에 맞춤 -->
      <img class="fit-width" src="./greater-height.jpg" alt="프로필 이미지" />
    </div>
    <div class="img-wrapper">
      <!-- 컨테이너 높이에 맞춤 -->
      <img class="fit-height"	src="./greater-height.jpg" alt="프로필 이미지" />
    </div>
    <div class="img-wrapper">
      <!-- 컨테이너 너비, 높이에 맞춤 -->
      <img class="fit-width-height" src="./greater-height.jpg" alt="프로필 이미지" />
    </div>
  </div>
</section>
```

```css
/* width에 맞추기 */
.fit-width {
  width: 100%;
}
/* height에 맞추기 */
.fit-height {
  height: 100%;
}
/* width, height 둘 다 맞추기 */
.fit-width-height {
  width: 100%;
  height: 100%;
}
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iowgrtcsaxrsgmvy33ei.png)

너비가 더 큰 이미지를 컨테이너 너비에 맞춰 표시하면 하단 여백이 남습니다. 반대로, 컨테이너 높이에 맞춰 표시하면 이미지가 컨테이너 밖으로 넘치게되죠. 최후의 수단인 `width: 100%; height: 100%`를 사용했지만 역시 이미지 비율이 유지되지 않습니다. 이러한 문제는 높이가 더 큰 이미지에서도 똑같이 발생합니다. 이 방법은 아닌 것 같아요.

&nbsp;  

## 2. background-image 사용

두 번째로 시도한 방법은 `<img>` 태그가 아닌 다른 태그를 사용하여, 해당 요소의 배경 이미지로 프로필 이미지를 표시하는 것이었습니다. 아래 코드를 확인해주세요.

```html
<section>
  <h2>3. background-image 사용</h2>
  <div class="block">
    <div class="img-wrapper">
      <div class="background greater-width-img"></div>
    </div>
    <div class="img-wrapper">
      <div class="background greater-height-img"></div>
    </div>
  </div>
</section>
```

```css
/* background-image 사용 */
.background {
  width: 100%;
  height: 100%;
  background-position: center;
  background-size: cover;
}
.greater-width-img {
  background-image: url("./greater-width.jpg");
}
.greater-height-img {
  background-image: url("./greater-height.jpg");
}
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rhcd4bvsangg35gmagax.png)

`background-image`를 사용하여 프로필 이미지를 표시했을 때, 앞서 작성한 요구사항을 모두 충족합니다. 하지만 마크업이 마음에 들지 않아요. 무언가 semantic하지 않은 느낌입니다. 접근성 관점에서도 만족스럽지 않아요. `role`, `aria-label` 속성을 사용하여 마크업을 수정해보았습니다.

```html
<section>
  <h2>3. background-image 사용</h2>
  <div class="block">
    <div class="img-wrapper" role="img" aria-label="프로필 이미지">
      <div class="background greater-width-img"></div>
    </div>
    <div class="img-wrapper" role="img" aria-label="프로필 이미지">
      <div class="background greater-height-img"></div>
    </div>
  </div>
</section>
```

ARIA 속성을 사용하여 마크업을 수정했지만, 그래도 의미에 맞는 `<img>` 태그를 사용하고 싶어요. 이때 사용한 속성이 `object-fit` 속성입니다.

&nbsp;  

## 3. object-fit

CSS `object-fit` 속성은 **대체 요소(replaced element)**의 컨텐츠를 컨테이너 크기에 맞게 설정한다고 합니다. 그렇다면 대체 요소는 무엇일까요?

&nbsp;  

> **replaced element**
>
> **elements whose contents are not affected by the current document's styles.** The position of the replaced element can be affected using CSS, but not the contents of the replaced element itself.
>
> ex) `<iframe>`, `<video>`, `<embed>`, `<img>`
>
> 출처: https://developer.mozilla.org/en-US/docs/Web/CSS/Replaced_element

&nbsp;  

대체 요소는 자신의 컨텐츠가 문서 스타일(document's styles)에 영향을 받지 않는 요소를 뜻합니다. 즉, CSS 스코프에서 벗어난 친구들이죠. 하지만 딱 두 가지 경우 CSS의 영향을 받는다고 적혀있습니다.

1. 대체 요소의 위치 설정(대체 요소의 컨텐츠 위치 X)
2. **컨테이너 영역 안에서** 대체 요소의 컨텐츠를 positioning

&nbsp;  

여기서부터 뇌피셜이지만, 첫 번째 경우 `<img>` 요소는 CSS로 위치를 변경 할 수 있지만, `<img>` 요소의 컨텐츠인 이미지 그 자체는 위치를 변경 할 수 없다는 뜻으로 이해했습니다.

두 번째 경우는 `<img>` 요소의 컨텐츠인 이미지를 컨테이너 영역 안에서 제어하는 [CSS 속성](https://developer.mozilla.org/en-US/docs/Web/CSS/Replaced_element#controlling_object_position_within_the_content_box)이 있다는 것입니다. 그 중 하나가 오늘 사용해볼 `object-fit` 속성입니다.

```html
<section>
  <h2>4. object-fit 속성 사용</h2>
  <div class="block">
    <div class="img-wrapper">
      <img class="object-fit" src="./greater-width.jpg" alt="프로필 이미지" />
    </div>
    <div class="img-wrapper">
      <img class="object-fit" src="./greater-height.jpg" alt="프로필 이미지" />
    </div>
  </div>
  </div>
</section>
```

```css
/* object-fit 사용 */
.object-fit {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kci97p5xb17wcree0e91.png)

`object-fit` 속성을 사용하여 앞서 요구사항에 맞게 코드를 작성 할 수 있었습니다. 주의해야 할 것은 `object-fit` 속성은 IE에서 전혀 지원되지 않는다는 것입니다. 아래는 브라우저별 지원 현황입니다. (2021/6/3 기준)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0046lk0vd6jib3peehnr.png)

&nbsp;  

이번 포스트는 여기서 마치도록 하겠습니다.