블록의 top 및 bottom 마진은 때로는 (결합되는 마진 중 크기가) 가장 큰 한 마진으로 결합(combine, 상쇄(collapsed)) 됩니다, 마진 상쇄(margin collapsing)로 알려진 행동
마진 상쇄는 요소들이 세로로 배치되어 있을 경우에 발생한다. 마진 상쇄
이미지를 보면 요소 A의 margin-bottom: 10px
이고 요소 B의 margin-top: 30px
이다. 요소 B의 마진이 요소 A의 마진보다 값이 크다.
이렇게 위아래로 겹쳐진 요소 간의 top과 bottom의 마진이 모두 존재할 때 더 큰 값만 적용되고 작은 값은 무시된다. 이 현상을 상쇄된다고 표현한다.
그래서 결과물은 이미지의 화살표 오른쪽처럼 30px만 적용되는 것이다.
만약 50px, 20px
가 아니라 30px, 30px
라면 하나만 렌더링 된다.
좌우 여백은 해당되지 않는다.
국어사전을 보면 상쇄된다는 말은 효과가 없어지는 것을 말한다.
마진의 효과는 화면에 렌더링 되는 것이니까 상쇄된 더 작은 마진은 화면에 나타나지 않는다. 하지만 지정된 값 자체가 없어지는 것은 아니다.
<h1>Heading 1</h1>
<h2>Heading 2</h2>
h1 {
margin: 0 0 50px 0;
background-color: red;
}
h2 {
margin: 20px 0 0 0;
background-color: blue;
}
위 이미지는 파란색 요소의 margin-top:20px
가 상쇄된 상태다. 현재 사이 여백은 50px이다.
보면 빨간색 요소의 margin-bottom
이 마진 여백(주황색 부분)을 다 채우는 것을 확인할 수 있다.
그런데 파란색 요소를 확인하면 margin-top
영역이 존재한다. 여백이 상쇄된 것이지 없어진 것이 아니다.
위에서 예시로 든 상황이 바로 이 상황이다.
빈 요소
- 높이(height)가 0인 상태의 블록 요소
- 요소의 크기가 상하로 늘어나는 프로퍼티 값이 없을 때
- height
- min-height / max-height
- padding
- border 등
- 내부에 inline 콘텐츠가 존재하지 않는 요소
빈 요소의 경우 위와 아래를 가르는 경계가 없다는 말이 이해가 안 가서 그림을 만들어봤다.
이렇게 빈 요소의 경우는 위아래를 구분할 수 없어서 자신의 margin-top
, margin-bottom
을 비교하고 마진 상쇄가 발생한다.
빈 요소가 사용되는 경우
- 빠른 레이아웃 구성을 위해 div로 영역을 만들어 놓을 경우
- 내부에 요소를 append 하기 위해 빈 컨테이너를 만들어 놓을 경우 등
(height, padding, border 등 높이와 관련된 속성들은 상위로부터 상속되지 않는다.)
부모 박스와 첫 번째 자식의 margin-top, 마지막 자식의 margin-bottom이 겹칠 때 발생한다.
* {
margin: 0;
padding: 0;
}
body {
background-color: #eee;
padding: 0 30px;
}
.parent {
background-color: green;
margin: 30px 0;
}
.red {
width: 300px;
height: 100px;
background-color: red;
margin-top: 20px;
}
.blue {
width: 300px;
height: 100px;
background-color: blue;
margin-bottom: 20px;
}
<div class="parent">
<div class="red">red</div>
<div class="blue">blue</div>
</div>
예제를 만들어봤다.
margin: 30px 0
margin-top: 20px
margin-bottom: 20px
개발자 도구로 확인해 보면,
parent인 초록색 박스의 margin:30px 0
이 적용되어 있다. 각 주황색 부분이 30px이다.
빨간색 박스의 margin-top:20px
도 여전히 존재한다. 상쇄되어 렌더링 되지 않을 뿐이다.
파란색 박스의 margin-bottom: 20px
도 여전히 존재한다. 상쇄되어 렌더링 되지 않을 뿐이다.
이 경우 자식 요소의 마진 값이 살아남더라도 부모 요소에 마진이 적용된 것처럼 보이게 된다.
마진이란 콘텐츠 간의 간격이고, 간격을 벌리기 위해서는 경계를 필요로 합니다. 브라우저는 부모 박스와 첫 번째(마지막) 자식 박스 간의 경계를 그 사이에 있는 border / padding / inline 콘텐츠 유무로 판단합니다. 앞에 설명했던 빈 박스의 마진 상쇄 현상과는 조금 다르게, 이미 명시적으로 height / min-height 값을 줬더라도 이번 경우에선 신경 쓰지 않습니다. [CSS 마진 상쇄(Margin-collapsing) 원리 완벽 이해]
케이스를 나눠보니 경계를 인식할 수 있냐가 마진 상쇄가 발생하는 기준인 것 같다.
경계를 만들어 주는 것이 해결법이라고 하는데 padding을 주거나, border를 주거나, 사이에 인라인 요소를 삽입하거나 하는 해결법이 존재한다.