CSS 박스 모델에 대해

CSS 에서 가장 중요한 개념 중 하나가 박스모델입니다.
박스모델의 개념을 이해함으로써 각각의 엘리먼트를 문서에 배치하는 원리를 알 수 있기 때문입니다. 그리고 이를 응용하여 전체 레이아웃을 정의할 수도 있고, 콘텐츠를 디자인할 수도 있기 때문에 CSS를 통한 디자인을 하려면 박스모델을 이해하는 것이 필수라고 할 수 있습니다.

우선... 첫번째로 이해해야 할 명제는 "모든 엘리먼트, 태그는 박스 모델이다" 라는 것입니다. <br>, <b> 같은 표현을 위한 태그를 제외하면, 자주 사용하는 <div>, <span>, <table>, <p> 등의 태그들은 기본적으로 사각형(박스) 형태로 되어 있습니다. 생각해보면 이러한 태그들이 원형으로 들어가는 것은 없지요? ^^;;
두번째는 "contents, padding, border, margin" 입니다. 모든 박스모델은 이러한 속성을 가지고 있고 이 순서대로 둘러싸여있다고 보시면 되겠네요. 또한 padding, border, margin이 각각 4가지 속성을 가지고 있는데, top, bottom, left, right 로 분리할 수 있어서 각 방향의 속성을 따로 지정해 줄 수 있습니다. 예를 들어 margin-right:2px; margin-left:2px; 등으로 이렇게 따로 지정해 줄 수 있으며, 각각의 속성은 임의대로 조합해서 사용할 수 있습니다.

사용자 삽입 이미지
  1. contents : 순수한 콘텐츠
  2. padding : 콘텐츠와 경계선 사이의 여백
  3. border : 경계선. 이 선 자체의 모양이나 두께도 바꿀 수 있다.
  4. margin : 경계선 밖에서 박스모델의 최종 경계선까지의 여백
원래 이론상 모든 태그에는 margin, padding, border의 초기값이 0으로 지정되어야 하는 것이 맞지만 각 브라우저의 설정에 따라 기본적으로 가지고 있는 간격이 존재할 수도 있습니다. 예를 들면 순서 없는 리스트를 의미하는 <UL> 내의 엘리먼트인 <LI> 태그의 경우 목록 모양을 만들어주기 위해 버튼 형태와 함께 기본적 패딩을 가지고 있습니다. 보통 CSS로 디자인하기 위해서 <LI> 속성에 list-style:none, padding:0 을 적용해주는 걸 많이 보셨을 거에요.

간단하게 <div>태그로 만든 박스에 패딩을 적용한 소스를 확인해 보겠습니다. 이 편이 박스모델을 이해하는 것이 훨씬 쉬울 것 같습니다.

<div style="width:400px;background:#f2cccc;">
<div style="width:300px;background:#f4f4f4; padding:10px 20px; border:solid 2px red; margin-right:10px; margin-left:10px;">
THIS IS BOX MODEL. THIS IS BOX MODEL. THIS IS BOX MODEL. THIS IS BOX MODEL. THIS IS BOX MODEL. THIS IS BOX MODEL. THIS IS BOX MODEL. THIS IS BOX MODEL. THIS IS BOX MODEL. THIS IS BOX MODEL. THIS IS BOX MODEL. THIS IS BOX MODEL. THIS IS BOX MODEL.
</div>
</div>


이 모델을 분석하면 다음과 같이 됩니다.

사용자 삽입 이미지

