본문 바로가기

Front-end/HTML, CSS

Flex Box를 이용한 안정적인 그리드 레이아웃 제작

강사님이 운영중이신 영화관 웹사이트... 메인 요소 안 영화 정보와 사이드바로 구분된 레이아웃이 흥미롭다.

 

이런 페이지에서 중요한 것은 컨텐츠의 크기 변화, 또는 다양한 디바이스 너비에서도 안정적으로 유지되는 레이아웃의 설계

 

천천히 만들어 가 보자. 🐢


1. 메인 영역 안에서 영화 정보와 사이드바의 구분

우선 flex box의 속성을 이용하여 컨테이너를 168px로 고정된 사이드바와, 나머지 너비를 차지하는 메인 영역으로 나눈다.

 

<main class="contents">
    <div class="l_wrapper">
      <div class="container">
        <div class="container-main">MAIN</div>
        <div class="container-sidebar">Side bar</div>
      </div>
    </div>
  </main>

index.html

.container {
  box-shadow: inset 0 0 30px gold;
  display: flex;
  gap: 24px;
  min-height: 848px;
}

.container-main {
  box-shadow: inset 0 0 20px purple;
  flex-grow: 1;
}

.container-sidebar {
  box-shadow: inset 0 0 20px pink;
  width: 168px;
  height: 283px;
}

style.css

 

1. container에 flex 속성을 주어 container-main과 container-sidebar를 flex-item으로 만든다.

 

2. sidebar의 너비와 높이를 지정하고, main의 flex-grow에 1 값을 주어 컨테이너의 가용공간을 main의 너비에 더해준다.

flex-grow 사용 전 (flex-grow: 0)
flex-grow: 1

이제 컨텐츠를 채우면 될 것 같은데... 레이아웃 설계는 그리 만만치 않다.

 

우리는 미래의 돌발상황에도 무너지지 않는 안정적인 코드를 작성해야 한다.

현상금 10억 베리의 프론트엔드 개발자

 

그럼 flex box를 사용할때 자주 발생하는 문제와 그 해결법을 알아보자.

2-1. flex item의 너비는 컨텐츠의 양에 따라 자동으로 조정된다. 

이전 코드에서 의도적으로 container-main의 컨텐츠를 늘여보았다.

 

그럼 해당 아이템이 컨테이너에서 차지하는 공간도 함께 늘어남에 따라 sidebar의 공간은 줄어듦을 확인할 수 있다.

 

근본적인 이유는 flex item의 flex-basis 속성이 초기값 auto를 가지고 있기 때문인데, 

 

이것은 아이템의 너비가 컨텐츠 양과 함께 늘어나는 것을 의미한다.

 

따라서 이 문제의 해결 방법은 다음과 같다.

  1. container-main에 flex-basis: 0 주기
  2. container-sidebar에 flex-shrink: 0 주기
  3. container-sidebar에 min-width: 168px 주기

1번은 flex-basis 값을 0으로 만들어 container-main의 너비가 컨텐츠의 양에 영향받지 않게 하는 것이고,

 

2과 3번은 container-main의 너비 변화에 관계없이 container-sidebar의 너비가 변하지 않게 고정하는 방법이다. 

sidebar의 너비가 잘 고정되었다.

2-2. flex item이 길이가 긴 컨텐츠(이미지, 단어)를 가지고 있을 때 flex container 외부로 오버플로우가 발생한다.

sidebar의 flex-shirnk 0인 상태에서의 오버플로우

이를 해결하기 위해선 flex-basis에 대한 이해가 필요하다.

 

flex-basis는 flex item의 너비를 결정하는 속성이고, 앞서 말했듯 초깃값인 auto 상태에서는 컨텐츠의 크기에 따라 너비가 맞춰진다.

 

하지만 flex-basis의 값이 0인 경우, flex item의 너비는 0이 되지 않는데, 그 이유는 아이템의 min-width이 초깃값 auto로 컨텐츠의 크기만큼 계산되어있기 때문이다.

 

flex-basis: 0의 공격을 막는 min-width: 0

 

따라서 flex-basis: 0과 min-width: 0을 동시에 주면, flex tem는 너비가 0부터 계산되면서  flex-grow의 영향만을 받게된다.

사라진 오버플로우

*flex item의 경우 width: 0으로 flex-basis: 0과 min-wdith: 0을 동시에 나타낼 수 있다.


