함께 성장하는 프로독학러

CSS - 레이아웃을 위한 스타일 도구, flex 본문

Programming/HTML_CSS

CSS - 레이아웃을 위한 스타일 도구, flex

프로독학러 2018. 5. 21. 15:19

안녕하세요, 프로독학러 입니다.


이번 포스팅에서는 CSS 의 레이아웃을 위한 도구 중 하나인 flex 에 대해서 알아보도록 하겠습니다.


* 본 포스팅의 내용은 생활코딩의 flex 강의를 복습한 내용입니다. 생활코딩에서 직접 강의를 수강하고 싶으신 분들은 아래의 링크를 참조해 주세요

https://opentutorials.org/course/2418/13526


이전에는,


flex 가 생기기 이전에는 레이아웃을 만들기 위해 table 을 사용하거나, position, float 등을 이용했습니다.


물론 위의 방법들을 통해서도 원하는 레이아웃을 만들 수 있지만, 이는 원래의 목적에 반하는 코딩을 하는 것이었습니다.


table 은 표를 위한 도구이며, 이는 정보를 의미합니다. 

정보를 위해 만들어진 도구를 디자인에 활용하면, 검색엔진이나 스크린 리더 등의 HTML 코드를 해석하는 소프트웨어가 정보와 디자인을 구분하는 것이 힘들게 되어 사용자에게 제대로 정보를 전달해 주지 못하는 경우가 생깁니다.

또한, 코드 자체가 복잡해져서 유지보수 측면에서도 좋지 않은 방법입니다.


position 을 이용하면 relative, absolute 등을 이용해 요소를 이동시켜야 하는데, 이는 사용자의 접근환경에 따라 원치 않는 모습으로 구현될 수 있는 단점이 있습니다.


float 의 원래 목적 역시 디자인을 위한 것이 아닌 이미지 옆에 글씨가 흘러가도록 하는데 것입니다.


따라서, 레이아웃과 디자인을 위한 스타일 도구의 필요성이 계속해서 부각되었고, 그 결과 flex 라는 레이아웃을 위한 도구가 등장하게 되었습니다.


flex 조건


flex 를 사용하기 위해서는 기본적으로 알아야 할 내용이 몇 가지 있습니다.


컨테이너 태그, 아이템 태그


flex 를 사용하기 위해서는 최소 두 개 이상의 태그가 필요합니다.

컨테이너 역할을 하는 태그와 자식 역할을 하는 아이템 태그가 필요합니다.

이를 다른 말로 하자면, 정렬하고자 하는 아이템 태그들은 컨테이너 역할을 하는 태그로 감싸져 있어야 한다는 것입니다.


1
2
3
4
<container>
    <item>item1</item>
    <item>item1</item>
</container>
cs


이런 형태로 말이죠.

그렇다고 해서 HTML 태그의 이름이 container, item 인 것은 아닙니다.

클래스나 아이디등을 통해서 태그에 container 태그에 주는 속성을 주고, item 태그에 주는 속성을 주면 됩니다.


컨테이너와 아이템 태그의 속성


컨테이너 태그와 아이템 태그에는 각각 줄 수 있는 속성이 구분되어 있습니다.


container 태그에만 줄 수 있는 속성 

item 태그에만 줄 수 있는 속성

  display

  order 

  flex-direction

  flex-grow 

  flex-wrap

  flex-shrink 

  flex-flow

  flex-basis 

  justify-content

  flex 

  align-items

  align-self 

  align-content

 


flex Basic (컨테이너 속성)


그럼 본격적으로 flex 에 대해서 알아보도록 하겠습니다.


flex 를 적용시키려면 컨테이너 역할을 수행하는 태그에 display:flex; 스타일을 적용시켜 주어야 합니다.


그리고 컨테이너 태그에 flex-direction 스타일의 값에 따라 컨테이너 안의 아이템들이 정렬되는 방향을 결정합니다.


row : 가로 정렬, 왼쪽에서 오른쪽으로 정렬

row-reverse : 가로 정렬, 오른쪽에서 왼쪽으로 정렬

column : 세로방향 정렬, 위에서 아래로 정렬

column-reverse : 세로 정렬, 아래에서 위로 정렬


코드를 통해 테스트 해 보겠습니다.

테스트는 코드펜에서 진행하도록 하겠습니다.


코드펜 - https://codepen.io/pen/


위의 링크를 통해 코드펜의 새로운 프로젝트를 만들어봅시다.


HTML 코드 부분에 아래의 코드를 붙여 넣어봅시다.