첫번째 div 엘리먼트의 붉은색의 배경은 height를 지정하지 않고 width만 400px으로 지정하였습니다. 이 엘리먼트는 기본적으론 아무 것도 적용하지 않았기 때문에 padding과 margin은 모두 0입니다.
그 안의 두번째 div 엘리먼트는 width는 300px로 지정했으며, padding은 상하 10px, 좌우 20px이고 border는 상하좌우 모두 solid 형태의 2px, margin은 왼쪽과 오른쪽을 각각 10px로 정하였습니다.
즉 이 박스의 전체 width는 10(margin) + 2(border) + 20(padding) + 300(contents) + 20(padding) + 2(border) + 10(margin) = 364px 입니다.
참고로 background-color 속성도 적용되어있는데 background 속성은 contents + padding 영역에 적용이 됩니다.
height의 경우 콘텐츠에 따라 유동적으로 결정되도록 따로 height 를 주지 않아 일정한 높이는 없지만 2px 의 border가 상하에 적용되어 있고, padding이 상하에 10px 적용되어 있는 걸 확인할 수 있죠.

margin과 padding에서 쓸 단위는 px, em, % 등 상관없이 사용할 수 있습니다.
border의 경우 약간 틀린데 경계선의 모양과 색상을 따로 줄 수 있기 때문에 추가 속성이 있습니다. border-width 외에 border-style, border-color 속성 등이 있습니다. border-style 속성의 경우 경계선의 모양을 결정해주는데, 사용되는 밋밋한(?) 형태의 실선인 'solid' 가 자주 사용됩니다.. border-color 속성은 보시다시피 색상을 지정하는데 RGB코드나 색상명으로 사용하구요. 이 세 속성을 연달아 사용할 수 있어서 border:solid 2px red; 등으로 지정할 수 있습니다.


1. margin 및 padding 의 간략한 표기
원래 margin-top, margin-bottom 등으로 따로 표기하는 것이 원칙이지만 이를 간단하게 margin 속성 하나로 제어할 수 있을 뿐만 아니라 일부의 값이 같으면 더 축약하여 쓸 수 있습니다.
줄여 쓸 때에는 margin:5px 10px 15px 20px; 등으로 네개의 값을 연달아 쓸 수 있는데 '상우하좌' 순서입니다. 이는 위쪽부터 시작해서 시계방향으로 돌아가는 것과 같으니 시계방향이라는 것만 기억하셔도 됩니다.
  • 1개 - margin:5px; -- 상하 좌우에 모두 똑같이 5px 의 마진이 적용됩니다.
  • 2개 - margin:5px 10px; -- 상하에는 5px, 좌우에는 10px 의 마진이 적용됩니다.
  • 3개 - margin:5px 10px 15px; -- 상 5px 좌우 10px, 하 15px 의 마진이 적용됩니다.
  • 4개 - margin:5px 10px 15px 20px; -- '상좌하우' 방향에 모두 별도의 마진이 적용됩니다.
다만 이렇게 줄여서 쓸 경우엔 한가지 속성만 지정했을 때와 달리, 네가지 값을 한꺼번에 지정하는 효과가 있기 때문에 주의해야 합니다.
만약 초기 마진이 모두 0으로 지정되어 있는 상황에서 margin:9px 0 0 0; 과 margin-top:9px; 는 보이는 것은 같지만 의미가 같지는 않습니다. 전자는 이전 속성에서 지정된 margin-left나 margin-right 값이 다시 0으로 설정되지만, 후자는 따로 지정하지 않았기 때문에 이전 값에 변화가 없습니다.


2. 여러 margin 사이의 충돌
화면 상에서 세로방향(상하)에 연달아 있는 엘리먼트의 경우 margin 속성이 맞닿게 되면 작은 쪽이 없어져 병합되는 현상이 발생합니다.
예를 들어 첫번째 div 엘리먼트가 margin:10px 0;으로 설정되어 있고, 두번째 div 엘리먼트가 margin:20px 0 55px;로 설정되어 있다면 첫번째의 아래 마진 10px와 두번째의 위 마진 20px가 더해져서 총 30px의 마진이 들어가야 원래 의도에 맞습니다만, 이때 마진이 병합되어 작은 마진은 사라지고 20px의 마진이 적용되는 것입니다. 이를 피하기 위해서는 경계선이 없는 엘리먼트의 경우 한쪽에는 마진 대신 패딩을 적용해주면 됩니다. 경계선(border)이 있는 경우는... 코딩을 바꿔야겠지요. ^^
하지만, 이러한 병합은 가로방향(왼쪽, 오른쪽) 마진과 float가 적용된 엘리먼트의 마진의 경우엔 적용되지 않기 때문에 이럴 때에는 걱정하지 않으셔도 됩니다.


