마진 병합현상 (Margin Collapsing)
인접하는 블록요소의 상 하단의 마진이 한쪽으로 병합되는 현상이다.(상쇄,겹침 등등 다양하게 불린다.)
때문에 마진 10+10이 =10이 되거나, 15+10은 15가 되는(더 큰 쪽의 마진값으로 병합) 원치 않는 상황이 발생된다.
하지만 알고보면 마진병합현상은 CSS가 의도적으로 만든 기능이다.
상하단 마진이 병합되지 않고 둘 다 적용이 된다면 상대적으로 다른곳들에 비해 그 부분만 마진이 너무 두꺼워지기 때문에,
디자인이 더 안정적으로 보일 수 있도록 설계된 것이다.
일단은, 마진 병합은 우리를 도와주는 이로운 현상이다라고 이해하자.
마진병합현상이 일어날 수 있는 조건
- 인접해있는 block 요소끼리만 일어난다.
- 상하단만 해당사항이다.
일단 아래와 인접해있는 블럭요소끼리는 상하단의 마진이 동시에 발생할 때에
'값이 더 큰 마진' 하나만 적용된다는 것은 이해하기 어렵지 않다.
하지만 곤란한 상황이 발생할 수 있다.
아래의 예를 살펴보자.
부모 div 안에 2개의 자식 div가 들어있다.
부모 div에는 margin값을 상하 0 좌우 auto를 주었고
자식 div들에 상하좌우 마진 50px를 줘보자.
See the Pen Challenge #2 by Koreanhamster (@koreanhamster) on CodePen.
우리의 예상으로는 자식div들에 마진이 먹히면서 부모 div 영역인 회색 background가 8자의 모양처럼 나와야한다.
그런데 8 대신, 상하 마진은 적용되지 않은 H 모양이 나온다.
이는 부모 div 역시 블록레벨의 요소이기 때문에 자식div와 병합 현상이 일어났고,
부모div(회색박스) 자체의 margin처럼 표현된 것이다.
그래서 부모 div와 body 사이의 마진이 50px 생긴 것을 볼 수 있다.
그렇다면 이걸 어떻게 해결할 수 있을까?
Best: 부모 요소에 overflow:hidden이나 display:flow-root 를 적용하는 방법
부모 요소에게 overflow:hidden을 주게 되면 새로운 block format context가 부모 요소 기준에서 만들어지면서 부모 요소의 마진과 자식 요소의 마진은 별개가 된다.
비슷한 방법으로 display: flow-root를 주면 깔끔하게 문제가 해결되지만
역시나 IE는 지원하지 않는다.
parent에 border나 padding을 1px만 넣기
이렇게 되면 공간을 차지하고 있는 요소가 parent와 child 사이에 하나 낀 것이니
더이상 마진병합은 일어나지 않는다.
하지만? 결국에는 1px을 더 사용하는것이기 때문에 우리가 의도한 디자인에서 그만큼의 차이가 나게 된다.
이는 우리가 마진 병합 현상을 해결했다라고 하기는 어렵다.
그래서 보다 완성도 높은 디자인을 구현하고 싶을 때 그리 추천하는 방법이 아니다.
부모와 자식요소 사이에 비어있는 table태그 넣어주기
See the Pen Untitled by Koreanhamster (@koreanhamster) on CodePen.
우연히 블로그에서 발견하고 실험해봤더니 정말 잘 되어서 가져온 해결법.
table의 크기는 자식요소에 의해 결정되므로 그 자체는 아무런 공간을 차지하지 않는다.
html에 넣어줄 수도 있지만 CSS가상요소를 넣어 처리해줌으로써 마크업을 심플하게 유지할 수 있다.
자식요소에 display:inline-block 값 주기
See the Pen inline by Koreanhamster (@koreanhamster) on CodePen.
마진병합현상의 조건이 '블록요소'이여야 한다는 것이기 때문에,
자식요소들을 lnline-block으로 바꾸면 마진병합현상은 사라진다.
하지만 이는 역설적으로 마진병합현상이 무슨 기능을 하고 있는지 아주 잘 보여주는데,
자식요소들간의 상하마진이 좌우보다 2배씩 커지는 부자연스러운 모습으로 나타나는 것이다.
물론 맨 위에 위치한 자식을 제외한 나머지 자식들에 margin-top값을 0으로 지정해줌으로써 문제를 해결할 수 있지만, 번거롭다.
결론
상황에 따라 해결하자.
아래는 내가 마진을 이해하는데 도움을 많이 받은 블로그 링크를 첨부하고,
간단히 한 구역을 요약해서 번역해보았으니 참고하시길!
지금까지 마진병합이 일어나는 이 모든 상황들은 우리가 "in-flow"상황에 있다고 가정 한 것이다.
Grid나 Felxbox를 사용할 때, 혹은 taken out-of-flow일 때(예를 들어 float속성을 가질 때나 absolute position일 때)에는
마진 병합 현상이 절때 일어나지 않는다.
사실 마진의 이런 예측힘들고 재사용성을 어렵게 하는 측면때문에 개발자들 사이에서는 margin대신에 이런 layout compenents를 사용하는 것을 선택하는 운동이 일어나고 있기도 하다. 하지만 margin이 범적으로 사용되고 있는 것도 사실이기 때문에, 결국은 우리가 여전히 이것들을 잘 알고있어야 한다.
https://www.joshwcomeau.com/css/rules-of-margin-collapse/
'Front-End Developer > CSS' 카테고리의 다른 글
Flex 별 거 아냐 - 자식요소편 (0) | 2022.04.09 |
---|---|
니가 누구던지 센터로 가버려 - CSS 중앙정렬 4가지 방법 (5) | 2022.04.07 |
Flex 별 거 아냐 - 부모요소 편 (2) | 2022.04.07 |
How to move bullet points in css? (0) | 2022.04.02 |
이종찬님 특강 - 행복한 CSS냐 망한 CSS냐. (0) | 2022.04.02 |