[CSS] 마진 상쇄 현상
📌 참고 사이트
여백 상쇄 정복 - CSS: Cascading Style Sheets | MDN (mozilla.org)
여백 상쇄 정복 - CSS: Cascading Style Sheets | MDN
여러 블록의 위쪽 및 아래쪽 바깥 여백(마진)은 경우에 따라 제일 큰 여백의 크기를 가진 단일 여백으로 결합(상쇄)되곤 합니다. 이런 동작을 여백 상쇄라고 부릅니다. 단, 플로팅 요소와 절대 위
developer.mozilla.org
[CSS] 마진 겹침 현상(Margin-Collapsing) — 혼자공부끄적끄적 (tistory.com)
[CSS] 마진 겹침 현상(Margin-Collapsing)
마진 겹침 현상이란? 인접한 마진이 상쇄되는 현상을 말한다. 블록 요소에 한해서 좌우 방향은 적용되지 않고 오직 수직방향으로만 적용되며, 마진값이 0이더라도 상쇄 규칙은 적용된다. 또한
doooodle932.tistory.com
📋 마진(여백) 상쇄
📍 마진 상쇄란?
➡️ 위쪽과 아래쪽 margin이 맞닿아 있을 때 경우에 따라 가장 큰 여백의 크기를 가진 단일 margin으로 결합(상쇄)되는 경우를 의미한다. (margin의 크기가 같으면 둘 중 하나의 margin으로 결합)
➡️ float 속성이 적용된 요소와 절대 위치를 지정(position: absolute)한 요소의 margin은 절대 상쇄되지 않는다.
📍 마진 상쇄가 일어나는 상황
1️⃣ 인접한 형재 요소간의 맞닿는 margin은 서로 상쇄
ex)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<p style="margin-bottom: 50px; background-color: aquamarine">
나는 margin-bottom이 50px!
</p>
<p style="margin-top: 30px; background-color: bisque">
나는 margin-top이 30px!
</p>
</body>
</html>
둘 중 더 큰 사이즈인 50px로 margin이 상쇄된 것을 볼 수 있다.
❕ 뒤쪽 형제에 float 속성이 적용되어 있는 경우는 예외이다.
<!DOCTYPE html>
<html lang="en">
.....
<body>
<p style="margin-bottom: 50px; background-color: aquamarine">
나는 margin-bottom이 50px!
</p>
<p style="margin-top: 30px; background-color: bisque; float: left">
나는 margin-top이 30px! float은 left!
</p>
</body>
</html>
위와 같은 경우 margin-collapse 현상이 일어나지 않고 각각 margin-bottom: 50px, margin-top: 30px가 제대로 적용되어 있는 것을 볼 수 있다.
2️⃣ 부모 요소와 자식 요소 간 마진 상쇄
➡️ 부모와 그의 첫 번째 자식의 상단 마진이 겹치거나 부모와 그의 마지막 자식의 하단 마진이 겹치는 현상이다.
➡️ 부모와 자식 사이에 inline 컨텐츠가 없거나 상(하)단에 명시적으로 padding이나 margin이나 border를 주지 않았다면 margin이 겹치는 현상이 발생한다. 또한, 블록 서식 맥락이 생성되지 않은 경우에도 margin이 겹친다.
(height와 min-height의 값이 있더라도 위 조건에 해당하면 마진 상쇄 현상이 일어난다.)
* 블록 서식 맥락: 부모(조상) tag 입장에서 어느 자식 tag까지의 CSS를 나에게 포함시켜야 하는가를 의미하는 개념이다. containing block과 반대된다고 볼 수 있다. containing block은 자식 tag 입장에서 부모 tag들을 살펴보는 것이기 때문이다.
위 사진과 같은 경우에 해당하면 블록 서식 맥락이 형성되는 것이므로 마진 상쇄 현상이 일어나지 않는다.
➡️ 자식 요소의 마진이 더 크거나 작은 것에 상관없이 상쇄된 마진은 부모 박스의 바깥으로만 렌더링된다.
ex)
<!DOCTYPE html>
<html lang="en">
.....
<body>
<!-- 부모 -->
<div
style="
background-color: salmon;
margin-top: 100px;
width: 200px;
height: 300px;
"
>
<!-- 자식 -->
<div
style="
background-color: skyblue;
margin-top: 200px;
width: 100%;
height: 100px;
"
></div>
</div>
</body>
</html>
첫번째 자식의 margin이 200px로 부모의 margin인 100px보다 더 크므로 margin-top은 200px로 상쇄된다.
하단에서 마진 상쇄 현상이 일어날 때도 동일한 원리로 일어난다.
다음과 같이 부모의 상(하)단에 margin 대신 padding값을 사용하거나 border 값을 설정하면 위와 같은 마진 상쇄 현상을 예방할 수 있다.
.....
<body>
<div
style="
background-color: salmon;
margin-top: 100px;
width: 200px;
height: 300px;
border: solid 1px; /* 주목 */
"
>
<div
style="
background-color: skyblue;
margin-top: 200px;
width: 100%;
height: 100px;
"
></div>
</div>
</body>
.....
결과로 위 그림처럼 부모의 상단에는 부모의 margin-top인 100px가 적용되고, 자식의 상단에는 자식의 margin-top인 200px가 따로 적용되어 자식의 위치가 아래로 내려간 것을 볼 수 있다.
3️⃣ 빈 블록에서의 마진 상쇄
➡️ border, padding, inline 콘텐츠, height, min-height가 없으면 높이가 0인 빈 요소가 된다. 빈 요소는 위, 아래를 가르는 경계가 없기 때문에 상단 margin 값과 하단 margin값을 비교해 더 큰 margin값으로 상쇄한다.
ex)
좀 복잡한 경우를 살펴보겠다. 아래의 경우를 코드로 작성해 보겠다.
💻 HTML
<!DOCTYPE html>
<html lang="en">
.....
<body>
<div class="first-child"></div>
<!--빈 요소-->
<div class="empty"></div>
<div class="third-child"></div>
</body>
</html>
💻 CSS
.first-child {
background-color: salmon;
width: 200px;
height: 200px;
margin-bottom: 30px;
}
.empty {
width: 200px;
margin-top: 60px;
margin-bottom: 30px;
}
.third-child {
background-color: skyblue;
width: 200px;
height: 200px;
margin-top: 30px;
}
우선 .empty와 .third-child의 margin-bottom 30px와 margin-top 30px가 상쇄되어 margin이 30px가 되고, 빈 요소는 border, padding, inline 콘텐츠, height, min-height가 없으면 그 요소의 상단, 하단의 margin과 자신의 margin을 비교하여 큰 것을 남기므로 빈 요소의 margin-top인 60px 위아래로 있는 30px의 margin은 상쇄되어 결국 60px의 마진만 남게 된다.
위에서 남은 margin의 절반이 .first-child의 margin-bottom인 30px와 크기가 같은 것을 통해 최종적으로 남은 margin은 60px라는 것을 알 수 있다.
빈 요소에서의 마진 상쇄를 없애기 위해서는 border, padding, min-height, height 등을 주는 방법을 사용하면 된다.
❕부모 자식 간 마진 상쇄에서는 부모에 min-height, height를 설정해 주었더라도 border나 padding이나 inline 컨텐츠가 존재하지 않으면 마진 상쇄가 여전히 일어나지만, 빈 요소에서는 빈 요소에 min-height, height 같은 것을 설정해 주면 border 같은 것들을 설정해 주지 않아도 마진 상쇄가 일어나지 않는다.
빈 요소에 height를 주어 마진 상쇄 현상을 해결해 보겠다.
.empty {
width: 200px;
margin-top: 60px;
margin-bottom: 30px;
height: 1px; /* 주목 */
}
.empty의 margin-top인 60px와 margin-bottom인 30px가 제대로 적용된 것을 볼 수 있다.
.empty의 margin-top의 윗부분과 margin-bottom의 아래부분은 형제 간 마진 상쇄가 일어난 것이므로 위아래 형제들에서 padding이나 border를 사용해 margin을 대신하는 방식 등으로 마진 상쇄 현상을 해결 가능하다.
(border-bottom: 30px solid white 이런 식으로)