3. 음수값의 margin, padding 사용 가능
원래 마진과 패딩 값은 양수 값을 사용하는 것이 원칙이지만 음수를 사용해서 특이한 효과를 줄 수 있습니다. 주로 겹치는 효과 등을 연출할 수 있습니다.
CSS
   Special Effect
이 문구는 아래 special effect라는 문구가 있는 div 엘리먼트에 margin-top:-10px; 를 준 것입니다. 다만 주의하실 점은 원래 엘리먼트에 링크가 있을 경우에 아래 엘리먼트의 마진을 조정하여 원래 엘리먼트의 영역를 덮을 경우 링크가 적용되지 않는 현상이 발생할 수도 있습니다.


4. 인라인 태그와 블록 태그의 margin, padding 적용의 차이
표현을 위한 태그를 제외한 엘리먼트들은 보통 블록 속성을 가진 태그와 인라인 속성을 가진 태그가 존재합니다. 블록 속성 태그는 <div>로 대표되며 이와 비교되는 인라인 태그가 <span>태그입니다.
블록 속성 태그는 위 아래로 분리된 영역을 가지기 때문에 옆으로 별도의 콘텐츠를 배치할 수 없습니다. 하지만 인라인 속성 태그는 블록을 생성하지 않기 때문에 양 옆으로도 콘텐츠를 배치하는 것이 가능합니다.
인라인 태그들에 margin이나 padding 속성을 적용할 때에는 좌우 방향의 값은 적용되지만, 상하 값은 적용되지 않는 것을 유의하셔야 합니다.
CSS 속성 중 display 속성을 지정하여 원래의 인라인 태그나 블록 태그들도 역할을 서로 바꾸는 것이 가능하긴 하지만 display:inline; 등으로 강제적으로 인라인 속성으로 변경한 <div>엘리먼트도 역시 상하 방향의 마진과 패딩이 적용되지 않기 때문에 주의해주세요~


5. 테두리 넣기 (border속성)
경계선은 세가지 속성을 별도로 가지고 있습니다. 어떤 모양인지 보여줄 style과 두께를 말하는 width, 색상을 말하는 color 속성입니다. 이 속성이 상하좌우에 적용되어 border에 관련된 속성은 총 12개의 조합이 있을 수 있습니다. (물론 이와 별도로 구분되는 속성도 있습니다. border-collapse 같은...)
style의 경우 border-top-style, border-bottom-style, ... , border-style 속성이 있을 수 있는데 경계선의 모양을 결정합니다. 가장 많이 사용하는 실선의 경우 'solid'를 사용합니다. solid, dashed, dotted, double, groove, inset, outset, ridge 등의 속성이 존재합니다만 각각의 모양은 직접 만들어보세요~ (우리나라 특성상 화려한 그래픽을 자랑하는 국내 웹사이트 특성상 이 속성들을 다 사용할 일은 없을 것 같습니다만-_-) width는 말 그대로 두께를 말하고, color 역시 RGB코드 또는 색상명을 사용할 수 있습니다.
border-right:solid 2px red; 등으로 한 방향의 경계선 스타일을 간략하게 지정할 수도 있고 네 방향이 다 같을 경우 border:solid 2px red; 같은 식으로 더 간단하게 통합할 수 있습니다. 속성의 순서는 상관없이 사용할 수 있으며 생략할 수도 있지만, 생략할 경우에는 기본값으로 처리되게 되죠.


