CSS 박스 모델: 웹 요소 레이아웃의 핵심 이해

CSS 박스 모델은 웹 페이지의 모든 HTML 요소를 사각형 상자로 간주하며, 이 상자가 콘텐츠, 안쪽 여백(padding), 테두리(border), 바깥 여백(margin)을 처리하는 방식을 정의합니다. 각 요소는 이 박스 모델에 따라 화면에 배치되고 공간을 차지하게 됩니다.

CSS 박스 모델 구성 요소

각 요소의 가장 안쪽에는 실제 콘텐츠(content)가 위치합니다. 이 콘텐츠 영역을 직접 감싸는 것이 안쪽 여백(padding)입니다. 안쪽 여백은 요소의 배경색이나 배경 이미지가 적용되는 영역이기도 합니다. 안쪽 여백의 바깥쪽 경계는 테두리(border)입니다. 마지막으로 테두리 밖에 위치하는 것이 바깥 여백(margin)으로, 기본적으로 투명하여 뒤에 있는 다른 요소를 가리지 않습니다.

안쪽 여백, 테두리, 바깥 여백은 모두 선택 사항이며, 기본값은 0입니다. 하지만 대부분의 브라우저는 사용자 에이전트 스타일시트를 통해 특정 요소에 기본 바깥 여백과 안쪽 여백을 설정합니다. 이러한 브라우저 기본 스타일을 재정의하려면 요소의 marginpadding을 명시적으로 0으로 설정하면 됩니다. 개별적으로 설정할 수도 있고, 모든 요소에 적용하려면 다음과 같이 범용 선택자를 사용할 수 있습니다:

* {
  margin: 0;
  padding: 0;
}

CSS에서 widthheight 속성은 오직 콘텐츠 영역의 너비와 높이만을 지칭합니다. 안쪽 여백, 테두리, 바깥 여백을 추가해도 콘텐츠 영역의 크기 자체는 변하지 않지만, 요소가 차지하는 전체 공간 즉, 박스 모델의 총 크기는 증가합니다.

예를 들어, 요소의 각 변에 10px의 바깥 여백과 5px의 안쪽 여백이 있다고 가정해 봅시다. 이 요소의 전체 너비를 100px로 만들고 싶다면, 콘텐츠의 너비는 70px로 설정해야 합니다. 계산은 다음과 같습니다: 10px (왼쪽 margin) + 5px (왼쪽 padding) + 70px (content) + 5px (오른쪽 padding) + 10px (오른쪽 margin) = 100px.

.sample-container {
  width: 70px; /* 콘텐츠 너비 */
  margin: 10px; /* 바깥 여백 */
  padding: 5px; /* 안쪽 여백 */
  border: 1px solid black; /* 예시 테두리 */
}

안쪽 여백, 테두리, 바깥 여백은 요소의 모든 변에 일괄적으로 적용하거나, 각 변에 개별적으로 적용할 수 있습니다. 특히 바깥 여백은 음수 값을 가질 수 있으며, 특정 레이아웃 조정 시 유용하게 활용되기도 합니다.

CSS 안쪽 여백 (Padding)

안쪽 여백은 요소의 테두리와 콘텐츠 영역 사이에 존재하는 공간입니다. 이 공간을 제어하는 가장 기본적인 속성은 padding입니다.

padding 속성은 요소의 안쪽 여백을 정의하며, 길이 값(예: px, em, rem)이나 백분율 값을 사용할 수 있습니다. 음수 값은 허용되지 않습니다.

예를 들어, 모든 <h1> 요소의 모든 변에 15픽셀의 안쪽 여백을 부여하고 싶다면:

h1 {
  padding: 15px;
}

padding 속성은 시계 방향 순서로 상단, 오른쪽, 하단, 왼쪽 안쪽 여백을 한 번에 설정할 수 있습니다. 각 변에 다른 단위나 백분율 값을 지정하는 것도 가능합니다:

.card {
  padding: 10px 0.5em 20px 15%; /* 상, 우, 하, 좌 순서 */
}

개별 안쪽 여백 속성

요소의 상단, 오른쪽, 하단, 왼쪽 안쪽 여백을 각각 설정하려면 다음 네 가지 개별 속성을 사용합니다:

  • padding-top
  • padding-right
  • padding-bottom
  • padding-left

위에서 사용한 약식 속성과 동일한 효과를 내려면 다음과 같이 작성할 수 있습니다:

.card {
  padding-top: 10px;
  padding-right: 0.5em;
  padding-bottom: 20px;
  padding-left: 15%;
}

안쪽 여백의 백분율 값

안쪽 여백에 백분율 값을 설정할 수 있습니다. 이 백분율은 요소의 부모 요소 width에 상대적으로 계산됩니다. 따라서 부모 요소의 너비가 변경되면 안쪽 여백의 크기도 함께 변합니다.

