본문 바로가기

Study/CSS

Box & Flex Box

Box Model이란?

box라는 것은 다음 그림과 같이 생겼다.

개발자도구 > element > styles

 

html의 모든 요소는 브라우저 위에서 보여질 때, 위와 같은 box가 된다. 이 box를 이루고 있는 구성 요소에는 margin, border, padding, content이 있다. 모든 box가 이 네가지의 구성요소로 이루어져 있어서 box-model 이라고 부른다.

 

.box {
    margin: 2px;
    border: 1px solid violet;
    padding: 2px;
    width: 50px;
    height: 50px;    
}

 

이런 박스 요소의 너비와 높이는 어떻게 정할 수 있을까? 박스의 가장 내부에 있는 content의 너비와 높이를 박스의 크기로 정할까? 아니면 가장 외부의 margin 까지를 박스의 크기로 정할까? 아니면 padding 이나 border 까지? 이것을 결정하는 것은 box-sizing 이라는 속성이다. 

Box Sizing이란?

box sizing은 CSS의 property 중 하나로,

  • content-box(기본값) 
  • border-box를 value로 갖는다.

 

box sizing이라는 이름에서 잘 나타나 있듯이, 이 속성을 이용하면 어떤 요소, 즉 box의 크기를 재는 방법(sizing)을 결정할 수 있다.

content-box Vs. border-box

content-box

content-box는 우리가 box-sizing 프로퍼티를 이용하지 않으면 기본적으로 적용되는 값이다. 즉, 모든 요소는 기본적으로 content을 기준으로 크기(너비, 높이)가 결정된다. 

 

computed > show all opt select > box-sizing 기본값을 확인해 볼 수 있다

 

content-box는 우리가 생각하는 스타일링을 망가뜨릴 가능성이 크기 때문에 뒤에서 살펴볼 border-box 값을 모든 element에서 사용하는 것이 좋다. 이제 왜 이 속성값이 우리의 스타일링을 망가뜨리는지 살펴보자.

박스의 크기를 content-box 방식으로 정하면, border와 padding은 content-box에 포함되지 않는다. 예를 들어 어떤 요소의 크기를 150*150으로 정했더라도 왼쪽 padding을 20, 오른쪽 padding을 30 주면 실제 요소의 크기는 170*180이 된다. 150*150의 너비와 높이는 요소의 컨텐츠 크기만을 sizing 하기 때문이다. 

 

mdn

 

현재 child container의 width는, parent container 안에 쏙 포함 되도록 100%로 지정되어있다.

 

mdn

 

그런데 border와 padding을 각각 10px, 5px씩 지정해 주자 자식 컨테이너가 부모 바깥으로 튀어나온 것을 볼 수 있다. 이 값들은 content의 바깥을 감싸면서 추가로 더해지기 때문이다.

즉, 우리가 의도했던 부모 컨테이너의 너비(content의 너비) 값에 padding과 border가 더해져 우리가 생각 했던 것보다 박스가 커진다. 이렇게 의도치 않게 스타일링이 망가지는 것을 방지하기 위해서는 border-box라는 속성값을 이용해야 한다.

 

border-box

mdn

 

border-box 값을 이용하면 우리가 설정한 요소의 사이즈(width, height)에 padding과 border가 포함되어 계산된다. 원래는 content이 혼자 다 차지하던 공간을 padding, border가 함께 나누어쓰는 것이기 때문에, 입력할 수 있는 content의 양이 줄어든다는 단점이 있지만, 보통은 border-box를 사용하여 스타일링을 한다.

 

* {
  box-sizing: border-box;
}

 

Box란?

html에서 만들어진 모든 요소들은 브라우저 위에서 render 될 때 box로 표현이 된다. 이 box에는 다양한 type이 존재하는데, 이 type에 따라 기본적인 box model이 작동하는 방식이 달라진다. 모든 html 요소는 display 속성 값을 가지고 있고, 이 값을 이용하면, box의 type을 지정할 수 있다.

 

  • display: block | "막다, 차단하다"의 의미를 갖는다. => area(면)
    • block 요소의 width를 따로 지정하지 않으면, 그 요소는 부모 요소의 content box의 width만큼의 너비를 갖는다. 그렇기 때문에 자동으로 부모 컨테이너에 다른 요소가 채워질 수 없게 blocking할 수 있다. 따로 width를 지정했다면, 남은 공간은 margin으로 자동으로 채움으로써 blocking 한다. => margin: 0 auto; 
    • block 요소의 height을 따로 지정하지 않으면, 그 요소는 모든 자식 요소의 height의 합 만큼의 높이를 갖는다. 

 

inline 값을 갖는 span의 padding top

 

  • display: inline | in line, 안에 있다, 즉 "흐름 안에 있다"는 의미를 갖는다. => line(선)
    • 흐름을 깨뜨리는 width, height과  padding, border, margin의 top, bottom 값을 지정할 수 없다(left와 right 값은 지정할 수 있다). 지정하더라도 위의 사진처럼 영역으로서 의미있는 값을 갖지 못한다. 

 