6. IE6 Quirks 모드 이하에서의 적용 이상
국내에서 가장 높은 점유율을 자랑하는 IE6의 경우, DTD를 별도로 지정하지 않고 Quirks모드로 돌릴 경우에는 박스 모델의 해석이 약간 틀려집니다. 또한 5.5 이하 버전에서는 상관없이 발생하는 현상인데요.
사용자 삽입 이미지
원래 width 속성으로 지정된 길이는 박스모델 내에서는 contents에 대해 적용되고 margin, border, padding과 별도로 적용되는 것이 맞습니다만, IE6의 Quirks모드와 IE5.5 버전 이하에서는 contents와 함께 padding, border 를 합한 것으로 계산하는 이슈가 있습니다.
이를 해결하기 위해서는 표준 모드로 동작할 수 있도록 정확한 DTD를 지정해주는 방법이 1차적인 대책입니다만 IE5.5 이하 버전에서는 이것도 적용되지 않기 때문에 컨디션 코드 또는 CSS 핵을 사용해주어야 합니다. 즉 IE구버전에만 적용되는 CSS핵을 사용하셔서 여기에만 적용되는 width를 직접 계산하셔서 넣어주셔야 하죠.
(참조 : http://www.456bereastreet.com/)


7. IE6 에서 float속성 적용된 div의 좌우 마진 두배 현상
이 현상은 박스 모델과는 크게 관련은 없지만, 레이아웃/콘텐츠 구성 시 div 엘리먼트의 마진을 조정하면서 이유없이 일어나는 버그이기 때문에 다루어 봅니다.
블록 속성의 엘리먼트에 float 속성을 주면 블록 속성을 유지하면서도 가로로 배열하는 것이 가능합니다. 이 경우가 레이아웃을 잡을 때 많이 사용하는 형태입니다만, IE6의 경우 float된 엘리먼트의 경우 가로 방향의 마진이 적용되는 경우 이 마진이 두배씩 적용되는 현상이 발생합니다. 이것은 위의 경우와는 달리 명백한 버그라고 할 수 있겠네요...
예를 들어 가로 500픽셀의 div 엘리먼트 내에 두개의 div엘리먼트를 float속성을 주어 배열하는 경우를 생각해보죠. 첫번째 엘리먼트는 100픽셀의 가로길이를 가지고 두번째 엘리먼트가 왼쪽 마진을 50px를 가지고 350px의 길이를 가지게 되면 100 + 50 + 350 = 500 의 식에 의해 정확히 맞아 떨어지게 되는 것이 이론상 맞지만..
<div style="width:500px;">
    <div style="float:left;width:100px;">
    LAYER1
    </div>
    <div style="float:left;margin-left:50px;width:350px;">
    LAYER2
    </div>
</div>
타 브라우저에서는 의도한 대로 정확히 보이지만, IE6의 경우 버그 때문에 마진이 두배가 되어 100px 의 마진이 적용되죠. 이것은 전체 길이 500px 를 넘어서게 되어 두번째 엘리먼트는 첫번째 엘리먼트의 다음 줄로 넘어가게 되죠.
이 버그를 해결하려면 float된 두개의 div 엘리먼트에 display:inline; 속성을 주어서 교정할 수 있습니다만, 이 속성은 인라인으로 바뀌는 것이 아니고 단순히 IE의 버그를 해결하기 위해서 존재합니다. 여전히 이 div엘리먼트의 속성은 블록 속성입니다.

Posted by 아마티

2007/10/16 18:47 2007/10/16 18:47
, , ,
Response
No Trackback , 7 Comments
RSS :
http://minicube.kr/blog/rss/response/65

CSS 핵

브라우저마다 HTML렌더링하는 방식이 조금씩 차이가 나고, 때로는 버그가 존재하는 관계로(망할 IE) 모든 CSS 코드가 모든 웹브라우저에서 똑같이 보이지 않습니다.
따라서 이러한 특성을 이용하여 특정 브라우저를 제외하거나, 특정 브라우저에서만 CSS를 적용하는 기법을 CSS 핵(Hack) 이라고 부르죠...

그래서 문법적으로 맞지 않거나, 특정 브라우저에만 적용되는 비표준인 경우가 많기 때문에 이러한 CSS핵은 어쩔 수 없는 경우가 아니면 사용하지 않아야 합니다. 또한, 단순히 눈앞의 문제만을 해결하기 위해 핵을 사용하면 나중에 페이지를 수정하거나 브라우저의 버전이 올라갈 때에 문제가 생기는 경우도 있구요.

CSS핵은 이런게 있다는 것도 알아두고, CSS핵을 사용하기 이전에 근본적으로 디자인을 수정하거나 다른 표준 태그로 해결하는게 좋을 듯 하네요.

어쨌든 일단 현존 CSS핵에 대한 정리!

http://centricle.com/ref/css/filters/

사용자 삽입 이미지


서핑하다 찾은 사이트인데 CENTRICLE.COM 의 CSS filters 페이지가 가장 잘 되어 있는 것 같습니다.
이제까지 알려진 CSS핵의 종류와 현존하는 거의 모든 웹 브라우저에서 적용되는지의 여부를 알기쉽게 표로 보여줍니다. 각 항목을 눌러보면 해당 핵의 예제도 볼 수 있네요.

http://www.communis.co.uk/dithered/css_filters/

사용자 삽입 이미지


웹표준 교과서에서 소개하는 CSS 핵 & 필터 안내 페이지

그 외에 평소에 자주 사용하는 팁으로서의 CSS 핵 정리는 아래에 정리.

Netscape 4 배제하기
<link rel="stylesheet" type="text/css" href="/css/style.css" media="all" />
Netscape 는 media 속성이 screen 이 아닌 경우 외부 스타일시트를 읽지 못하는 버그가 존재함.

Win IE 3~4, Mac IE 4~4.5, Netscape 4 배제하기
@import url("/css/style.css")
Win IE 4, Mac IE 4 는 인용부호가 "가 아니면 읽지 못하는 버그 존재. IE 3과 Netscape 4는 @import 지원하지 않음.

Mac IE 5 배제하기
H1 { /* \*/ color:red; /* */ }
Holly 핵이라 하며, 주석 안의 내용이 적용되지 않음.

Win IE 4~5 배제하기
H1/**/ { color:red; }
셀렉터 뒤에 /**/ 삽입.

Win IE 4~5, Mac IE 4.5~5 배제하기
H1 { color/* */:red; }
속성과 속성값을 구분하는 콜론(:) 앞에 /* */ 삽입.

Win IE 4~6, Mac IE 4, Netscape 4 배제하기
html>body H1 { color:red; }
셀렉터 앞에 html>body 삽입.

Win IE 6 제외시키기
H1 { color /**/:red; }
속성과 속성값을 구분하는 콜론(:) 앞에 스페이스와 /**/ 삽입.

언더스코어 핵 (_)
H1 { _color:red; }
Win IE 4~6 에 적용.

닷핵 (.)
H1 { .color:red; }
속성 앞에 . 삽입. Win IE 6~7 에만 적용. 타 브라우저는 정확히 확인하지 못했습니다.
이 핵에 대해선 계속 확인중인데 블로그스피어나 여타 서적에는 전혀 언급이 없는 이상한 핵(?)입니다.

해시 핵(#)
H1 { #color:red; }
속성 앞에 # 삽입. Win IE 4~6, Mac IE 5, Opera 7, Mozilla계열, Firefox 에 적용.

스타 핵
*HTML H1 { color:red; }
셀렉터 앞에 *html 삽입. Win IE 4~6, Mac IE 4~5 에 적용.

스타7 핵
HTML*H1 { color:red; }
셀렉터 앞에 html* 삽입(공백없이). Win IE 5.5~6, Mac IE 5, Safari 에 적용.

xmlns 속성 핵
HTML[xmlns] H1 { color:red; }
셀렉터 앞에 속성 선택자를 삽입. Mozilla, Firefox, Opera, Safari 등 속성 선택자를 지원하는 브라우저에 적용.

:root 가상클래스 핵
:root H1 { color:red; }
셀렉터 앞에 :root 가상클래스 삽입. Mozilla, Firefox, Mac IE 5, Safari 등 가상클래스를 지원하는 브라우저에 적용.

Tantek 박스모델 핵
H1 {
    width:500px;
    voice-family: ""}"";
    voice-family:inherit;
    width:400px;
}
Tantek Celik 이 고안한 유명한 박스모델 핵. Win IE 4~5, Mac IE 4, Netscape 4 에서는 voice-family 속성 이전의 스타일 적용. 그외의 브라우저는 뒤의 속성 적용.

단순 박스모델 핵
H1 {
    width:500px;
    w\idth:400px; //Win IE 6, Mac IE 5, Mozilla, Opera, Safari
    \width:450px; // only Win IE 5
}

속성의 첫번째, 두번째 글자 사이에 \를 삽입하면 Win IE 6, Mac IE 5, Mozilla, Opera, Safari 에 적용.
추가로 속성의 앞에 \를 삽입하면 Win IE 5 에만 적용.

IE 7, Opera 적용하기
*+html body H1 { color:red; }
셀렉터 앞에 *+html body 삽입. IE 7, Opera 8 이후 버전 적용. Opera를 배제한 IE7 전용으로 하고 싶을 때는 *+html>/**/body 로 Opera 전용 속성 기술.

IE 7 적용하기
*:first-child+html H1 { color:red; }
셀렉터 앞에 *:first-child+html 삽입. IE 7에만 적용되고, 이외의 브라우저는 앞에서 기술한 셀렉터의 속성 적용.

Win IE 5 패스필터
@media tty {
i{content:"";/*" "*/}}; @import '/css/style.css'; {;}/*";}
}/* */


Win IE 5.5 패스필터
@media tty {
i{content:"";/*" "*/}}@m; @import '/css/style.css';/*";}
}/* */


Win IE 6 패스필터(?)
<!--[if IE 6]><link rel="stylesheet" type="text/css" href="/css/style.css" media="all" /><![endif]-->

Win IE 7 패스필터(?)
<!--[if gte IE 7]><link rel="stylesheet" type="text/css" href="/css/style.css" media="all" /><![endif]-->

모던브라우저 패스필터 (Win IE 5.5 이하, Mac IE 5, Opera 8 이하, Netscape 4 이하 제외)
@import "null?"{";
@import "/css/style.css";
@import "null?"}";



저의 주 작업 브라우저는 IE6, IE7, FF2, OP9 입니다. 개인적으로 CSS 핵은 거의 사용하지 않지만, 폼 (특히 체크박스, 라디오 버튼) 의 형태가 각 브라우저마다 틀려서 IE 6~7 에서 폼의 마진을 조절하기 위해 언더스코어 핵, 닷핵 만을 사용하고 있습니다.
덧붙여... 우리나라에서 최고의 사용률을 보여주는 IE가 CSS Spec을 제대로 지원하지 않으면서도 이를 업데이트하지 않는 이유는, 아이러니컬하게도 브라우저간 버그를 보정하기 위한 CSS핵도 큰 이유를 차지하고 있는 듯.
IE 6에서 갑자기 IE 7 또는 표준스펙 풀 지원으로 CSS 지원 스펙을 수정하면 현재 IE 6 기준으로 만들어진 사이트나 IE 6용 패스필터, 핵을 사용한 엄청난 수의 사이트(특히 우리나라)는 어떻게 될지...

중요 포인트!!
1. 구조를 설계할 때 절대 CSS핵 위주로 설계하지 말 것.
2. 단발성 CSS 핵보다는 패스필터 사용 권장.
3. CSS핵은 어쩔 수 없는 경우에만 사용할 것.

Posted by 아마티

2007/08/16 15:21 2007/08/16 15:21
, , ,
Response
No Trackback , No Comment
RSS :
http://minicube.kr/blog/rss/response/42


블로그 이미지

Professional front-end UI Developer.

- 아마티

Notices

Archives

Authors

  1. 아마티

Calendar

«   2012/02   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29      

Site Stats

Total hits:
212473
Today:
82
Yesterday:
69