예를 들어, 다음 규칙은 단락의 안쪽 여백을 부모 요소 너비의 8%로 설정합니다:

p {
  padding: 8%;
}

흥미로운 점은 상단 및 하단 안쪽 여백의 백분율도 부모 요소의 높이가 아닌 너비에 상대적으로 계산된다는 것입니다.

CSS 테두리 (Border)

요소의 테두리는 콘텐츠와 안쪽 여백 주변을 감싸는 하나 이상의 선입니다. CSS border 속성을 사용하면 테두리의 스타일, 두께, 색상을 정의할 수 있습니다.

테두리 정의

CSS 테두리 속성을 사용하면 어떤 HTML 요소에도 시각적으로 멋진 테두리를 적용할 수 있습니다. 각 테두리는 세 가지 주요 속성으로 구성됩니다: 두께(width), 스타일(style), 색상(color).

테두리와 배경

CSS 명세는 테두리가 "요소의 배경 위에" 그려진다고 명시합니다. 이는 점선이나 파선과 같은 테두리 스타일의 경우, 테두리의 보이는 부분 사이에 요소의 배경이 나타나야 함을 의미합니다.

초기 CSS2에서는 배경이 안쪽 여백까지만 확장된다고 정의했으나, CSS2.1에서 이 부분이 수정되어 요소의 배경은 콘텐츠, 안쪽 여백, 그리고 테두리 영역 전체에 걸쳐 적용됩니다. 대부분의 최신 브라우저는 CSS2.1의 정의를 따릅니다.

테두리 스타일 (Border Style)

스타일은 테두리에서 가장 중요한 측면입니다. 스타일이 지정되지 않으면 테두리는 나타나지 않기 때문입니다. border-style 속성은 none을 포함하여 10가지 이상의 다양한 테두리 스타일을 정의합니다:

  • none: 테두리 없음 (기본값)
  • hidden: none과 유사하지만, 테이블의 경우 충돌을 해결할 때 none보다 우선순위가 높음
  • solid: 단색 실선
  • dotted: 점선
  • dashed: 파선
  • double: 이중 실선
  • groove: 3D 오목한 효과
  • ridge: 3D 볼록한 효과
  • inset: 3D 안으로 들어간 효과
  • outset: 3D 밖으로 튀어나온 효과

예를 들어, 이미지를 포함하는 링크에 outset 스타일을 적용하여 "볼록한 버튼"처럼 보이게 할 수 있습니다:

a img {
  border-style: outset;
}

다양한 스타일 정의

border-style 속성에 여러 값을 지정하여 각 변에 다른 스타일을 적용할 수 있습니다. 값의 순서는 시계 방향으로 상단, 오른쪽, 하단, 왼쪽입니다:

.custom-panel {
  border-style: solid dotted dashed double; /* 상: solid, 우: dotted, 하: dashed, 좌: double */
}

개별 변 스타일 정의

요소의 특정 변에만 테두리 스타일을 설정하려면 다음 개별 속성을 사용합니다:

  • border-top-style
  • border-right-style
  • border-bottom-style
  • border-left-style

다음 두 규칙은 동일한 결과를 만듭니다:

p {
  border-style: solid solid solid none;
}
/* 또는 */
p {
  border-style: solid;
  border-left-style: none; /* 이 코드는 위 코드 이후에 와야 함 */
}

참고: 약식 속성(border-style)과 개별 속성을 함께 사용할 때는 개별 속성을 약식 속성 뒤에 배치해야 합니다. 그렇지 않으면 약식 속성의 값이 개별 속성 값을 덮어쓸 수 있습니다.

테두리 두께 (Border Width)

border-width 속성을 통해 테두리의 두께를 지정할 수 있습니다. 두께는 px, em과 같은 길이 값으로 지정하거나, thin, medium (기본값), thick 세 가지 키워드 중 하나를 사용할 수 있습니다.

예를 들어, 단락 요소에 두꺼운 실선 테두리를 적용하려면:

p {
  border-style: solid;
  border-width: thick;
}

키워드의 실제 두께는 CSS 명세에 정의되어 있지 않으므로, 브라우저마다 다르게 렌더링될 수 있습니다.

개별 변 두께 정의

border-width 속성에도 시계 방향으로 상단, 오른쪽, 하단, 왼쪽 테두리의 두께를 지정할 수 있습니다:

p {
  border-style: solid;
  border-width: 15px 5px; /* 상/하: 15px, 좌/우: 5px (값 복사 규칙) */
}

다음 개별 속성들을 사용하여 각 변의 두께를 설정할 수도 있습니다:

  • border-top-width
  • border-right-width
  • border-bottom-width
  • border-left-width

