sharingStorage

형제 요소의 margin이 영향을 주는 경우 ( position, overflow 그리고 BFC) 본문

Front-End/CSS

형제 요소의 margin이 영향을 주는 경우 ( position, overflow 그리고 BFC)

Anstrengung 2024. 11. 12. 16:15

 

이 글은 한 초보 개발자의 간단한 질문에서 부터 시작되었다. 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
     body {
        background-color: green;
      }
     
      header {
        width: 100%;
        height: 6.4rem;
        background-color: blue;
        position: fixed;
      }
      main {
        background-color: red;
        margin-top: 6.4rem;
        height: 10rem;
        width: 100%;
      }
    </style>
    <title>Document</title>
  </head>
  <body>
    <header>헤더헤더</header>
    <main>123123123</main>
  </body>
</html>

위 코드는 header의 fixed를 통해 상단에 고정시키고 main에 컨텐츠를 담기 위해 간단한 작업을 할 때 사용하는 코드인데 위 코드를 실행하면 우리가 의도한 바대로 작동하지 않는다.

 

위 코드를 실행해본 결과이다 body의 위치를 이해하기 쉽도록 green을 주었다.

 분명 main에 margin-top을 주었는데 왜 형제 요소인 fixed 헤더까지 내려올까??

 

문제점 1 fixed에 offset값을 넣지 않았다.

너무나 당연한 답입니다.fixed는 뷰포트 기준으로 top, left, rigth, bottom에 의해 결정되는데 이를 적용하지 않았을 때 초기위치에 absolute값과 동일하게 적용됩니다.

해서 위 로직은 position: absolute 와 동일하게 적용되는 것입니다.

결론적으로 top: 0 을 넣으면 이 문제는 해결이 됩니다.

 

 

문제점 2 근데 왜 형제요소의 main의 margin이 왜 부모요소를 이동시키는가?

우리가 일반적으로 아는 선에선 자식요소에 margin이 있다고 해서 부모 요소가 움직이지는 않습니다.

하지만 예외적으로 부모요소에 padding값이나 border값이 없고 자식 요소에 상단에 여백(margin top)이 존재하면 자식요소의 여백이 부모요소를 밀어서 여백과 함께 부모와 자식이 함께 이동하게 됩니다.

 

해결방법 1

부모요소에 padding값 또는 border값을 추가한다.

간단히 부모요소에 padding과 border를 넣음으로써 우리가 원하는 css결과를 얻을 수 있습니다. 하지만 이 방법이 요구사항에 벗어나는 해답일 가능성이 존재하기 때문에 다른 방법을 찾아봐야할 수도 있습니다.

padding과 border를 설정

padding: 1px;
//또는 
border: 1px solid

 

 

해결방법 2

부모요소에 overflow 속성 auto 또는 hidden을 적용한다.

이렇게 하면 부모요소에 대한 새 블록 서식 컨텍스트 (block formatting context - 이하 BFC)를 만들 수 있으며 이를 통해 부모요소가 자식요소의 여백과 함께 밀려나는 것을 방지할 수 있습니다.

이때!!

overflow 속성의 default 값은 visible이고 html요소의 overflow는 visible값을 가지고 있기 때문에 body의 overflow를 아무리 바꿔도 원하는 결과를 얻기 쉽지 않습니다.

(div 부모로 감싸고 overflow를 적용하면 정상적으로 우리가 원하는 결과를 얻을 수 있습니다.)

해서 html 요소의 overflow속성과 body 속성의 overflow값을 auto로 바꾸면 아래와 같이 우리가 원하는 결과를 얻을 수 있습니다.

 

근데 이 방법은 정말 옳은 것일까? overflow를 이런 방식으로 사용하는 것이 보편적인가? 에 대한 의문점이 생겼고 이를 더 알아보는 과정에서 얻은 몇가지 지식과 함께 서술을 해보겠습니다.

 

💡body 요소의 기본 overflow 값은 visible이다.

근데 overflow 속성이 visible이라는 것은 스크롤없이 자르지않고 요소밖의 내용을 모두 보여주는 것인데 왜 overflow auto처럼 작용하는것인가?

이는 브라우저가 내부적으로 스크롤이 필요한 경우 auto값으로 취급하여 스크롤바를 생성하게 해주기 때문입니다.

 

💡absolutely positioned element 에 대해 알아보기

fixed나 absolute와 같은 요소를 absolutely positioned element라고 부르며 이는 요소의 Containing block에 가장자리부터 거리를 지정합니다. 이 때 요소가 margin을 가지고 있으면 margin값들은 offset에 더해져 계산됩니다. 

