본문으로 바로가기

이미지 요소나 비디오 요소를 특정 비율에 맞춰 확장 또는 축소되길 원할때 사용되는 기법에 대한 설명입니다. 스크립트의 사용없이 오직 CSS만을 이용하여 이를 구현해보며 원리의 이해를 돕습니다.

이미지 비율 유지

이미지의 비율을 유지하면서 크기 조정을 하는 방법은 이미지의 너비와 높이 둘 중 어느 하나를 auto 값을 유지한 채로 크기 조정을 하는 것이다. 흔히 반응형 이미지에 사용되는 방법은 아래와 같다.

img {
    max-width: 100%;
    height: auto;
}

반응형 이미지의 너비를 자유롭게 조정하기 위해서 이를 감싸는 컨테이너를 추가 해주고 적절한 너비를 부여하면 아래와 같다.

<div class="thumbnail-wrapper">
    <img src="xxxx">
</div>
.thumbnail-wrappper {
    width: 25%;
}

img {
    max-width: 100%;
    height: auto;
}

이미지 원본의 비율을 유지하기 위해 너비만 부여했기에 이미지는 각각의 통일되지 못한 높이를 가지고 있게 된다. 또한 유동적인 너비를 갖도록 % 너비 값을 부여했으나 높이는 그럴 수 없다.

일반적으로 고정된 높이 값을 부여하고 넘치는 부분을 자른다면 아래와 같은 결과를 얻게 된다.

.thumbnail-wrappper {
    width: 25%;
    height: 200px;
    overflow: hidden;
}

img {
    max-width: 100%;
    height: auto;
}

유동적인 너비에는 대응하지 못하는 결과를 초래하므로 추천되지 않는 방법이다. 컨테이너 또한 일정한 비율 유지가 필요함을 깨닭게 된다.

컨테이너 비율 유지

컨테이너의 비율 유지를 위해 사용되는 기법은 2009년 Creating Intrinsic Ratios for Video에 기고된 내용인 아래의 내용을 이해하는 것이 핵심이다.

퍼센테이지(%, 백분율)은 컨테이너 블럭의 너비를 참조한다.

익히 알다시피, 퍼센테이지 단위는 부모 요소를 기준으로 계산되어 진다. 의외인 것은 자식 요소의 수직적인 패딩 값도 부모 요소의 너비에 영향을 받는 다는 것이다. 그 이유를 묻는다면 글쎄다... 그렇게 만들어졌고 브라우저들의 공통사항이다. 이 특징을 이용하여 상,하 어느 방향의 패딩값을 이용해서 특정 비율을 유지하는 컨테이너를 만들 수 있다.

<div class="thumbnail-wrapper">
    <div class="thumbnail">
        <img src="xxxx">
    </div>
</div>
.thumbnail-wrappper {
    width: 25%; 
}

.thumbnail {
    position: relative;
    padding-top: 100%;  /* 1:1 ratio */
    overflow: hidden;
}

img {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    max-width: 100%;
    height: auto;
}

이는 각각의 높이를 가지고 있는 이미지들을 absolute 포지셔닝을 통해 문서의 흐름에서 제외시켜 이미지의 높이가 컨테이너의 높이에 영향을 줄 수 없게 만들고 새로 추가된 .thumbnail 요소의 상단 패딩값으로 높이를 조절하게 만든다.

즉, 상단 패딩값 만큼만 이미지가 노출되고 나머지 넘치는 부분은 잘리게 되어 컨테이너는 일정한 비율을 유지하게 되며 유동적인 너비 변화에 대응한다.

다양한 비율 만들기

padding-top 의 값을 아래와 같이 변화시켜 다양한 비율을 얻을 수 있다.

  • 2:1 : padding-top: 50%
  • 1:2 : padding-top: 200%
  • 4:3 : padding-top: 75%
  • 16:9 : padding-top: 56.25%

이미지 가운데 정렬 및 가득채우기

출력할 이미지의 크기가 어느정도 예상 가능하다면 컨테이너의 너비와 비율을 적당히 수정해 이미지가 컨테이너에 가득차도록 만들 수 있을 것이다. 위의 비율 예에서는 4:3 비율이 출력할 이미지의 추천형태일 것이다.