테두리가 없는 경우

테두리가 표시되려면 반드시 solidoutset과 같은 border-style을 선언해야 합니다. border-style의 기본값은 none이기 때문에, 스타일을 명시하지 않으면 테두리 두께를 아무리 크게 설정해도 테두리는 보이지 않으며 실제 두께는 0으로 처리됩니다.

h3 {
  border-width: 10px; /* border-style이 'none'이므로 테두리는 표시되지 않음 */
}

테두리가 나타나게 하려면 반드시 테두리 스타일을 선언해야 합니다.

테두리 색상 (Border Color)

border-color 속성을 사용하여 테두리 색상을 설정할 수 있습니다. 명명된 색상, 16진수 값, RGB/HSL 값 등 모든 유형의 색상 값을 사용할 수 있습니다. 최대 네 개의 색상 값을 지정할 수 있으며, 상단, 오른쪽, 하단, 왼쪽 순서로 적용됩니다.

.widget-box {
  border-style: solid;
  border-color: #ff0000 green blue yellow; /* 상: 빨강, 우: 초록, 하: 파랑, 좌: 노랑 */
}

색상 값이 4개 미만이면 값 복사 규칙이 적용됩니다. 예를 들어, 두 개의 값만 지정하면 첫 번째 값은 상단과 하단에, 두 번째 값은 왼쪽과 오른쪽에 적용됩니다.

p {
  border-style: solid;
  border-color: blue red; /* 상/하: 파랑, 좌/우: 빨강 */
}

테두리 색상을 명시적으로 선언하지 않으면, 해당 요소의 color 속성(텍스트 색상)을 상속받습니다.

개별 변 색상 정의

다음 개별 속성들을 사용하여 각 변의 테두리 색상을 설정할 수 있습니다:

  • border-top-color
  • border-right-color
  • border-bottom-color
  • border-left-color

<h1> 요소에 검은색 실선 테두리를 지정하되, 오른쪽 테두리만 빨간색으로 만들려면:

h1 {
  border-style: solid;
  border-color: black;
  border-right-color: red; /* 오른쪽만 빨간색으로 재정의 */
}

투명 테두리 (Transparent Border)

CSS2에서는 transparent라는 테두리 색상 값을 도입했습니다. 이 값은 두께는 있지만 보이지 않는 테두리를 만드는 데 사용됩니다. 이는 마치 추가적인 안쪽 여백처럼 작동하면서도 필요할 때 테두리를 보이게 할 수 있는 장점이 있습니다.

다음은 링크에 transparent 테두리를 적용한 예시입니다:

<a href="#">링크 1</a>
<a href="#">링크 2</a>
a {
  border-style: solid;
  border-width: 5px;
  border-color: transparent; /* 초기에는 보이지 않음 */
  display: inline-block; /* 너비/높이, 패딩/마진 적용을 위해 */
  padding: 5px;
  margin: 5px;
}
a:hover {
  border-color: gray; /* 호버 시 테두리 색상 변경 */
}

이 투명 테두리는 요소의 배경이 테두리 영역까지 확장되므로, 시각적으로는 안쪽 여백과 유사하게 동작합니다.

CSS 바깥 여백 (Margin)

요소의 테두리 바깥에 있는 공백 영역을 바깥 여백(margin)이라고 합니다. 바깥 여백을 설정하면 요소 주위에 추가적인 "빈 공간"이 생성됩니다.

바깥 여백을 설정하는 가장 간단한 방법은 margin 속성을 사용하는 것입니다. 이 속성은 길이 값, 백분율 값, 그리고 음수 값까지 허용합니다. 또한 auto 키워드를 사용하여 요소를 가로로 중앙 정렬할 수도 있습니다.

다음 선언은 <section> 요소의 모든 변에 1rem의 바깥 여백을 설정합니다:

section {
  margin: 1rem;
}

margin 속성에도 안쪽 여백과 마찬가지로 시계 방향으로 상단, 오른쪽, 하단, 왼쪽 바깥 여백을 순서대로 지정할 수 있습니다:

.content-block {
  margin: 12px 0 18px 6px; /* 상: 12px, 우: 0, 하: 18px, 좌: 6px */
}

바깥 여백의 백분율 값 또한 부모 요소의 width에 상대적으로 계산됩니다. 예를 들어, 다음 규칙은 단락의 바깥 여백을 부모 요소 너비의 5%로 설정합니다:

.responsive-div {
  margin: 5%;
}

margin의 기본값은 0이지만, 브라우저는 <p>, <h1> 등의 많은 요소에 기본 바깥 여백을 적용합니다. 이 기본 스타일은 명시적으로 margin을 선언하여 재정의할 수 있습니다.

값 복사 규칙

