2016.12.21 15:00
   , ,

css에는 마진 상쇄(margin collapsing) 혹은 마진 겹침(margin overlap)라는 현상이 있습니다.

 

탑과 바텀에 마진이 있는 경우 큰 쪽 한 개만 적용되는 현상을 말합니다.

 

아래위 마진이 겹쳐 있습니다.

 

1. 현상 확인

아래 코드를 실행해봅시다.

 

 

 

탑 마진(margin-top)을 20px주고

바텀마진을(margin-bottom) 20px를 줬습니다.

그런데 결과물은 20px 입니다,

 

 

이것을 마진 상쇄(margin collapsing), 마진 겹침(margin overlap) 현상이라고 합니다.

 

2. 현상의 이해

마진 상쇄가 일어나는 이유는 레이아웃의 예외제어를 쉽게 하기 위해서입니다.

보통 줄 단위(row)의 레이아웃의 경우 마진상쇄가 일어나지 않으면 맨 위에 줄과 맨 아래 줄을 따로 처리해야 하는 문제가 발생합니다.

아래 예제를 통해 문제를 확인해 봅시다.

 

 

 

같은 css를 적용했지만 맨 위칸과 맨 아래칸 마진이 달라서 레이아웃이 이상해 보입니다.

 

 

 

이 문제를 해결하기 위해선 맨 위 칸과 맨 아랫간에 별도의 css를 적용해야 하는 문제가 발생합니다.

그래서 마진 상쇄 현상이 필요한 것이죠.

 

 

마진 상쇄 현상은 아래와 같은 3가지 상황에서 일어납니다.

 

인접 형제 요소(Adjacent siblings)
부모 및 맏이/막내 요소(Parent and first/last child)
빈 블록(Empty blocks)

(참고 : w3c - 8.3.1 Collapsing margins, MDN - 마진 상쇄 정복)

 

2-1. 인접 형제 요소( Adjacent siblings )

붙어 있는 형제 요소끼리 마진 상쇄가 일어나는 현상을 말합니다.

아래위로만 발생합니다.

좌우는 발생하지 않는다는 것이죠.

 

아래 코드를 확인해 봅시다.

 

 

 

아래위로는 마진 상쇄가 일어나지만 좌우로는 일어나지 않는 것을 볼 수 있습니다.

 

 

 

 

2-2. 부모 및 맏이/막내 요소(Parent and first/last child)

부모의 특정요소가 없다면 자식요소의 'margin-top'과 'margin-bottom'이 상쇄되는 현상을 말합니다.

 

특정요소는

 

첫 줄이면

border
padding
inline(화면에 표시되는 글자 같은 것들)

 

이고 마지막 줄이면

border
padding
inline

height

min-height
max-height

 

 

첫 번째 줄일 때 'margin-top'이 상쇄되고

마지막 줄일 때 'margin-bottom'이 상쇄됩니다.

 

아래 코드를 봅시다.

 

 

 

 

 

div가 여러 번 중첩되었지만 'margin-top'과 'margin-bottom'는 한 번만 적용된 것을 확인할 수 있습니다.

 

 

 

 

2-3. 빈 블록(Empty blocks)
근접한 블록이 특정요소가 없으면 마진이 상쇄됩니다.

 

특정요소는

border
padding
inline

height

min-height
max-height

 

아래코드는 주황색(orange)과 파란색('blue')의 내용을 뺀 코드입니다.

 

 

 

주황색은 가로마진이 남아있어 그대로 있지만 파란색은 마진이 상쇄되어 존재가 지워졌습니다

 

 

 

3. 마진 상쇄 피하기

 

그렇다면 마진 상쇄가 필요 없는 경우 어떻게 해야 할까요?

간단하게 위에서 말했던 특정요소를 css에 포함 시키면 됩니다.

 

공통으로 사용되는

border
padding
inline

를 이용하면 됩니다.

 

 

 

 

하단 마진만 처리할 거면 선택의 폭은 더 넓어지죠.

 

마무리

이런 디스플레이에 영양을 주는 현상을 정의 하면서 우회 방법이 없다는 게 좀 이상하네요.
이 현상을 피하려면 보더나 패딩같이 레이아웃에 영향을 주는 요소를 활용해야 합니다.

