CSS 박스 모델과 box-sizing 속성
웹페이지 상의 모든 엘리먼트는 하나의 박스의 개념으로 모델링 할 수 있습니다. 이 박스 모델이라고 불리는 컨셉은 CSS의 근간이 되기 때문에 반드시 이해하고 있어야 합니다.
Box Model 이란?
우리가 웹페이지에 배치하는 모든 HTML 엘리먼트는 3개의 층을 가진 사각형 구조의 형태를 띠고 있습니다.
가장 외곽의 층을 margin
영역이라고 부르는데, 보통 주변에 위치한 다른 엘리먼트와의 상하좌우 간격을 두기 위해서 쓰입니다.
그 바로 아래 층을 border
영역이라고 부르는데, 경계선을 그리기 위해서 쓰이며, margin
과 padding
과 달리 두께 뿐만 아니라 색상과 모양까지 지정할 수 있습니다.
그 바로 아래 층은 padding
영역이라고 불리는데, 컨텐츠와 경계선 사이의 간격을 지정하기 위해서 쓰입니다.
마지막으로 가장 중간에 있는 영역은 content
영역이라고 하며, 컨텐츠의 width
(너비)와 height
(높이)를 지정해줄 수 있습니다.
예를 들어, 15px
두께의 margin
과 5px
두께의 bordr
그리고 20px
두께의 padding
을 가진 엘리먼트는 다음과 같이 만들 수 있습니다.
<div class="container">
MARGIN
<div class="box">CONTENT</div>
</div>
.container {
background-color: orange;
width: 400px;
border: 1px solid red;
}
.box {
color: white;
background-color: green;
width: 200px;
height: 30px;
padding: 20px;
border: 5px dashed black;
margin: 15px;
}
실제 너비감 결정
많은 분들이 박스 모델에서 가장 혼선을 겪는 부분이 바로 엘리먼트의 너비가 어떻게 결정이 되느냐 입니다.
예를 들어, 위 예제에서 .container
엘리먼트의 width
는 400px
이고 .box
엘리먼트의 width
는 200px
입니다.
그런데 얼핏봐도 초록색 영역이 오렌지색 영역의 절반 이상을 차지하고 있다는 것을 알 수 있습니다.
이는 박스 모델에서 width
속성은 순수하게 content
영역의 너비만을 포함하기 때문입니다.
따라서 실제 엘리먼트가 화면에서 차지하는 너비를 생각할 때는 padding
과 border
의 두께까지 고려해야합니다.
위 예제의 경우, 초록색 영역의 너비는 실제 content
영역의 너비에 좌우 padding
값과 좌우 border
값을 더한 250px
이 됩니다.
200px + (20px * 2) + (5px * 2) = 250px
동일한 방식으로, .container
엘리먼트가 화면에서 자치하는 너비는 402px
이 됩니다.
400px + (0px * 2) + (1px * 2) = 402px
이러한 CSS의 박스 모델의 디폴트 동작 방식이 웹페이지의 레이아웃을 잡을 때는 매우 불편하게 느껴질 수 있습니다. 왜냐하면, 부모 엘리멘트 안에 자식 엘리먼트를 빈틈없이 배치하려면 위와 같은 계산을 직접해줘야 하기 때문입니다.
예를 들어, .box
엘리먼트를 .container
엘리먼트 속에 딱 맞게 배치하려면 width
값을 몇으로 해줘야할까요?
우선, .box
엘리먼트의 margin
속성값을 0
으로 설정하여, .container
엘리먼트와의 간격을 제거해야줘야 합니다.
그 다음, .container
엘리먼트의 가용 너비에서 좌우 padding
값과 좌우 border
값을 빼줘야 합니다.
400px - (20px * 2) - (5px * 2) = 350px
자, 이제 .box
엘리먼트의 width
속성값을 350px
로 수정해주면 다음과 같이 두 엘리먼트가 빈틈없이 배치됩니다.
.box {
margin: 0;
width: 350px;
/* 나머지 동일 */
}
반응형 레이아웃에서는 px
과 같은 절대 단위 대신에 %
와 같은 상대 단위를 사용하기 때문에 이 문제가 더욱 심각해질 수 있습니다.
지금까지 계산한 width
속상값을 다시 %
로 환산해야된다고 생각해보세요…
그리고 상위 컨테이너의 width
속성값 마저도 px
이 아닌 %
로 정의되어 있다고 상상해보세요…
box-sizing
CSS 박스 모델의 이러한 불편한 부분은 box-sizing
속성을 이용하면 해결을 할 수 있습니다.
box-sizing
속성의 기본값은 content-box
인데, 위에서 설명드린 것 처럼 width
속성값은 순수하게 content
영역의 너비만을 포함합니다.
하지만 box-sizing
속성값을 border-box
로 변경해주면, width
속성값은 content
영역뿐만 아니라 padding
과 border
까지 포함시키게 됩니다.
따라서 .box
컨테이너의 width
속성을 .container
컨테이너의 width
속성값과 동일한 400px
로 설정하면, .box
컨테이너가 .container
컨테이너 안으로 딱 맞게 들어가게 됩니다.
그리고 실제 content
영역의 너비는 400px
에서 좌우 padding
과 좌우 border
두께를 뺀 350px
로 자동 계산됩니다.
400px - (20px * 2) - (5px * 2) = 350px
반응형 레이아웃에서 적합하도록 절대 길이인 400px
대신에 상대 길이인 100%
로 바꿔줄 수도 있습니다.
만약에, box-sizing
속성이 content-box
로 설정된 상황에서 100%
로 설정해줬다면 .box
컨테이너의 너비가 .container
컨테이너를 초과하여 밖으로 삐져나왔을 것입니다.
왜냐하면 %
단위는 부모 엘리먼트의 너비를 기준으로 하는데, 그럼 content
영역의 너비만 400px
이 되고, 여기에 padding
과 border
를 감안하면 450px
이 되기 때문입니다.
box-sizing
속성은 width
속성 뿐만 아니라 height
속성에도 동일한 영향을 줍니다.
height
속성값이 30px
이었는데, 여기서 상하 padding
과 상하 border
두께를 빼면 -10px
이 됩니다.
30px - (20px * 2) - (5px * 2) = -10px (?)
높이에는 음수 개념이 없기 때문에, content
영역의 높이는 0
으로 취급되고, 아래 부분 padding
이 짤리는 현상이 발생하게 됩니다.
따라서 height
속성값을 적당히 늘려줘야 하는데, 80px
로 늘려주면 content
영역을 위한 가용 높이를 30px
이 확보되어 이 전과 동일한 높이감을 가질 수 있습니다.
80px - (20px * 2) - (5px * 2) = 30x (!)
.box {
box-sizing: border-box;
width: 400px; /* 100% */
height: 80px;
/* 나머지 동일 */
}
기존에 직접 계산해야했던 content
영역의 너비와 높이를 자동으로 처리해주기 때문에 레이아웃이 많이 편해졌습니다.
실제 웹 프로젝트에서는 다음과 같이 전체 선택자로 아예 box-sizing
속성의 기본값을 바꾸는 경우도 어렵지 않게 볼 수 있습니다.
*,
*::before,
*::after {
box-sizing: border-box;
}
마치면서
지금까지 CSS에서 박스 모델의 개념과 box-sizing
속성을 이용해서 좀 더 편하게 레이아웃을 하는 방법에 대해서 간단히 알아보았습니다.
대부분 브라우저의 개발자 도구는 이 박스 모델의 각 층 별로 CSS 속성값들이 어떻게 설정/계산되었는지를 시각적으로 보여줍니다.
따라서 그냥 웹페이지만 눈으로만 보시지 마시고, 개발자 도구를 통해 박스 모델을 정밀하게 분석해보시면 큰 도움이 되실 겁니다.