복수의 마진이 겹칠 때 상쇄되는 현상이다. MDN에서는 다음과 같이 설명하고 있다.
여러 블록의 위쪽 및 아래쪽 바깥 여백(마진)은 경우에 따라 제일 큰 여백의 크기를 가진 단일 여백으로 결합(상쇄)되곤 합니다. 이런 동작을 여백 상쇄라고 부릅니다.
MDN 문서에서는 언급하고 있지 않지만, 마진 상쇄는 "수직" 방향으로만 적용된다. 즉, block 요소 사이에서만 일어나는 현상이다.
기본적으로 마진 상쇄는 세 가지 상황에서 발생한다.
형제 요소간의 마진 상쇄는 이해하기 쉽다!
박스 두 개의 상하 간격이 200px이 아니라 100px인 것을 확인할 수 있다.
부모 요소와 자식 요소는 직관적으로 이해하기가 어려웠다.
검정색 박스가 20px 아래로 이동하고, 파란색 박스는 검정색 박스 안에서 100px 아래로 이동할 것이라고 생각했다.
하지만, 검정색 박스만 100px 이동했다.
MDN 문서에서 조금 어렵지만 다음과 같이 설명하고 있다.
부모 블록에 테두리, 안쪽 여백, 인라인 부분이 없고 블록 서식 맥락이 생성되지 않았으며 부모의 margin-top을 자손의 margin-top과 분리할 권한이 없는 경우, 또는, 부모 블록에 테두리, 안쪽 여백, 인라인 콘텐츠가 없으며 부모의 margin-bottom과 자손의 margin-bottom을 분리할 height, min-height, max-height가 존재하지 않는 경우 부모와 자손의 여백이 상쇄됩니다. 상쇄된 여백은 부모 블록 바깥에 위치합니다.
즉, 부모와 자식간에 margin을 구분하는 경계가 없을 때 발생한다는 것이다.
예시에서 부모 요소에 border를 추가하면, 직관적으로 생각할 수 있는 레이아웃이 완성된다.
무엇이든 부모 요소와 자식 요소간에 있다면 마진 상쇄가 발생하지 않는다.
패딩을 추가하거나, 인라인 요소를 추가해서 마진 상쇄를 막을 수 있다.
주의할 점은, 상쇄된 여백이 부모 블록 바깥에 위치한다는 것이다.
비어있는 요소는 이해하기 쉽다. 요소의 margin-top과 margin-bottom 서로 상쇄된다.
margin-top이 100px, margin-bottom이 50px이지만 100px만 적용되었다.