뭔가 레이아웃에 영향을 안 주는 방법을 찾고 싶은데 모르겠네요;;;

 

  1. 익명 2018.01.02 04:10  Address  Edit/Delete  Reply

    이것 때문에 고생했는데 이유를 알게되었습니다 감사합니다.
    하지만 참으로 불합리하다는 생각을 도저히 지울 수 없습니다.
    맨위, 아래의 예외처리 불합리함 때문이라면 nth-child 속성값도 있고 다른방법도 많은데
    좌우는 아니고 위아래만 적용된다는것도 이상하고
    지멋대로 마진 상쇄적용했으면 적용안되는 우회방법이라도 만들어야지!!!
    아 생각할수록 빡치네!

    • Favicon of https://blog.danggun.net BlogIcon 당근천국 2018.01.03 01:41 신고  Address  Edit/Delete

      그러게 말입니다.
      최소한 좌우도 룰이 동일하다던가 우회 방법이 있어야할거 같은데.....
      표준이 이모양이라-_-;;

  2. ??? 2018.09.06 17:04  Address  Edit/Delete  Reply

    부모 요소에 overflow: hidden; 적용하시면 자식 요소의 마진 상쇄를 없앨 수 있습니다.

    • Favicon of https://blog.danggun.net BlogIcon 당근천국 2018.09.21 02:10 신고  Address  Edit/Delete

      그렇군요.
      요즘 바빠서 테스트를 못하고 있어서 확인은 안되지만 오버플로도 디스플레이요소이긴한데 다른 요소들에 비하면 활용도가 높아 보이네요.

  3. 최종찬 2018.10.10 10:28  Address  Edit/Delete  Reply

    부모요소:before {
    content: "";
    display: table;
    }
    해주면 바로 해결이되네요!

  4. HANUL 2019.08.18 02:10  Address  Edit/Delete  Reply

    포스트 잘 보았습니다.
    다만 질문이 한 가지 있는데

    부모의 특정요소가 없다면 자식요소의 'margin-top'과 'margin-bottom'이 상쇄되는 현상을 말합니다.
    특정요소는

    첫 줄이면
    border
    padding
    inline(화면에 표시되는 글자 같은 것들)

    이고 마지막 줄이면
    border
    padding
    inline
    height
    min-height
    max-height

    첫 번째 줄일 때 'margin-top'이 상쇄되고
    마지막 줄일 때 'margin-bottom'이 상쇄됩니다.


    바로 위의 부분입니다.
    만약 코드가

    <div class="c1">
    <div class="c2">
    <div class="c3">
    <div class="c4"></div>
    </div>
    </div>
    </div>

    와 같이 있다면, 가장 상위 div인 c1을 기준으로, 직속 자식인 c2가 첫 줄이고, c4가 마지막 줄이 되는 건가요?

    (저장하니 띄어쓰기한 게 안 보이네요.
    c1이 가장 조상, c2가 c1의 자식,
    c2가 c3의 부모, c3이 c2의 자식
    c3이 c4의 부모, c4가 c3의 자식)

    • Favicon of https://blog.danggun.net BlogIcon 당근천국 2019.08.18 06:43 신고  Address  Edit/Delete

      그런식으로 자식요소일때는 모든 div가 첫줄이자 마지막줄입니다.

      '2-2.'에서 말하는 첫줄과 마지막줄은
      <div></div>
      <div></div>
      <div></div>
      이런식으로 나열된것을 말합니다.

    • HANUL 2019.08.18 17:13  Address  Edit/Delete

      답변 감사드립니다.
      그럼 제가 쓴 댓글의 html코드를 기준으로 말씀드리자면,,,
      c2가 부모, c3이 c2의 자식이자 첫 줄과 마지막 줄이니,
      c2에 border, padding, inline 중 하나라도 없으면 c3의 margin-top이 상쇄되고,
      border, padding, inline, height, min-max, max-height중 하나라도 없으면 c3의 margin-bottom이 상쇄되는 건가요?

      감사합니다.

    • Favicon of https://blog.danggun.net BlogIcon 당근천국 2019.08.20 22:25 신고  Address  Edit/Delete

      맞습니다.
      "2-2."의 셈플이 해당 상황입니다.
      (익스에서는 소스가 잘보이지 않습니다.)

댓글 작성

이름
패스워드
홈페이지
비밀글