본문 바로가기
HTML & CSS

[CSS] 마진 상쇄 현상

by 카누가 좋아요 2023. 8. 10.

📌 참고 사이트

여백 상쇄 정복 - 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들을 살펴보는 것이기 때문이다.

 

블록 서식 맥락이 생성되는 때 (출처: mdn web docs)

위 사진과 같은 경우에 해당하면 블록 서식 맥락이 형성되는 것이므로 마진 상쇄 현상이 일어나지 않는다. 

 

➡️ 자식 요소의 마진이 더 크거나 작은 것에 상관없이 상쇄된 마진은 부모 박스의 바깥으로만 렌더링된다.

 

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 이런 식으로)

'HTML & CSS' 카테고리의 다른 글

[HTML] 자주 쓰이는 태그들 정리  (0) 2023.08.11
[CSS] flex  (0) 2023.08.10
[CSS] position  (0) 2023.08.09
[CSS] display (block, inline, inline-block, none)  (0) 2023.08.09
[CSS] float와 clear  (0) 2023.08.08

댓글