CSS에서 Flex를 해보자.

2021. 10. 19. 18:21프론트엔드/HTML, CSS, Javascript

728x90

내가 최근에 만들고 있는 페이지인데, 중앙의 리스트만 스크롤하고 싶었다.
그래서 이렇게 저렇게 찾아서 땜빵을 해보는데 잘 안 되서 그냥 근본적으로 접근해보자고 생각했다.


Flex Container

Flex를 쓰기 위해선 컨텐츠들을 담는 컨테이너가 필요하다.

이 컨테이너 역할을 하는 div는 두가지 특성을 설정해주면 된다.

- display: flex;

- flex-direction: row;

display: flex;를 통해 이 div의 하위 컨텐츠는 flex 방식으로 처리하겠다는것을 알리고,

flex-direction을 통해서 flex를 진행하는 방향을 알려준다.

flex-direction의 종류는 다음을 보자.

https://developer.mozilla.org/ko/docs/Web/CSS/flex-direction

 

flex-direction - CSS: Cascading Style Sheets | MDN

flex-direction CSS 속성은 플렉스 컨테이너 내의 아이템을 배치할 때 사용할 주축 및 방향(정방향, 역방향)을 지정합니다.

developer.mozilla.org


Flex Content

이제 컨텐츠들을 설정할 때다.

컨텐츠는 다음의 옵션으로 설정한다.

- flex: 0 1 auto;

이 flex는 세가지 옵션의 축약어인데, 각각 flex-grow, flex-shrink, flex-basis이다.
즉 0 1 auto;란, flex-grow: 0; flex-shrink: 1; flex-basis: auto;와 같다.
기본 값은 위처럼 0 1 auto;이다.

https://developer.mozilla.org/ko/docs/Web/CSS/flex

 

flex - CSS: Cascading Style Sheets | MDN

flex CSS 속성은 하나의 플렉스 아이템이 자신의 컨테이너가 차지하는 공간에 맞추기 위해 크기를 키우거나 줄이는 방법을 설정하는 속성입니다.

developer.mozilla.org

자세한건 위의 링크를 보고, 간단한 사용법을 익혀보자.

우선 화면을 몇 대 몇으로 나눌지 생각해 봐야한다.
만약 내가 세개를 1:2:1로 화면을 분할하고 싶다면, 다음과 같이 설정하면 된다.

<div style="display: flex;">
  <div style="flex: 1;" />
  <div style="flex: 2;" />
  <div style="flex: 1;" />
</div>

실전

이제 내가 쓰는 페이지를 구성해보자. 

여기에 필요한 요소는 다음과 같다.

- 고정 높이를 가진 App Bar (파란색 바탕 영역)

- 아래 전체 영역이 화면을 꽉 채워야 함

- 하단 영역은 좌, 우로 나뉘어야 함

- 좌측 영역은 스크롤이 되어야 함


고정 높이를 가지는 Content

우선 상, 하단으로 분리해야 한다. 해보자.

(html, body는 height: 100%; margin: 0;으로 설정하자)

<div class='column-container'>
  <div class='column1'>먼저 해야하는 걸 보여줘, Worky</div>
  <div class='column2'></div>
</div>
.column-container {
  display: flex;
  height: 100%;
  flex-direction: column;
  background-color: olive;
}

.column1 {
  flex: 0 1 64px;
  background-color: orange;
}

.column2 {
  flex: 1;
  background-color: orangered;
}

html의 구조는
컨테이너(.column-container)안에 두 컨텐츠(.column1, .column2)가 있다.

CSS는 우선 중요한 부분만 뽑아서 보자

.column-container {
  display: flex;
  height: 100%;
  flex-direction: column;
}

.column1 {
  flex: 0 1 64px;
}

.column2 {
  flex: 1 1 auto;
}

우선 container는 높이는 화면 전체, display: flex; 방향은 column(세로)로 설정하였다.

column1이 중요한데, 세번째 속성(flex-basis)가 64px로 설정되었다.
즉, 이 컨텐츠의 기본 사이즈는 64px로 설정이 된다.
그러면서 첫번째 속성(flex-grow)가 0이기 때문에, 비율적으로 늘어나지도 않는다.

column2는 첫번째 속성(flex-grow)가 1이기 때문에,
다른 flex-grow를 가진 컨텐츠가 없기 때문에 1/1, 즉 100%가 된다.

실제 출력 화면은 이렇다.

보다시피 상단 64px를 제외하고는 나머지가 전부 column2의 영역이 된 것을 알 수 있다.


하단 영역 가로로 쪼개기

이제 하단 영역 (column2)를 가로로 쪼개보자.

<div class='column-container'>
  <div class='column1'>먼저 해야하는 걸 보여줘, Worky</div>
  <div class='column2'>
    <div class='row-container'>
      <div class='row1'></div>
      <div class='row2'></div>
    </div>
  </div>
</div>
... 기존 CSS 코드

.row-container {
  display: flex;
  height: 100%;
  flex-direction: row;
  background-color: orchid;
}

.row1 {
  flex: 1;
  background-color: palegreen;
}

.row2 {
  flex: 3;
  background-color: red;
}

세로 쪼개기와 구조가 거의 같다.

flex-direction은 row가 되었고, row1과 2는 1:3이 된 것만 체크하면 되겠다.

실제 화면은 이렇게 된다. 초록(row1)과 빨강(row2)가 1:3의 비율로 분할됨을 알 수 있다.


좌측 영역(초록)에 스크롤 넣기

우선 스크롤을 만들기 위해 다음과 같이 만들어주자

<div class='column-container'>
  <div class='column1'>먼저 해야하는 걸 보여줘, Worky</div>
  <div class='column2'>
    <div class='row-container'>
      <div class='row1'>
      	<div class='list-container'>
          <div>li</div>

           ... 스크롤이 생길때까지 (<div>li</div>)를 복붙해주세요

          <div>li</div>
        </div>
      </div>
      <div class='row2'></div>
    </div>
  </div>
</div>

우선 list-container를 새로 만들어 감싸고, 안에 div를 오지게 넣었다.

자, 이제 스크롤이 생겼지만 전체 페이지에 걸쳐 생기게 되었다.
그리고 별개로 주황영역 (column1)의 영역도 망가졌다.
그 이유는, flex가 처리를 할 때 아랫 영역이 화면보다 길어지면서 주황 영역을 밀어냈기 때문이다.
flex-shrink를 0으로 설정하여 처리할 수 있지만, 다른 방식으로 해보겠다.

왼쪽 영역에만 스크롤이 될 수 있도록 CSS를 적용해주자.

... 기존 CSS 코드

.row1 {
  display: table;
  height: 100%;
}

.list-container {
  height: 100%;
  overflow-y: auto;
}

'갑자기 왜 table이 나오지?' 라고 의문이 들 수 있는데, 나도 정확히는 모른다.
하지만 원리를 알아보면 .row를 table로 만들어서 높이를 고정한 다음,
list-container가 범위를 벗어나는 컴포넌트를 스크롤로 만든다.

실제 결과물이다.


마무리

사실 왜 display를 table로 설정하면 높이가 고정되는지에 대한 원리를 나도 잘 모르겠다.
열심히 찾아봤지만 Document에서도 내부 원리를 설명하지 않는다.
다른 방식으로 시도를 해봤지만 해결이 되진 않았다.

물론 브라우저를 뜯어보면 되겠지만 당장은 프로젝트에 집중하기로 했다.
다소 아쉽다.