1
2
3
4
5
6
7
<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
</div>
cs


그리고 CSS 부분에는 아래의 스타일 코드를 붙여넣습니다.


1
2
3
4
5
6
7
8
9
10
11
        .container{
            background-color: powderblue;
            height:200px;
            display:flex;
            flex-direction:row;
        }
        .item{
            background-color: tomato;
            color:white;
            border:1px solid white;
        }
cs


HTML 과 CSS 를 입력하면 아래에 위와 같이 flex 가 적용된 모습이 나타납니다.

container 태그와 item 태그 모두 div 태그를 이용했으며, class 를 통해 태그를 구분지어 flex 속성을 주었습니다.


CSS 에서 .container 부분을 수정해 봅시다. flex-direction 을 row-reverse; 로 변경해 봅시다.



item 태그들이 오른쪽에서 왼쪽으로 정렬되는 것을 볼 수 있습니다. 


flex-direction 속성을 column 으로 변경하면, 아래 그림과 같이 item 태그들이 정렬됩니다.



여기서 주목할 점은, flex-direction 이 어떤 방향이던 그의 반대 방향전체를 사용한다는 점입니다.


*row 일 때는 height 전체를 사용, column 일 때는 width 전체를 사용


flex - basis / grow & shrink (아이템 속성)


이제 아이템 태그에 적용하는 기본적인 속성에 대해 알아보도록 하겠습니다.


flex-basis


flex-basis 속성은 item 의 크기를 지정하는 속성입니다. px 이나 rem 등으로 크기를 직접 지정합니다.


코드펜의 CSS 부분을 아래와 같이 수정해 봅시다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
        .container{
            background-color: powderblue;
            height:200px;
            display:flex;
            flex-direction:row;
        }
        .item{
            background-color: tomato;
            color:white;
            border:1px solid white;         
        }
        .item:nth-child(1){
            flex-basis: 150px;
        }
cs


12번째 줄에서 첫 번째 자식에게 flex-basis 값으로  150px 을 주었습니다. 결과는 다음 그림과 같습니다.



첫 번째 자식에만 크기가 지정된 것을 알 수 있습니다.


flex-gorw


flex-gorw 속성은 item 의 크기를 늘려서(grow) 컨테이너의 폭이나 높이를 여백없이 다 사용하는 속성입니다.

(flex-direction 이 row 계열이면 아이템들의 크기를 늘려 컨테이너 전체의 폭을 사용, column 계열이면 컨테이너 전체의 높이를 사용)

속성값으로는 숫자가 오는데, 이는 비율을 의미 합니다.


이를 코드를 통해 확인해 보도록합시다.


CSS 를 아래와 같이 수정해봅시다.


1
2
3
4
5
6
7
8
9
10
11
12
        .container{
            background-color: powderblue;
            height:200px;
            display:flex;
            flex-direction:row;
        }
        .item{
            background-color: tomato;
            color:white;
            border:1px solid white;
            flex-grow:1;
        }
cs


결과는 다음과 같습니다.



아이템들이 자신의 크기를 늘려서 컨테이너의 전체 폭을 다 사용했습니다.

모든 값이 1이라면 모두 같은 비율로 자신을 늘린다는 의미입니다.


만약 한 아이템의 flex-grow 값이 2라면 어떻게 될까요?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        .container{
            background-color: powderblue;
            height:200px;
            display:flex;
            flex-direction:row;
        }
        .item{
            background-color: tomato;
            color:white;
            border:1px solid white;
            flex-grow:1;
        }
        .item:nth-child(3){
            flex-grow:2;
        }
cs


위와 같이 CSS 부분을 수정해 봅시다. 전체 아이템 태그의 flex-grow 값은 1이지만, 3번째 아이템의 flex-grow 값은 2로 지정했습니다.

결과는 다음과 같습니다.



세 번째 아이템만 다른 아이템의 두배 비율로 grow 했습니다.


이는 1+1+2+1+1 로 이해하면 좀 더 이해가 빠를 것입니다.

(각 아이템들의 flex-grow 값을 더하면 전체 컨테이너의 크기)


flex-shrink


flex-shrink 속성은 flex-basis 속성을 가진 아이템 태그가 화면(view port)이 줄어듦에 따라 자신을 줄이는 정도를 지정하는 속성입니다.