margin 속성에 값을 4개 미만으로 지정할 경우, CSS는 다음과 같은 값 복사 규칙을 적용합니다:

  • 세 개의 값: 상단, 오른쪽, 하단 값을 지정하면, 왼쪽 값은 오른쪽 값과 동일하게 적용됩니다.
    h1 { margin: 10px 20px 15px; } /* 상:10px, 우:20px, 하:15px, 좌:20px */
  • 두 개의 값: 상단, 오른쪽 값을 지정하면, 하단 값은 상단 값과 동일하고, 왼쪽 값은 오른쪽 값과 동일하게 적용됩니다.
    h2 { margin: 1em 2em; } /* 상:1em, 우:2em, 하:1em, 좌:2em */
  • 하나의 값: 모든 네 변의 바깥 여백이 해당 값과 동일하게 적용됩니다.
    p { margin: 5px; } /* 상, 우, 하, 좌 모두 5px */

이 규칙 덕분에 필요한 최소한의 값만 지정하여 스타일을 간결하게 유지할 수 있습니다. 그러나 특정 조합의 바깥 여백을 적용해야 할 때는 모든 4개의 값을 명시해야 할 수도 있습니다.

.custom-spacing {
  margin: 20px 30px 30px 20px; /* 상:20px, 우:30px, 하:30px, 좌:20px */
}

개별 바깥 여백 속성

요소의 특정 변에만 바깥 여백을 설정하려면 다음 개별 속성들을 사용할 수 있습니다:

  • margin-top
  • margin-right
  • margin-bottom
  • margin-left

예를 들어, <aside> 요소의 왼쪽 바깥 여백만 25px로 설정하려면:

aside {
  margin-left: 25px;
}

여러 개의 개별 속성을 한 규칙에 함께 사용할 수도 있습니다:

.section-header {
  margin-top: 15px;
  margin-right: 25px;
  margin-bottom: 25px;
  margin-left: 15px;
}

이 경우, 약식 margin: 15px 25px 25px 15px;을 사용하는 것이 더 간결할 수 있습니다. 어떤 방법을 사용하든 결과는 동일하므로, 개발자가 더 쉽고 편리하다고 느끼는 방법을 선택하면 됩니다.

CSS 바깥 여백 병합 (Margin Collapsing)

바깥 여백 병합(Margin Collapsing)은 두 개 이상의 수직 바깥 여백이 만날 때 하나의 바깥 여백으로 합쳐지는 현상을 말합니다. 병합된 바깥 여백의 높이는 병합에 참여한 바깥 여백 중 가장 큰 값으로 결정됩니다.

바깥 여백 병합 시나리오

바깥 여백 병합은 웹 페이지 레이아웃에서 혼란을 야기할 수 있지만, 몇 가지 규칙을 이해하면 예측 가능합니다.

  • 인접한 형제 요소: 한 요소의 하단 바깥 여백이 바로 뒤따르는 요소의 상단 바깥 여백과 만날 때 병합됩니다. 예를 들어, 한 단락의 margin-bottom과 다음 단락의 margin-top이 병합되어 둘 중 더 큰 하나의 바깥 여백만 존재하게 됩니다.
  • 부모-자식 요소: 부모 요소 안에 자식 요소가 포함되어 있고, 부모와 자식 사이에 안쪽 여백이나 테두리가 없어 바깥 여백을 분리하지 못하는 경우, 부모의 상단/하단 바깥 여백과 자식의 상단/하단 바깥 여백이 병합될 수 있습니다.
  • 빈 요소: 바깥 여백은 있지만 테두리나 안쪽 여백이 없는 빈 요소의 경우, 해당 요소의 상단 바깥 여백과 하단 바깥 여백이 서로 병합될 수 있습니다. 이 병합된 바깥 여백은 다시 다른 요소의 바깥 여백과 병합될 수 있습니다.

바깥 여백 병합은 기본적으로 수직 공간을 보다 일관성 있게 유지하려는 CSS의 설계 의도입니다. 예를 들어, 여러 단락으로 구성된 일반적인 텍스트 페이지에서 각 단락 사이의 공간은 단락의 margin-topmargin-bottom의 합이 아닌, 병합된 하나의 값으로 유지됩니다. 이는 페이지 전체적으로 균일한 단락 간격을 제공합니다.

참고: 바깥 여백 병합은 오직 일반 문서 흐름(normal document flow) 내에 있는 블록 레벨 요소의 수직 바깥 여백에서만 발생합니다. 인라인 요소, 플로팅된 요소, 절대 위치 지정된 요소, Flexbox 또는 Grid 아이템의 바깥 여백은 병합되지 않습니다.

태그: CSS Box Model Padding Border Margin

7월 3일 05:13에 게시됨