CSS로 이미지 정렬하기

엄격한(Strict) 문서 규격 정의(DTD)에서는 이미지 정렬에 흔히 사용되던 align 속성을 허용하지 않습니다. 따라서 img 태그만으로는 이미지의 위치를 자유롭게 조절할 수 없고, 반드시 CSS를 함께 사용해야만 합니다.

단순히 하나의 이미지만 넣어야 할 경우에는 text-align이라는 CSS 속성으로 간단히 해결할 수 있지만 현실적으로는 이보다 훨씬 복잡한 경우가 많습니다. 특히 이미지와 텍스트를 함께 배치하려면 어쩔 수 없이 float 속성을 사용해야 하는데 이 속성에 대한 해석이 브라우저에 따라 차이가 있으므로 브라우저 호환성 면에서 생각보다 훨씬 많은 위험성을 갖고 있습니다. 이렇게 까다로운 이미지 태그를 잘 사용하기 위해 알아두어야 할 점과 float 속성으로 이미지를 정렬하는 방법에 대해서 정리해봤습니다.

† 앞으로 제시할 모든 예는 noimgstyle class가 적용된 div 안에 넣었고, 기본적으로 적용된 속성은 아래와 같습니다. 그 외의 모든 CSS 규칙은 인라인 스타일로 정의했으므로 소스를 확인하면 각 예에 적용된 속성을 확인할 수 있습니다.