그리고 그 요소는 새로운 BFC를 만듭니다. 

header{
width: 100%;
 height: 6.4rem;
background-color: blue;
 position: fixed;
top: 0px;
margin-top: 50px;
margin-left: 20px;
}

offset 값은 top:0이지만 margin이 함께 적용된 모습

 

 

그러면 BFC가 뭔데…?

Block Formatting Context (BFC란?)

웹페이지의 시각적 CSS 렌더링에서 레이아웃이 이루어지는 영역으로 이곳에서 블록 박스들이 배치됩니다.

쉽게 말해 화면을 그릴 때 내부영역을 새로 잡아주는 것을 만들어 이 영역에 내부 요소를 잘 담아두기 위해 사용됩니다.

BFC가 만들어지는 조건

  • 문서의 루트 요소 (html)
  • float 속성사용
  • absolutely positioned element - position이 absolute이거나 fixed인 요소
  • inlin-blocks (display: inline-block)
  • Table cell, Table captions, table
  • overflow 값을 auto로 설정하거나 visible이 아닌 다른 값을 설정할 때
  • display flow-root일때
  • button요소와 flow-root로 설정된 input 타입들

BFC를 만드는 방법

위 조건중 하나 이상을 만족시켜주면 됩니다.

 

그래서 overflow를 사용해도 되는가?

여기서 중요한 점은 overflow를 사용할 때는 주의해야할 점이 있는데 overflow는 본래 컨텐츠가 넘쳤을 때 브라우저가 처리하는 방식을 지정하기 위해 사용하는 것이기 때문에 BFC를 생성하기 위해 해당 속성을 사용할 경우 의도치 않은 스크롤바가 나타나거나 그림자가 잘리는 등의 문제가 있을 수 있습니다. 또한 협업에서 overflow의 사용을 명확히 이해못할 가능성이 있기에 해당 방법으로 BFC를 사용하는 경우 주석을 통해 목적을 설명하는 등 몇가지 유의해야할 부분이 있습니다.

 

이러한 부작용을 막기위해선 display속성의 flow-root값을 사용하는 것을 권장합니다.

아래와 같이 이제는 대부분의 브라우저에서 지원해주고 있고 공식문서에서 해당 속성의 용도를 명확히 정의해주고 있습니다.

MDN display flow-root설명

 

 

그럼,, Containg Block은 뭔데??

Containing block이란?

해당 요소가 위치를 기준으로 삼는 조상 요소

하지만 항상 그런것은 아님을 곁들인,,

 

position에 따라 containg block은 다르게 정의됩니다.

 

position: static, relative, sticky - 컨테이닝 블록은 가장 가까운 조상 블록 컨테이너

position: absolute - static을 제외한 position 값을 가지고 있는 가장 가까운 조상 컨테이너

position: fixed - viewport 또는 페이지 영역 전체

 

position: absolute를 의도한 대로 사용하기 위해서 부모 요소에 relative를 주던 것이 Containg Block으로 삼기 위해서 였습니다.

 

💡 백분율을 사용한 width, height, padding, margin 속성과 절대적 위치로 설정된 요소의 오프셋 속성값은 자신의 containing block으로부터 계산됩니다.

 

ex) height, top, bottom 속성은 컨테이닝 블록의 height를 기준으로 백분율 계산

width, left, right, margin, padding은 컨테이닝 블록의 width값을 사용해 백분율 계산

 

body {
  background: beige;
}

section {
  display: block;
  width: 400px;
  height: 160px;
  background: lightgray;
}

p {
  width: 50%; /* == 400px * .5 = 200px */
  height: 25%; /* == 160px * .25 = 40px */
  margin: 5%; /* == 400px * .05 = 20px */
  padding: 5%; /* == 400px * .05 = 20px */
  background: cyan;
}

 

 

이렇게 좋은 동료의 질문으로 제가 가장 많은 공부를 해본 경험을 글로 작성해보았습니다. 꼬리에 꼬리를 물고 알아가다보니 이해도 쉽고 관계를 파악하며 직관적으로 배워볼 수 있어서 좋은 경험이였습니다.

 

Reference

https://developer.mozilla.org/en-US/docs/Web/CSS/position

https://developer.mozilla.org/en-US/docs/Web/CSS/overflow

https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block

https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_display/Block_formatting_context

 

'Front-End > CSS' 카테고리의 다른 글

CSS포지션 (position)  (0) 2022.02.22
Comments