+) text와 img가 대표적인 inline 요소들인데, img는 특수한 경우로, width와 height을 지정할 수 있다. 따라서 img 태그를 사용할 때에는 width와 height을 그냥 적용할 수 있더라도, display: block을 명시적으로 사용하는 것이 좋다. 

 

inline-block

 

  • display: inline-block | block과 inline의 장점을 조합한 속성 값이다.
    • inline 요소인 span의 display 속성값을 지정해서, span에 block 요소에만 적용할 수 있는 property인 padding top, bottom 값을 조정한다. 
  • display: flex | display를 flex로 지정한 요소를 flex box라고 부른다. 아래의 단계를 거쳐서 사용한다. 
    1. display: flex | 정렬하고 싶은 아이템들의 부모 컨테이너에 flex box 선언
    2. flex-direction | 정렬 방향 결정
      • row(default value), row-reverse, column, column-reverse
      • 정렬 방향이 결정되면 그 방향에 따라(row, column, reverse 여부에 따라) 두 개의 axis가 생긴다 => main & cross axis
      • justify-content | main-axis(row일 때로 가정)에서 아이템을 정렬하는 방법 결정
        • flex-start(왼쪽 정렬, 기본값), flex-end(오른쪽 정렬), center(가운데 정렬) 
        • 요소와 요소 간의 간격 => space-between, space-around, spance-evenly
      • align-items | cross-axis(column일 때로 가정)에서 아이템을 정렬하는 방법 결정, 먼저 적용
        • flex-start(위로 정렬, 기본값), flex-end(아래로 정렬), center(가운데 정렬)
        • 세로 방향으로 여러개의 요소가 있을 때 요소 간의 간격 => space-between, space-around, spance-evenly
      • align-content | cross-axis에서 아이템을 정렬하는 방법 결정, 나중에 적용
        • flex-wrap: wrap일 때 의미있는 속성
        • wrap으로 인해 여러 개의 flex-line이 생겼을 때, 하나의 큰 흐름을 기준으로 아이템을 정렬하고 싶을 때 사용할 수 있다 
      • align-self | align-items와 비슷하지만, 컨테이너의 모든 자식 요소가 아니라 개별 요소에 사용할 때 적용한다.  
    3.  flex-wrap | 모든 아이템을 무조건 한 줄에 정렬할 것인지, 아닌지 결정
      • nowrap(default value), wrap 
      • 기본값을 그대로 적용하면, 자식 요소의 너비를 줄여서라도 부모 요소에 한 줄로 나타낸다.
    4. 자식 요소에 다음 값을 사용할 수도, 안할 수도 있다.
      • order | 컨테이너의 display가 flex 일 때, 각 아이템에 order를 지정해서 배치되는 순서를 정할 수 있다.
      • flex-grow &flex-shrink | flex grow와 shirink를 이용하면, 부모 컨테이너의 크기에 따라 아이템이 줄어들거나, 늘어나는 비율을 지정할 수 있다.
        • flex-grow | flex-grow의 기본값은 0으로, 컨테이너의 크기가 늘어나서 빈 공간이 생겨도 아이템의 크기에는 변함이 없다. 반면 grow를 1로 지정하면, 해당 요소가 컨테이너의 비어있는 공간에 맞게 크기가 늘어난다. 이 값은 요소마다 다르게 지정할 수 있는데, 1로 지정한 요소와 2로 지정한 요소가 있다면, 2로 지정한 요소가 컨테이너의 비어있는 공간을 차지하는 비율은 1로 지정한 요소의 두 배가 된다. 
        • flex-shirink | flex-shirink의 기본값은 1로, 컨테이너가 줄어들면, 아이템이 한 줄에 배치되려고 하기 때문에(flex-wrap의 기본값이 nowrap이기 때문에) 아이템의 크기가 컨테이너의 크기에 맞게 줄어든다. 반면 shirink를 0으로 지정하면 컨테이너의 너비가 줄어들어도 요소의 크기가 줄어들지 않는다. 
      • flex-basis | 요소가 배치될 때 결정되는 최초의 사이즈로, 배치되는 방향과 관련있는 방향의 사이즈 크기(row에서는 width, column에서는 height)를 결정할 수 있다. 
        • auto | 기본값, flex-grow와 shrink에 지정된 값을 따름
        • 40%로 지정하면, 부모 컨테이너의 40%를 차지하게 됨
      • flex | flex-grow, flex-shrink, flex-basis를 한 번에 지정
        • { flex: 1 1 40%; } 

 

flex-wrap: wrap => 두 개의 flex line이 각각의 축을 가지고 있다(좌) align-content: flex-start, align-items과는 달리 두 개의 flex-line이 아니라 하나의 큰 흐름에서 수직축을 기준으로 아이템을 정렬할 수 있다(우)

 

nowrap(좌) wrap(우)

 

 

+) flex box 참고 자료

Basic Concepts of Flex | MDN

그림으로 flex box 이해하기

'Study > CSS' 카테고리의 다른 글

Float & Pseudo Element  (0) 2022.05.18
Responsive Design  (0) 2022.04.26
Transition & Animation  (0) 2022.04.06
Centering  (0) 2022.04.06
Position  (0) 2022.04.06