뭐야 마진 어디갔어 : 마진 겹침 현상

사자·2022년 4월 6일
2
post-thumbnail

마진(margin)이란, 요소 바깥 네 방향의 여백 영역을 설정하는 css 속성이다. reset.css 없이 여러 블록 요소들에 margin을 주다 보면, 의도치 않게 상하로 인접해있는 요소와 요소 사이의 마진이 줄어드는 현상이 일어난다. 이러한 현상을 마진 겹침 현상(margin collapsing)이라고 한다. 마진 상쇄, 마진 병합이라고도 한다.

해결법 바로가기

마진 겹침 현상(margin collapsing)

마진 겹침 현상의 대표적인 예는 아래와 같다.

1. 형제 요소 간의 상하단 마진 겹침


위 코드에서, section 태그에 각각 margin: 20px의 속성을 줌으로써 상하좌우에 여백을 부여했다.
이때, section 1의 bottom 마진과 section 2의 top 마진이 알맞게 들어갔다면 두 섹션 사이의 간격은 40px이어야 한다. 그러나 두 섹션 사이의 간격은 20px이 되었다.
이 경우의 마진겹침 현상은 일관성있는 디자인 만들기에 도움을 준다.

2. 부모 자식 요소 간의 마진 겹침


반면, 부모 요소의 마진과 자식 요소의 마진이 병합되는 경우도 있다. 부모 요소 안에서 자식 요소에 margin을 주면 1번에서의 예시와 같이 숫자 8 모양이 나올 것 같지만, 결과는 마진 겸침 현상으로 인해 H모양이 나온다.

이는 첫 번째 child의 margin-top, 마지막 child의 margin-bottom이 적용되지 않았기 때문이다. css를 확인해보면 parent에는 margin을 부여하지 않았으나, child요소의 margin 값이 부모 영역을 넘어서고 있는 모습을 확인할 수 있다.


마진 겹침 현상을 해결하는 법

이와 같은 현상을 해결하는 방법은 여러 가지 있다.

1. 부모 요소에 overflow 속성 적용하기
부모 요소에 overflow: hidden 속성을 주면 top, bottom margin이 적용된다.

.parent {
	overflow: hidden;
}

만약 Internet Explore 호환을 고려하지 않아도 된다면, 비슷한 원리로 작동하는 display: flow-root 속성을 부여해도 된다. IE가 퇴장한 미래에서는 이게 유용할 지도.

2. 부모 요소에 display: inline-block 적용하기
이 방법을 사용할 때는, 부모요소와 동격인 요소가 옆에 나란히 올 수 있음을 유념해야 한다.

.parent {
	display: inline-block;
}

3. 부모 요소에 border 값 적용하기
부모 요소에 border 값을 주어서 해결할 수도 있다. (border: none으로는 해결되지 않는다.)

.parent {
	border: 1px solid black;
}

border가 아니어도, 부모 태그에 padding을 주거나 자신의 공간을 차지하는 요소를 부모와 자식, 형제 요소 사이에 삽입하는 등의 방법으로도 해결이 가능하다. 단, box-sizing: border 속성을 사용하지 않을 경우 border나 padding에 의해 부모요소의 가로 너비가 달라질 수 있다는 점을 유의해야 한다.

4. 요소 사이에 table 태그 추가하기
또다른 해결 법 중, 이런 것도 있다.

<div class="parent">
  <!--✅ 이 부분 주목-->
  <table></table> 
  <!------------------>
  <div class="child">
    child 1
  </div>
  
  ...
  
</div>

위와 같이 마진 겹침이 발생하는 요소들 사이에 빈 table 태그를 넣어주는 것. 비어있는 table 태그는 공간을 차지하지 않아 레이아웃에 영향을 주지 않는다.
하지만 이렇게 하면 콘텐츠를 담지 않은 의미 없는 태그가 추가됨으로써 클린코드를 지향하는 사람들은 eww... 눈쌀을 찌푸릴 수 밖에 없는데, 이 원리를 응용하여 가상 요소로 표현하면 마크업을 해치지 않으면서 해결할 수 있다.

.parent::before,
.parent::after {
    content: ' ';
    display: table;
}

이처럼 마진 겹침이 발생하는 요소에 before, after 가상 클래스 선택자로 table 가상 요소를 추가해주면 문서에 실제 table을 넣지 않아도 행복해질 수 있다.

참고:


맺으며

안될 땐 "뭐야 왜 안돼?" 싶었지만, 위의 간단한 방법으로 수정이 되니 "뭐야, 왜 돼?" 라는 의문이 생긴다. 브라우저는 왜 마진이 겹치게 디자인 했을까? overflow를 주었을 때 왜 해결되는걸까? 이런 질문들을 기록으로 남겨두고 해결하려고 노력해야 진정으로 뾰족한 개발자가 되는 거겠지... 내일은 overflow를 좀더 파고들어 공부해보려 한다.

추가) display: flow-rootoverflow: ... 속성을 주었을 때 해결되는 것은, 블럭 포맷팅 컨텍스트(block format context)와 연관된다. 부모에게 새로운 블럭 포맷팅 컨텍스트가 생성되어 자식과의 마진 겹침 현상이 일어나지 않게 되는 것.

overflow: visible 외의 overflow: hidden, clip 등의 속성을 가진 블록 요소는 새로운 블럭 포맷팅 컨텍스트를 생성하여 마진 겹침이 발생하지 않는다.

블럭 포맷팅에 대한 정보는 여기를 클릭.

딥한 부분이지만 알아두면 행복감이 찾아온다는 빔캠프 종찬님의 말씀이다. 빔멘. float 속성을 쓸 때 특히 유용하다고 한다.

마진 병합에 대해서는 아래의 자료에서 좀더 자세한 설명을 확인할 수 있다. 강추!
[ㅁ] 마진병합 margin collapsing | 코딩가나다 | 빔캠프
The Rules of Margin Collapse (EN)

profile
FrontEnd Developer 🦁사자의 성장 로그

0개의 댓글