[CSS] margin-collapsing

yongkini ·2021년 9월 10일
0

CSS

목록 보기
7/10
post-thumbnail

마진 상쇄에 대하여

: 사실 개발자로 일을 할 때도 마진 상쇄를 많이 경험했었는데, 그 때는 창피하지만 그것이 마진 상쇄 때문인지도 몰랐던 경험이 있다. 물론 디버깅을 하면서 이것이 마진 상쇄구나 알았지만...ㅎ 어쨌든, 마진 상쇄는 개발중인 웹문서 커질수록 정말 알 수 없는 포인트에서 발생할 수 있는 것이기에 제대로 알아두고, 디버깅 시에 혹은 설계시에 잘 처리할 수 있도록 한다.

마진 상쇄란 ?

: 마진 상쇄(Margin-Collapsing)란, 두 요소 사이에 border, padding 혹은 또다른 콘텐츠가 없는, 또한, 두요소가 아니더라도 마진과 마진 사이에 어떠한 중간 매개물이 없는 두 마진(top, bottom) 사이에 일어나는 상쇄 현상이다. 좀더 구체적으로 말해보면, margin 중에서도 top과 bottom 사이(상하마진)에 일어나는 것으로 예를 들어, 두개의 콘텐츠 1,2(위아래로 쌓여있는 관계에 있는, 그리고 둘 사이에 마진값 이외에 어떤 방해물도 없는 관계)가 있을 때, 1(위에 있는 콘텐츠)에서 margin-bottom 값을 40px을 주고, 2(아래에 있는 콘텐츠)에서 margin-top 값을 50px을 줬을 때, 둘중에 더큰값인 50px로 둘 사이의 여백이 결정되는 것을 의미한다. 이 경우에는 40px 마진값이 상쇄되는 것이다.
** 참고로 마진상쇄는 한쪽의 마진값이 0이어도 발생하며 둘사이에 장애물이 없는 경우를 제외하고는(다른 예외 상황은 마지막 부분에 정리) 모두 일어난다. 또한, 블록요소와 블록요소 사이에만 일어난다(inline-block 등에는 해당x).

마진상쇄 예시


: 간단한 예시로 위의 두박스를 보면 위에 박스에 margin-bottom:50px을 줬고, 아래 박스에 margin-top:30px을 줬다. 직관적으로 생각해보면, 둘 사이에는 80px의 여백이 있어야할 것 같지만, 둘 사이에는 50px의 여백이 생겼다. 실제로 개발자 도구를 열어서 보니


이런식으로 box1의 마진값이 box2 사이의 여백을 가득 채운 것을 볼 수 있다. 이는 곧 box1의 마진 바텀값이 둘 사이의 여백 그자체, 즉, 둘 사이의 거리는 box1의 마진 바텀값으로 상쇄됐음을 보여준다. 이 때, 당연한 결과겠지만, 둘 사이에 또다른 상자블록을 두면 어떻게 될까?

본래 의도한대로 another box를 사이에 두기는 했지만, 각각의 마진값이 잘 먹히는 것을 볼 수 있다.

부모 자식 간(최상단, 최하단)의 마진상쇄

: 위에서는 형제관계끼리의 마진 상쇄를 알아봤다면, 이번에는 부모 자식간의 관계에서의 마진상쇄를 알아보고자 한다. 사실 부모와 자식관계에서 어떻게 마진상쇄가 일어날지.. 상상도(?)되지 않는다. 그나마 이해가 가능한건 위에서처럼 형제간의 마진 상쇄인데 부모간의 마진상쇄는 어떻게 일어나는지 살펴본다.

먼저 위의 그림은 parent라는 클래스명의 div아래 자식요소로 세개의 클래스명 child라는 div태그를 만든 것이다. 그리고 class 셀렉터로 자식요소 전체에 margin-top: 10px을 걸어줬다. 그리고 결과적으로 잘적용이되는 것을 볼 수 있다. 그렇다면, 슬슬 시비를.. 아니 마진상쇄를 일으켜보면, 일단 지금은 부모요소에 padding값을 10px을 줬는데, 그 padding값을 뺌과 동시에 부모요소에 margin-top을 20px로 줘본다.

그러면 이러한 결과가 나오는데?..
아까 만들어놓은 자식요소의 margin-top이 맨위의 자식요소 부분에서 사라진 것을 알 수 있다. 이는 맨위의 자식요소의 margin-top이 부모요소의 margin-top에 상쇄된 결과라고 할 수 있다. 하지만, 이번 경우에는 심지어 부모요소의 마진값을 설정해주지도 않았는데 상쇄가 일어났다.. 사실 모든 마진 상쇄는 margin값을 0으로 해놔도 일어난다. 단지 이경우에는 마진 상쇄에 의해 자식요소의 마진값이 부모요소 밖으로 상쇄되기 때문에 그 차이가 커보이는 것일뿐. 따라서 저러한 마진상쇄를 해결하기 위해서는 부모요소와 자식요소 사이에 inline요소 혹은 부모요소의 padding, border 혹은 자식요소(상단, 하단 둘다 해당)의 padding, border을 줘서 둘 사이에 장애물과 같은 것을 두는 방법이 있다.

빈요소에서 일어나는 마진 상쇄

: 빈요소에서 어떻게 마진 상쇄가 일어나는지 이해할 수 없지만, 높이마저 없는, 정말 아무것도 없는 요소에 margin-top, margin-bottom값을 준 케이스를 생각해보자. 그 둘사이에는 마진상쇄가 일어나기 좋게 border, padding, inline요소, 심지어 아예 콘텐츠 자체가 없다(하지만 블록요소). 가끔 일정부분의 공백을 주기위해 빈요소를 쓰는 경우가 있는데, 이 경우에 마진탑, 마진 바텀을 주면 마진 상쇄가 일어나므로 중간의 장애물을 만들어놓을 필요가 있다(height,min-height,padding,border 등).

마진 상쇄가 일어나지 않는 사항

  • 박스가 position: absolute 된 상태(따로 떨어지게 되는 것과 같으므로)
  • 박스가 float: left/right 된 상태 (단, clear 되지 않은 상태)
  • 박스가 display: flex 일 때, 내부 flexbox item에 대하여
  • 박스가 display: grid 일 때 내부 grid item에 대하여

마무리

: 마진 상쇄의 포인트는 두 블록 요소 사이에 아무것도 없을 때 상하마진이 상쇄된다는 점이다. 그리고 이를 방지하기위해 일종의 장애물(border, padding, inline요소 등)을 넣을 수 있다는 것!.

profile
완벽함 보다는 최선의 결과를 위해 끊임없이 노력하는 개발자

0개의 댓글