다음은 contents 그리드를 반응형으로 만드는 방법이다.

 

페이지 너비와 함께 아이템도 같이 줄어들다가, 특정 뷰포트(태블릿, 모바일)에서 열의 개수가 줄어들어 글을 더 읽기 쉽게 만들 수 있다.

<main class="contents">
  <div class="l_wrapper">
    <div class="container">
      <div class="container-main">
        <ul class="l_row">
          <li class="l_col">
            <section class="card">A</section>
          </li>
          <li class="l_col">
            <section class="card">B</section>
          </li>
          <li class="l_col">
            <section class="card">C</section>
          </li>
        </ul>
      </div>
    </div>
  </div>
</main>

index.html

.l_row {
  background-color: yellow;
  display: flex;
  flex-wrap: wrap;
  gap: 24px
}

.l_col {
  flex-basis: 320px;
  flex-grow: 1;
}

.card {
  color: black;
  background-color: limegreen;
}

style.css

 

ul과 li를 이용해 레이아웃을 마크업 하고, 아이템(l_col)에 flex-grow: 1을 주면 컨테이너의 여백 공간이 같은 비율로 나누어져 아이템의 너비(flex-basis)에 더해진다. (3등분 된다.)

flex-grow를 이용한 그리드 1

아이템은 320px의 basis를 가지고 있고, flex-wrap 때문에 페이지가 줄어들면 아이템이 다음 줄로 내려오게 되는데, 여기에도 flex-grow가 적용되어 아이템이 컨테이너 너비를 꽉 채우게 된다.

flex-grow를 이용한 그리드 2

 

하지만 우리가 원하는 레이아웃은 각 아이템들의 너비가 같아야 하므로 width 속성을 사용해야 한다.


width: calc(100% / 3)는 컨테이너의 너비를 3등분 한다는 뜻이다.

 

여백을 위해 각 아이템에 gap: 24px를 줄 경우 아이템 너비와 gap의 합이 컨테이너 너비를 벗어나 wrap된다.

 

그 대신 l_col에 패딩을 주고, l_row에 그 반절만큼 네거티브 마진을 주어 시각적으로 여백이 나타나게 할 수 있다.

.l_row {
  background-color: yellow;
  display: flex;
  flex-wrap: wrap;
  row-gap: 24px;
  margin: 0 -12px;
}

.l_col {
  width: calc(100% / 3);
  padding: 0 12px;
  /* width가 padding을 포함하여 계산 */
  box-sizing: border-box;
}

.card {
  color: black;
  background-color: limegreen;
}

style.css

width를 이용한 3등분

 

이제 아이템의 개수가 늘어나더라도 너비가 컨테이너의 1/3로 고정되는 것을 확인할 수 있다.

 

만약 특정 아이템이 차지하는 너비 비율을 바꾸고 싶다면, 클래스를 주어 선택자 안에 width의 값을 조정하면 된다. (미디어 쿼리에도 사용하면 페이지 너비에 따라 그리드의 열 개수가 바뀌게 할 수 있다.)

 

보통 총 너비를 12분할하여 원하는 만큼 사용하는 12 column grid가 자주 사용된다.

12 column grid

.l_col_12_12 {
  width: 100%;
}
.l_col_11_12 {
  width: 91.66666667%;
}
.l_col_10_12 {
  width: 83.33333333%;
}
.l_col_9_12 {
  width: 75%;
}
.l_col_8_12 {
  width: 66.66666667%;
}
.l_col_7_12 {
  width: 58.33333333%;
}
.l_col_6_12 {
  width: 50%;
}
.l_col_5_12 {
  width: 41.66666667%;
}
.l_col_4_12 {
  width: 33.33333333%;
}
.l_col_3_12 {
  width: 25%;
}
.l_col_2_12 {
  width: 16.66666667%;
}
.l_col_1_12 {
  width: 8.33333333%;
}

반응형 피카츄

 

'Front-end > HTML, CSS' 카테고리의 다른 글

image 사이의 여백 - 인라인 요소의 vertical-align  (0) 2024.07.27
getBoundingClientRect  (0) 2024.02.04
HTML 특수문자표  (0) 2024.01.26
grid 기본  (0) 2024.01.17
flex의 align-self, align-item과 align-content의 차이  (0) 2024.01.17