.noimgstyle { border: 1px solid #699; padding: 1em 1em 0 1em; margin-bottom: 1em; line-height: normal; height: 1%; }
.noimgstyle img { border: none; margin: 0; padding: 0; display: inline; }
.noimgstyle p { text-align: justify; margin-bottom: 1em; }
.noimgstyle span { background-color:#666; color: #fff; }

인라인(inline) 레벨 요소인 img 태그

일반적으로 이미지는 직사각형의 영역을 갖고 있습니다. 따라서 div, p, blockquote 등의 태그처럼 블록(block) 레벨에 속한다고 착각하기 쉽지만 실제로는 일반 텍스트와 동일한 인라인 요소입니다. 따라서 특별한 처리 없이 사용될 경우 아래 예처럼 텍스트의 한 글자처럼 취급됩니다.

글자처럼 test image 취급되는 test image image

그런데 동일한 인라인 요소임에도 줄이 제대로 맞지 않는 것을 볼 수 있습니다. 이것은 알파벳의 g, p, y 등의 문자에서 베이스라인 아래로 내려오는 꼬리(descender)를 위한 영역 때문입니다. 즉, 이미지를 꼬리가 없는 i 문자처럼 취급한다는 얘기지요.

이 사이 간격을 없애는 방법은 많이 알려져 있습니다. 첫 번째는 이미지를 감싸는 상위 요소(div 등)의 높이를 이미지와 같도록 해주는 것이고, 두 번째는 CSS의 vertical-align: text-bottom 속성을 지정하는 것입니다. 이미지를 블록(block) 요소로 보이도록 하는 세 번째 방법은 나중에 알아보고 일단 vertical-align: text-bottom 속성을 적용한 이미지를 보겠습니다. CSS를 인라인 스타일(inline stye)로 지정했으므로 소스를 확인하면 바뀐 부분을 확인할 수 있습니다.

글자처럼 test image 취급되는 test image image

† 인라인 이미지와 텍스트의 배치를 결정해주는 vertical-align 속성에는 많은 브라우저 호환성 문제가 있습니다. 특히 line-height 속성과 결합되면 심각한 문제가 생길 수 있다고 하네요. 일반적으로 발생하는 문제가 아니기에 추가적으로 설명하지는 않겠습니다. 어떤 문제가 있는지 알아보려면 이미지 수직 정렬과 line-height와의 관계긴 이미지와 line-height와의 관계 페이지를 인터넷 익스플로러와 파이어폭스에서 비교해 보시기 바랍니다.

블록(block) 레벨 요소로 보이는 이미지

이미지를 인라인 요소가 아닌 블록 요소로 보여지도록 해야 할 경우가 있는데 이 때 사용되는 것이 CSS의 display 속성입니다. 먼저 알아두어야 할 것은 이 속성이 HTML 요소가 어떻게 보여질지만을 바꿀 수 있다는 점입니다. 다시 말해서 인라인 요소를 블록 요소로 바꾸어주는 것이 아니라는 것이지요. 간단한 예를 들자면 HTML 규격상 인라인 레벨 요소는 블록 레벨 요소를 포함할 수가 없습니다. 따라서 인라인 요소인 span 태그에 display: block; 속성을 지정한다고 해도 span 태그 안에 p 태그는 들어갈 수 없습니다.

하지만 인라인 요소를 블록 요소로 보이게(display) 하면 이미지 위, 아래에서 줄바꿈(line break)이 생깁니다. 아래 예는 이미지에 display: block; 속성이 적용되었을 때의 결과입니다.

블록으로 test image 취급되는 test image image

† 이미지와 텍스트에 적용되는 line-height 속성 때문에 서로 다른 요소가 일부 겹치는 경우가 있습니다. line-height 속성 값을 바꾸어도 문제가 해결되지 않는다면 Designer kukie 님의 오늘의 문제는 line-height라는 글을 참고하시기 바랍니다. 이 문제로 한참을 헤매다가 kukie님이 잘 정리해두신 덕에 해결했습니다. :-)

인라인 이미지 정렬

인라인 이미지는 텍스트와 동일하게 취급되므로 텍스트 정렬에 사용되는 CSS의 text-align 속성이 그대로 적용됩니다. 따라서 중앙 정렬시키려면 이미지를 감싸고 있는 p 태그에 text-align: center;를 지정하고, 오른쪽으로 보내려면 text-align: right;를 사용할 수 있습니다. 아래는 가운데 정렬의 예입니다.

글자처럼 test image 취급되는 test image image

text-align 속성은 블록 레벨 요소와 테이블 셀(table cell: th, td), 인라인 블록(inline-block)에 적용되고, 해당 요소가 아닌 하위 요소에 영향을 미칩니다(예: 텍스트).

그런데 이미지가 이런 방식으로 텍스트와 함께 사용되는 경우는 드뭅니다. 보통은 이미지 아래에 텍스트가 들어가거나 이미지 옆 공간에 글 단락이 들어가니까요. 텍스트가 아래 배치될 경우에는 p 태그에 이미지만 넣거나 이미지를 블록 레벨로 보이게 하면 되지만 후자의 경우에는 문제가 복잡해집니다. 그럼 왜 문제가 복잡한지 알아볼까요?

이미지에 float 적용하기

이미지 옆에 텍스트 단락을 넣기 위해서는 이미지에 CSS의 float 속성을 주어야만 합니다. 과도적인(Transitional) HTML 문서 규격에서는 이미지에 align 속성을 사용할 수 있지만 엄격한(Strict) 문서 규격에서는 허용되지 않은 속성이기 때문입니다.

먼저 이미지에 float: left; 속성만 적용시킨 예를 보겠습니다. 단락 구분이 잘 보이도록 p 태그에 테두리선을 넣었습니다.

test imageLorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean vel tellus nec massa cursus malesuada. Pellentesque metus.

Proin eu nisi eu tortor consectetuer varius. Curabitur magna nunc, pretium id, tincidunt a, tempus porttitor, nisi. Integer erat lacus, tempor non, varius sit amet, laoreet in, arcu. Pellentesque tempus mauris. Nulla ut ante ut massa suscipit euismod.

이 상태로도 별 문제가 없지만 두 번째 단락을 이미지 옆이 아닌 새 줄에 넣으려는 의도였다면 원했던 결과는 아닐겁니다. float된 요소는 말 그대로 문서 내에서 떠 있는 상태이기 때문에 다른 요소들을 밀어낸 것처럼 보입니다. 또한, float된 요소는 순차적인 요소(box)들의 흐름(normal flow)을 따르지 않으므로 주의해서 사용해야만 합니다.

float 제거하기(clearing float)

float 속성을 적용시켜서 어떤 요소를 띄웠다면 적절한 곳에서 반드시 그 영향을 없애주는 것이 좋습니다. 기본적으로 float된 요소의 높이(height)는 해당 요소가 들어 있는 블록(containing block) 크기에 영향을 미치지 않는데 이런 특성을 없애서 바깥 블록이 float 요소의 높이만큼 늘어나도록 하면 float 특성을 제거할 수 있습니다. 이런 float 제거(clearing float) 방법에는 여러 가지가 있습니다.

clear 속성 사용

clear 속성을 이용해서 float을 제거하려면 두 가지 요건이 갖추어져야 합니다. 첫 번째는 float된 요소를 담고 있는 블록(containing block) 안에서 clear 속성이 사용되어야 한다는 것입니다. 아래 예가 이 요건을 갖춘 경우입니다.

<p><img src="somepath" style="float:left" />some text<br style="clear:both" /></p>
<p>some text</p>

하지만 아래와 같이 마크업할 경우에는 브라우저에 따라서 다른 결과가 생깁니다. 이미지를 담고 있는 요소(containing block)은 첫 번째 p 단락인데 clear 속성은 p 단락 밖에서 적용되었으니까요.

<p><img src="somepath" style="float:left" />some text</p><br style="clear:both" />
<p>some text</p>

두 번째 요건은 인터넷 익스플로러에만 해당되는 것으로 float 요소가 포함된 블록(containing block)이 화면상에서 레이아웃을 갖는 요소(haslayout = true)로 인식되어야 합니다. float 문제는 주로 페이지의 레이아웃을 잡을 때 나타나는데 대부분의 경우 float을 포함하는 divwidthheight 속성을 지정하면서 자동으로 이런 요건을 갖춥니다. 하지만 아래 예처럼 이런 속성이 지정되지 않은 p 태그 안에서는 clear 속성이 인터넷 익스플로러에서만 다르게 적용됩니다. 즉, 인터넷 익스플로러에서는 파이어폭스에서와는 달리 p 태그 높이가 이미지 높이만큼 자동으로 늘어나지 않는 것을 볼 수 있지요.

test imageLorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean vel tellus nec massa cursus malesuada. Pellentesque metus.

Proin eu nisi eu tortor consectetuer varius. Curabitur magna nunc, pretium id, tincidunt a, tempus porttitor, nisi. Integer erat lacus, tempor non, varius sit amet, laoreet in, arcu. Pellentesque tempus mauris. Nulla ut ante ut massa suscipit euismod.

간단한 해결 방법은 Holly hack을 적용시키는 것입니다. float 이미지가 있는 p 태그에 다음과 같은 CSS를 적용시키면 문제가 해결됩니다. widthheight 중 어느 하나라도 정해지면 haslayout 속성이 적용되기 때문입니다.

p { height: 1%; }

float된 이미지의 옆 공간을 채우기 위해서 br 태그를 여러 개 이어서 사용하는 경우가 있는데 좋은 방법이 아닙니다. 그보다는 CSS에 clear를 담당하는 class를 지정해놓고 필요할 경우 적용시키는 것이 좋지요. 흔히 이용되는 코드는 다음과 같습니다.

.clearer { clear: both; }
<br class="clearer" />
<div class="clearer"></div>

한 가지 주의해야 할 점은 <div class="clearer"></div>가 만능은 아니라는 사실입니다. HTML의 컨텐츠 모델에 따라서 동일한 블록 레벨 요소라 해도 p 태그 안에는 div 태그가 들어갈 수 없으므로 상황에 따라서 적절한 태그를 골라서 적용시켜야 합니다.

간단한 방법이지만 float 제거만을 위한 마크업이 추가된다는 단점이 있습니다. 게다가 이미지 옆에 여러 개의 단락이 들어가야 할 경우에는 사용할 수가 없지요. 또한, 위 예처럼 두 개의 단락이 p 태그로 명확하게 구분되어 있을 경우에는 br 태그를 사용할 필요가 없으므로 ‘의미 있는’ 마크업도 아닙니다.

clear 속성이 적용되는 방식

W3Cclear 속성에 관한 CSS 규격에는 다음과 같이 정의되어 있습니다.

clear 속성은 적용된 요소의 어느쪽 박스 경계가 이전에 float된 박스와 인접하지 않을지를 결정한다. 이 속성은 float된 요소 자체에도 적용되나 이 경우 clear의 효과는 나타나지 않는다.”

clear 속성이 left로 지정되면 clear가 적용된 요소의 박스 상단 마진(margin-top)이 위에 있는 왼쪽으로 떠 있는(left-floating) 박스의 아래 경계에 닿을 수 있도록 늘어나게 된다.”

이런 상황을 잘 설명해주는 이미지를 float 속성에 관한 CSS 규격에서 가져왔습니다.

그림에서 볼 수 있듯이 두 번째 p 블록에 clear 속성이 적용되면 이미지 크기로 인해 생긴 공간만큼 p 블록의 위쪽 마진(margin-top)이 자동으로 늘어나게 되고, 그 결과 블록이 이미지 아래로 내려오게 됩니다. 그러면 실제 예를 볼까요?

<p><img src="somepath" style="float:left" />some text</p>
<p style="clear:both">some text</p>

결과는 아래와 같습니다.

test imageLorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean vel tellus nec massa cursus malesuada. Pellentesque metus.

Proin eu nisi eu tortor consectetuer varius. Curabitur magna nunc, pretium id, tincidunt a, tempus porttitor, nisi. Integer erat lacus, tempor non, varius sit amet, laoreet in, arcu. Pellentesque tempus mauris. Nulla ut ante ut massa suscipit euismod.

먼저 앞서 설명한 float 제거(clearing float) 방법과는 달리 상위 블록이 자동으로 늘어나지가 않습니다. 또한, 인터넷 익스플로러(7 포함)와 기타 브라우저에서 서로 다른 결과가 나오는 것을 알 수 있습니다. 파이어폭스나 오페라 등의 브라우저에서는 이미지와 아래 p 요소 사이에 어떠한 공백도 생기지 않는데 이것이 그림이 나타내는 CSS의 표준 렌더링 방식입니다. 하지만 인터넷 익스플로러에서는 p 태그의 margin-bottom 속성이 float된 이미지에도 적용되기 때문에 이미지와 아래 p 요소 사이에 빈 공간이 들어가게 되지요.

모든 브라우저가 동일한 렌더링 결과를 보여준다면 굳이 float을 없애지(clearing float) 않아도(즉, containing block 길이를 늘리지 않고) 원하는 곳에서 clear 속성을 사용할 수도 있을겁니다. 이미지 아래로 p 태그와 같은 margin-bottom을 지정하면 되니까요. 하지만 현실적으로는 몇 가지 문제가 있는데 결정적으로 인터넷 익스플로러에서 이미지 하단과 p 단락 사이의 높이에 따라서 서로 다른 마진을 적용시키기 때문에 크로스 브라우징 면에서 사용하기는 어렵다고 생각됩니다.

† 이 문제에 대한 정보는 이상하게 찾을 수가 없더군요. 그래서 무언가 중요한 요소를 생각하지 못한게 아닌가 하는 생각도 듭니다. 하지만 최소한의 CSS만 적용한 상태에서도 같은 결과가 나오는 것을 보면 인터넷 익스플로러의 CSS 해석 문제라고 생각합니다. 관련 정보 아시는 분들의 제보를 기다립니다.

일단 마치며

간단히 이미지 정렬하는 방법에 대해 포스팅할 생각이었는데 p 태그에 테두리를 설정한 순간 이미 간단함은 멀리 사라졌습니다. 물론 이렇게 보여드리기 위한 예가 아니라면 흔히 발생하는 문제는 아닐겁니다. 하지만 글을 쓰는 입장에서는 가능하다면 왜 그런지 설명을 해야한다고 생각하기 때문에 간단하게 쓸 수가 없네요. 개인적으로 긴 글을 아주 싫어해서 나머지는 다음 글에서 이어나가기로 하겠습니다. ^^;

자료를 찾아보며 알게 된 분명한 사실은 인터넷 익스플로러가 표준을 따르는 오페라, 파이어폭스, 사파리(윈도우즈용으로 테스트)와는 다른 방식으로 float을 처리한다는 사실입니다. 이는 인터넷 익스플로러가 사용하는 자체 속성인 haslayout과 관련이 있는데 다음 글에서 좀 더 자세히 알아보도록 하겠습니다. 아울러 overflow를 사용하는 float 제거 방법과 그 외의 방법도 소개하겠습니다.

  1. CSS로 이미지 정렬하기
  2. hasLayout 속성과 홀리 핵(Holly hack)
  3. float을 제거하는 방법(clearing float)

댓글 11개가 달렸습니다. 태그: , ,

  1. Creorix | 2007-08-12 00:41

    float는 항상 많이 헷갈리기도 하고 크로스 브라우징시 주로 문제가 되는 부분이었는데, 정리해주셔서 감사합니다. 다음 글도 기대하고 있겠습니다 :)

  2. wystan | 2007-08-12 01:38

    도움 되신다니 기쁘네요. :-)

    생각을 글로 정리하는게 유익한 이유는 자료를 찾으면서 새로운 것들을 배울 수 있기 때문이라고 생각해요.
    이 글을 쓰면서도 잘 모르고 있던 사실들을 많이 알게 되었답니다~

  3. cindij | 2007-10-14 21:57

    우연히 알게 되어 들어와보게 되었습니다. 작업하면서도 항상 뭔가가 부족한 느낌이였는데
    정리가 될듯 싶어 즐겨찾기해두었는데 오늘 다시 보고 프린트합니다.
    문서화하니 더 개념을 이해할수 있을 것 같습니다.
    복받으세요.
    근데 관리자님 비스타에서 미리보기가 안 되네요. ^^

  4. wystan | 2007-10-15 23:58

    좋은 말씀 해주셔서 고맙습니다. ^^ 도움이 되신다니 참 기쁘네요~

    비스타에서 미리보기가 안된다는 걸 전혀 몰랐습니다. 알려주셔서 감사드려요~
    주변에 비스타 쓰는 분들이 없어서 금방 수정하기는 어렵겠지만 방법을 찾는대로 수정하겠습니다.

  5. toonitw | 2008-05-19 21:53

    단순히 구글에서 float 속성 사용법만 알아내려 했는데 정말 간단한 문제가 아니네요 ^^ 체계적으로 잘 정리해 주셔서 그래도 잘 알수 있었습니다.

  6. wystan | 2008-05-21 15:41

    고맙습니다~ ^^

    IE 7 이하가 float을 다르게 해석해서 문제가 더 복잡해지는데 그래도 IE 8에서는 이런 잘못된 구현이 사라질테니 그나마 다행이예요~

  7. 밥먹자 | 2009-01-31 22:08

    저번에 읽었는데 또 까먹어서 다시 공부하고 갑니다.
    감사합니다. ^^

  8. 와우 | 2009-12-11 17:01

    감사합니다^^
    개인 자료 소장용으로 퍼갑니다

  9. 맑음군 | 2010-12-16 16:49

    좋은 자료 잘 보았습니다.

    덕분에 이미지가 인라인 요소라는 부분을 정확하게 이해를 했네요.

    이런 부분은 보통 어떻게 처리하는지요?

    이미지 텍스트

    가 있을때 이미지의 높이가 100px이라면 바로 옆의 텍스트가 이미지의 세로기준으로 가운데 정렬이
    되는 방법은 어떻게 표현 하는지요?

    예전에 익스에서는 이미지태그에 align=absmiddle 코드를 넣어서 썼는데 이게 다른 브라우저에서는
    정상적으로 먹히지 않더군요.

    아시는 부분이면 도움 부탁 드립니다.^^

  10. 이선인 | 2011-07-28 10:14

    사실 다른곳에서 자료를 봤는데, 좋은 자료 퍼가기 위해서 원본작성자분께 인사드리려고 합니다.
    제 블로그에 퍼가겠습니다- 좋은 자료 감사합니다^ㅅ^

  11. 엽기토끼이요 | 2012-03-26 00:48

    사랑합니다. 원하던 자료입니다.

댓글이 닫혔습니다.