만일, 이미지의 크기를 예상할 수 없는 경우라면 적어도 이를 가운데 정렬이 되도록 만들어 볼 수 있다. 위에서 사용한 코드에 재수정이 필요한 부분이다.

<div class="thumbnail-wrapper">
    <div class="thumbnail">
        <div class="centered">
            <img src="xxxx">
        </div>
    </div>
</div>
.thumbnail-wrappper {
    width: 25%; 
}

.thumbnail {
    position: relative;
    padding-top: 100%;  /* 1:1 ratio */
    overflow: hidden;
}

.thumbnail .centered  {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    -webkit-transform: translate(50%,50%);
    -ms-transform: translate(50%,50%);
    transform: translate(50%,50%);
}

.thumbnail .centered img {
    position: absolute;
    top: 0;
    left: 0;   
    max-width: 100%;
    height: auto;
    -webkit-transform: translate(-50%,-50%);
    -ms-transform: translate(-50%,-50%);
    transform: translate(-50%,-50%);
}

물론 translate 속성을 지원하지 않는 IE8 이하는 가운데 정렬되지 않는다. CSS 만으로는 한계에 봉착하는 부분이다.

portrait 와 landscape 이미지 구분

위의 예제들에서 사용된 이미지는 반응형 이미지의 기본 값을 사용하고 있다. 너비를 max-width 속성으로 제한해 왔기 때문에 너비는 최대치에 달하여도 높이는 경우에 따라 화면을 가득 채우지 못하곤 한다.

컨테이너의 너비를 이미지 원본보다 키우고 반응형 이미지 설정을 제거하면 화면을 채우지 못하는 공간이 확연히 드러난다.

세로로 긴 형태의 이미지를 portrait(초상화) 라고 부르곤한다, 이러한 형태의 이미지들은 정해진 영역의 너비에 이미지의 너비를 맞춰야 한다.

img.portrait {
    width: 100%;
    height: auto;    
}

마찬가지로 가로로 긴 형태의 이미지를 landscape(풍경화) 라고 부르곤 한다. 이러한 형태의 이미지들은 정해진 영역의 높이에 이미지의 높이를 맞춰야 화면에 가득차게 된다.

img.landscape {
    width: auto;
    height: 100%;    
}

위의 이미지들은 원본 이미지의 크기를 넘어서는 컨테이너 영역을 가득 채우기 위해서 각각 너비와 높이를 100%로 강제로 늘였기 때문에 이미지가 훼손된 상태이다. 만일, max-widthmax-height를 활용한다면 이미지의 최대 크기는 원본 크기를 넘어서지 못하고 여백을 남기게 되며, 각각 상황에 맞게 활용해야 한다.

안타깝게도 이미지 형태별로 원하는 클래스명을 추가하는 것은 CSS로만은 불가능하고 스크립트를 활용해 이미지의 실제 너비와 실제 높이를 비교해 상황에 맞는 클래스명을 붙여 주어야 한다. 물론 서버단에서 이미 이를 지원한다면 이야기는 다르겠지만...

이미지 자르기

위에서 설정한 이미지들의 너비와 높이를 auto 값으로 두면 원본 이미지의 크기가 컨테이너 안에서 출력되게 된다. 가운데 정렬을 했다면 가운데 부분이 잘려서 보이게 될 터이다.

즉, 컨테이너의 크기에 따라, 정렬하고 싶은 위치에 따라, 원본 이미지의 사진을 잘라내어 노출할 수 있게 된다. 정렬을 위해 translate 속성을 사용했으니 이 값을 원하는 만큼 조정하면 될터이고, translate 속성을 모두 제거하고 직접 absolute 포지셔닝을 이용해 잘라낼 부위를 선택할 수 있을 것이다.

이 글에서 사용된 예제는 responsive img test 에서 확인할 수 있다. 그 밖의 플러그인이나 스크립트를 이용한 썸네일은 아래의 링크들이 도움이 될 터이다.

아직까지는 스크립트의 사용없이는 완벽한 모델을 구현할 수가 없다는 결론이다. 적어도 서버단에서 썸네일로 사용될 이미지에 대한 형태 구분이라도 지원된다면 원하는 결과에 다가설 순 있을 것이다.