본문 바로가기

CSS

[CSS] margin collapsing (마진 상쇄)



안녕하세요.

이번 포스팅은 margin collapsing (마진 상쇄) 현상에 대해서 알아 보도록 하겠습니다. 또는 마진 겹침 현상이라고도 합니다.


박스 모델을 구현할 때 마진겹침현상 때문에 애먹으신적이 종종 있으실 겁니다.

그런데 이 현상이 어떤 경우에 일어나는지 아시면 적어도 답답함은 조금 줄어들지 않을까 생각 됩니다.

그래서 어떤 경우에 마진겹침현상이 일어나는지 알아 보도록 하겠습니다. 



인접한 두 박스의 마진 방향이 겹칠 경우



<html>
<head>
<style>
.box1 {
border: orangered solid 1px;
}


.box2 {
border: purple solid 1px;
}


div {
margin: 20px;
}
</style>
</head>
<body>
<div class="box1">안녕하세요</div>
<div class="box2">margin collapsing test</div>
</body>
</html>




위 이미지를 보면 뭔가이상한 점이 느껴지시지 않습니까? 모든 div 엘리먼트에게 상하좌우 20px의 마진을 주었습니다.

그런데 위 쪽 박스의 20px 마진만 적용된 것처럼 보여집니다. 이것이 바로 마진겹침현상의 첫번째 경우입니다.

그럼 같은 경우의 예시를 하나 더 보겠습니다.



<html>
<head>
<style>
.box1 {
border: orangered solid 1px;
margin: 20px;
}


.box2 {
border: purple solid 1px;
margin: 30px;
}
</style>
</head>
<body>
<div class="box1">안녕하세요</div>
<div class="box2">margin collapsing test</div>
</body>
</html>



이번에는 box2 엘리먼트에 box1 엘리먼트 보다 마진 10px을 더 주었습니다. 위 이미지를 보면 알 수 있는 것은 마진의 방향이 겹쳤을때 마진의 크기가 더 큰 박스의 마진만큼 두 엘리먼트간의 여백이 생긴 것을 알 수 있습니다. 더 큰 마진만 적용 된 것처럼 보이죠.



부모와 자식 박스


두 번째의 경우부터는 약간 혼란스러워질 수 있습니다. 



<html>
<head>
<style>
.parent {
border: orangered solid 1px;
margin: 20px;
}


.child {
border: purple solid 1px;
margin: 30px;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">margin collapsing test</div>
</div>
</body>
</html>




정상적으로 지정한 마진의 크기만큼 적용이 된 것을 볼 수 있습니다. 그럼 부모와 자식 박스 사이에서 어떠한 경우에 마진겹침 현상이 생기는지 보겠습니다.



<html>
<head>
<style>
.parent {
/* padding: 10px; */
/* border: orangered solid 1px; */
margin: 20px;
}


.child {
border: purple solid 1px;
margin: 30px;
}
</style>
</head>
<body>
<div class="parent">
<!-- 안녕하세요 -->
<div class="child">margin collapsing test</div>
</div>
</body>
</html>



바로 위에 코드와 이미지를 보면 알 수 있듯 부모와 자식, 어느 한 쪽의 박스에 margin을 제외한 박스 모델의 구성요소가 아무것도 존재하지 않을때 마진겹침현상이 일어나게 됩니다.



빈 블록이 있는 경우


이번 경우는 앞서 말씀 드린 두 가지의 경우를 콜라보? 한 것이라고 볼 수 있습니다. 인접한 두 박스가 있을 때 어느 하나의 박스가 빈 박스일 경우입니다. 바로 예시를 보죠.



<html>
<head>
<style>
.empty {
/* padding: 10px; */
border: orangered solid 1px;
margin: 20px;
}


.normal {
border: purple solid 1px;
margin: 30px;
}
</style>
</head>
<body>
<div class="empty">
<!-- 안녕하세요 -->
</div>
<div class="normal">margin collapsing test</div>
</body>
</html>



인접한 두 박스가 둘 다 빈 박스가 아닐 경우 첫 번째로 말씀 드린 경우가 됩니다. 그럼 이번에는 empty 박스의 border를 없애 보겠습니다.



<html>
<head>
<style>
.empty {
/* padding: 10px; */
/* border: orangered solid 1px; */
margin: 80px;
}


.normal {
border: purple solid 1px;
margin: 50px;
}
</style>
</head>
<body>
<div class="empty">
<!-- 안녕하세요 -->
</div>
<div class="normal">margin collapsing test</div>
</body>
</html>




normal 박스의 위치가 왜 이렇게 바뀌냐하면 empty 박스가 빈 블록이 되면 마진을 위아래에서 크기가 큰 마진을 선택하여 하나의 마진만 적용되게 됩니다. 지금은 둘 다 80px이라 empty의 마진은 총 80px만큼 잡히게 되는 것이고 empty 박스의 마진과 normal 박스의 top 마진이 겹치게 되면서 위 쪽 마진이 80px만큼 잡히게 되는 것입니다. 이 개념은 좀 혼란스러울 수 있습니다.


  • 빈 블럭의 경우, 크기가 큰 마진을 선택하여 하나의 마진만 적용 된다.
  • 마진의 방향이 겹칠 경우, 크기가 큰 마진을 선택하여 하나의 마진만 적용 된다.
이 두 가지 규칙만 잘 기억 하시면 금방 이해를 하실 수 있으실 겁니다.

이상 포스팅을 마치겠습니다.





[Reference] - https://opentutorials.org/course/2418/13464

'CSS' 카테고리의 다른 글

[CSS] position  (0) 2018.08.17
[CSS] box model과 box-sizing  (0) 2018.08.02
[CSS] display - block과 inline 그리고 inline-block  (1) 2018.08.02
Text 개행 처리 및 글자 자르기  (0) 2017.07.18