CSS 마진 상쇄(Margin-collapsing) 원리 완벽 이해
- 그냥 이 글을 다시 한번 정리한 글이다. 이 글이 찾아본 글 중에 가장 깔끔해서 뭘 더 추가할 필요가 없을 듯. 위의 글이 더 잘 정리되어있으니 위에 것 볼 것. 그냥 나는 내가 공부하려고 대충 글로 끄적인거니 위에 글을 볼 것을 무조건 추천함. 그냥 똑같이 따라한 글이니 위의 글 볼 것.
마진 상쇄란 무엇인가?

- margin 겹침 현상이라고도 부르지만 원리적으로는 상쇄가 일어나는 것이기에 마진 상쇄가 맞다고 한다.
- 어떤 두 개 이상의 블록 요소의 위아래 마진이 겹칠 때 어느 한 쪽의 값만 적용하는 브라우저의 렌더링 규칙이다.
마진 상쇄가 일어나는 3가지 상황
1. 인적 형제 박스 간 상하 마진이 겹칠 때
- 겹친 두 마진을 비교해서 더 큰 마진으로 상쇄해서 렌더링 한다. 겹친 두 값이 같으면 중복을상쇄해 렌더링한다.(그냥 하나만 나오게 된다.)
2. 빈 요소의 상하 마진이 겹칠 때

- 빈 요소란 무엇인가? - 높이가 0인 상태의 블록 요소
- height / min-height / padding / border 등 상하로 늘어나는 프로퍼티 값을 명시적으로 부여 안한 경우
- 내부에 Inline 콘텐츠가 존재하지 않는 경우
- 위의 경우에는 위와 아래를 가르는 경계가 없으므로 위쪽 margin과 아래쪽 margin 중 큰 값으로 지정된다. 같으면 같은걸로 지정된다.
- 빈 요소는 안 만들고 싶어도 어쩌다 보니 만들어지게 된다.
- 빠른 레이아웃 구성을 위해 div로 영역을 만들 경우
- 내부에 요소를 append 하기 위해 빈 컨테이너를 만든 경우 등
- height, padding, border 등 높이와 관련된 속성은 상속되지 않기에 생기는 문제이다.
3. 부모 박스와 첫번째(마지막) 박스의 상단(하단)마진이 겹치는 경우
- 마진이란 콘텐츠 간의 간격이고, 간격을 벌리기 위해서는 경계가 필요하다.
- 브라우저는 부모 박스와 첫번째(마지막) 박스 간의 경계를 사이에 있는 border/padding/inline 콘텐츠 유무로 판단한다.
- 이 경우 2번의 경우와 다르게 명시적으로 height 값을 줬더라도 발생한다.
- 부모와 첫번째(마지막) 자식 사이에 inline 콘텐츠가 없거나, 첫번째(마지막)에 명시적으로 padding, border 값을 주지않으면 마진이 겹친다. - 이때, 자식 요소의 마진이 더 크든 작든 상쇄된 마진은 부모 박스의 바깥으로 렌더링 된다.
3.1 부모 박스와 첫번째 자식 박스의 상단 마진이 겹치는 경우
- 부모 마진이 자식 마진보다 큰 경우

- 자식 마진이 부모 마진보다 큰 경우

- 자식 마진과 부모 마진의 값이 같은 경우

- 결론적으로는 두 값 중 마진 값이 큰 값으로 남는다는 것이다.
- 하단 마진이 겹치는 것도 같은 원리이다.
- 이런 경우에는 부모 박스 상단(하단)에 padding 또는 border 값을 주어 벽을 만든다.

마진 상쇄 규칙이 적용되는 경우
- 마진 상쇄는 인접한 두 박스가 온전한 block-level이어야 한다. -> inline, inline-block, table-cell, table-caption 등의 요소는 block-level이 아니다.
- 마진 값이 0이더라도 상쇄 규칙은 적용된다.
- 좌우 마진은 겹쳐도 상쇄되지 않는다. - 위아래만 적용된다.
마진 상쇄 규칙 예외
- 박스가 position:absolue인 상태
- 박스가 float:left/right인 상태(단, clear 되지 않은 상태)
- 박스가 display:float 일 때, 내부 flexbox item
- 박스가 display: grid 일 때, 내부 grid item
결국 어쩌는게 좋으냐
- 우선 인접하는 블록 레벨 요소 두개 중에서 더 큰 마진 값으로 상쇄된다. - 위 아래만
- 일반적인 경우에 이를 해결하고 싶다면 border, padding 을 두거나 그냥 상위 컴포넌트를 display:flex로 두고 가로정렬, 세로정렬 해버리자. -> 이게 무조건 답은 아니다. 근데 보통 블럭 나열하다 생기는 문제는 이런 상황에서 생기는 거 아닌가?
참고자료