값이 0이면 뷰포트가 줄어들더라도 자신의 크기를 줄이지 않습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        .container{
            background-color: powderblue;
            height:200px;
            display:flex;
            flex-direction:row;
        }
        .item{
            background-color: tomato;
            color:white;
            border:1px solid white;
            flex-grow:1;
        }
        .item:nth-child(1){
            flex-basis:350px;
            flex-shrink:0;
        }
cs


CSS 를 위와 같이 수정하고, 뷰포트를 줄여봅시다.


위 그림은 뷰포트가 650px 일 때의 모습입니다.



뷰포트를 405px 까지 줄였을 때의 모습입니다.

첫 번째 아이템을 제외한 나머지 아이템들이 자신의 크기를 줄여 컨테이너 전체의 크기를 줄이고 있습니다.


계속해서 뷰포트의 크기를 줄이자, flex-shrink 값이 적용되지 않은 아이템들은 뷰포트 밖으로 밀려나 보이지 않게 되버리지만, flex-shrink 값을 0으로 준 첫 번째 아이템을 끝까지 자신의 basis 크기를 유지하는 것을 알 수 있습니다.


flex-shrink 값이 1 이상이면, 자신의 크기를 줄이기 시작합니다.

만약 flex-shrink 값을 여러 아이템이 1, 2 와 같이 나눠 가지고 있다면, 1을 가진 아이템은 1/3 만큼 자신을 줄이고, 2를 가진 아이템은 자신을 2/3 만큼 줄입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        .container{
            background-color: powderblue;
            height:200px;
            display:flex;
            flex-direction:row;
        }
        .item{
            background-color: tomato;
            color:white;
            border:1px solid white;
            flex-grow:1;
        }
        .item:nth-child(1){
            flex-basis:350px;
            flex-shrink:2;
        }
        .item:nth-child(2){
            flex-basis:150px;
            flex-shrink:1;
        }
cs


위의 코드를 CSS 부분에 붙여넣고 뷰포트를 조절해 가면서 확인해 봅시다.

flex-shrink 값이 높은 첫 번째 아이템이 두 번째 아이템보다 자신을 더 많이 줄이는 것을 알 수 있습니다.


Holy Grail layout


지금까지 배웠던 flex 의 개념을 이용하면, 웹 어플리케이션에 가장 많이 사용되는 Holy Grail 레이아웃을 간단하고 깔끔하게 구현할 수 있습니다.


Holy Grail 레이아웃은 아래그림과 같은 레이아웃을 말합니다.



위와 같은 레이아웃을 구현하려면 flex 를 두 번 적용하면 되는데, header, (nav, main, ad), footer 를 컨테이너로 감싸고 flex-direction 을 column 으로 주고, nav, main, ad 를 다시 컨테이너로 감싸고 flex-direction 을 row 로 주면 됩니다.


코드펜의 HTML 에 다음과 같이 HTML 코드를 작성해 봅시다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    <div class="container">
        <header>
            <h1>생활코딩</h1>
        </header>
        <section class="content">
            <nav>
                <ul>
                    <li>html</li>
                    <li>css</li>
                    <li>javascript</li>
                </ul>
            </nav>
            <main>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem. Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc,
            </main>
            <aside>
                AD
            </aside>
        </section>
        <footer>
            <a href="https://opentutorials.org/course/1">홈페이지</a>
        </footer>
    </div>
cs


CSS 부분에는 아래의 코드를 작성합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
        .container{
            display: flex;
            flex-direction: column;
        }
        header{
            border-bottom:1px solid gray;
            padding-left:20px;
        }
        footer{
            border-top:1px solid gray;
            padding:20px;
            text-align: center;
        }
        .content{
            display:flex;
        }
        .content nav{
            border-right:1px solid gray;
        }
        .content aside{
            border-left:1px solid gray;    
        }
        nav, aside{
            flex-basis: 150px;
            flex-shrink: 0;
        }
        main{
            padding:10px;
        }
cs


그러면 아래 그림과 같이 Holy Grail 레이아웃이 만들어 집니다.


flex의 기타 속성들


위에서 알아본 속성 이외에도 여러가지 flex 관련 속성들이 있습니다.

이는 아래의 소스를 통해 인터렉티브 하게 알아보면 쉽습니다.



여기까지...


CSS 의 레이아웃을 위한 도구 flex 에 대해서 알아보았습니다.


감사합니다.


**참고 자료 (항상 감사드립니다)

https://opentutorials.org/course/2418/13526


*이 포스팅이 도움이 되셨다면 다녀가셨다는 표시로 공감 부탁드릴게요! (로그인 하지 않으셔도 공감은 가능합니다 ㅎㅎ)

Comments