brunch

You can make anything
by writing

C.S.Lewis

by 조은 Dec 27. 2016

웹 레이아웃

CSS Box부터 Position까지

CSS로 레이아웃을 짜는 방법은 아주 다양하다. HTML의 구조를 어떻게 하느냐에 따라서도 레이아웃을 짜는 방법이 달라지며 브라우저 지원율이 어느 정도냐에 따라서도 레이아웃을 짜는 방법은 달라진다. 전통적인 잘못된 방법 중 하나는 Table Layout을 이용하는 것이지만 이메일 같은 곳에서는 여전히 그런 레이아웃을 사용하기도 한다.


이번 글에서는 CSS를 이용해서 레이아웃을 어떻게 짜임새 있게 구성할 수 있는지 알아본다. 다만 여기에 나오는 모든 방법이 정답은 아니기 때문에 여러분들만의 방법을 찾을 수 있다면 그렇게 하는 걸 추천한다.


이 글은 기존에 HTML / CSS가 어떤 일을 하며, 서로 간 어떻게 결합하는지에 대해 어느 정도 아는 사람을 기준으로 작성한다. 아래 예제에서 대문자로 쓴 것과 소문자로 쓴 것은 편집상 가독성을 위해 그렇게 한 것이므로 실제 작성 시에는 소문자로 통일해도 크게 무관하다.


[TOC]

1. BOX

2. BLOCKINLINE

3. FLOAT LAYOUT

4. FLEXBOX LAYOUT

5. POSITION


BOX

모든 HTML 요소는 사각형 박스(box) 형태를 취하고 있다. 실제로 CSS3에 접어들면서 border-radius 같이 원형으로 보이는 효과를 낼 수는 있지만 실제 박스가 원형이 된 게 아니라 그렇게 보이는 것뿐임에 유의하여야 한다.


박스는 BOX-MODEL이라는 모델을 가지고 있으며, 이 모델에 따라서 그 크기를 정한다.

Box dimensions (CSS 2.1)


한 박스를 이루는 구성요소로는 크기의 근간이 되는 콘텐츠(Content), 너비(width), 높이(height)를 가장 먼저 떠올릴 수 있다. 이때 주의해야 하는 점은 높이를 고정값으로 지정할 경우 콘텐츠의 길이가 넘칠 경우 박스의 바깥쪽으로 넘친다는 점이다. 패딩(padding)은 외곽선(border)과 콘텐츠 사이의 간격을 지정하며, 마진(margin)은 박스 외부 간격을 정의한다는 점에 그 차이를 두고 있다.


모델에 따라 실제로 보이는 박스의 가로 크기는 너비(width) + 좌측 패딩(padding-left) + 우측 패딩(padding-right) + 좌측 외곽선(border-left) + 우측 외곽선(border-right)을 더한 값이 된다.

마찬가지로 세로 크기는 높이(height) + 상단 패딩(padding-top) + 하단 패딩(padding-bottom) + 상단 외곽선(border-top) + 하단 외곽선(border-bottom)을 더한 값이 된다.


예를 들어 아래와 같은 CSS가 있다면,

div {

  width: 150px;

  height: 150px;

  border:1px solid #ddd;

  padding:15px; /* padding: <top> <right> <bottom> <left>를 축약형으로 쓴 것이다 */

  margin:15px; /* margin: <top> <right> <bottom> <left>를 축약형으로 쓴 것이다 */

}


위 div의 가로 사이즈는 150 + 2 + 30으로 182px / 세로 사이즈는 150 + 2 + 30으로 182px이다. 여기에 실제 레이아웃 계산 시에는 margin도 더해 계산하기 때문에 한 박스당 212px을 가지고 있다고 생각해도 크게 무관하다.


브라우저에서 모든 요소의 기본 배경색은 투명(transparent)이기 때문에 패딩과 마진 간 차이가 없어 보일 수 있지만, 요소에 배경색을 지정하는 경우 그 차이는 명확히 드러나므로 위 이미지를 참고하여 패딩과 마진 간 차이를 잘 이해해보도록 하자.


BLOCK과 INLINE

모든 HTML 요소에는 display라는 속성이 존재한다. display는 뜻 그대로 이 HTML 요소가 어떻게 화면에 보일지 결정하는데 이 속성 값을 크게 BLOCK과 INLINE으로 나눌 수 있다. 물론 더 상세히 나누면 TABLE 관련 display, RUBY 관련 display, 추후에 다룰 FLEXBOX 관련 display 등 다양한 것들이 존재하지만 우선은 BLOCK과 INLINE에 대해 명확히 아는 게 도움이 된다.


BLOCK

display:block 블록 레벨 요소(Block-level elements)를 나타낸다. 블록 레벨 요소는 블록처럼 보이는 요소를 나타내며, 대표적으로는 P요소나 DIV요소가 있다. 여기서 블록처럼 보인다는 건 내부 콘텐츠의 길이와는 상관없이 수직으로 계속 쌓이는 형태를 의미한다.


블록 레벨 요소는 블록 서식 문맥(block formatting context)에 속하는 박스이며, 각 블록 레벨 요소는 자식 박스 및 생성된 콘텐츠를 포함하는 주요 블록 레벨 박스(principal block-level box)를 생성하며 모든 위치 지정 스킴에 관련한다.


테이블 같은 몇 가지 특수한 케이스를 제외한 블록 레벨 박스는 블록 컨테이너 박스(block container box)이며, 블록 컨테이너 박스는 인라인 레벨 박스(추후에 다룸)블록 레벨 박스를 포함할 수 있다. 블록 컨테이너면서 블록 레벨 박스를 블록 박스라고 부른다.


INLINE

display:inline 혹은 display:inline-block 인라인 레벨 요소(Inline-level elements)를 나타낸다. 인라인 레벨 요소는 콘텐츠 라인 내에 존재하며, 대표적으로는 span이나 img 등이 있다.


인라인 레벨 요소는 인라인 레벨 박스(inline-level box)를 생성하며, 이는 인라인 서식 문맥(inline formatting context)에 속하는 박스다. 인라인 서식 문맥인라인 레벨 박스를 포함할 수 있다.


인라인 레벨 박스에서 유의해야 할 점 중 하나는, 인라인 레벨 박스에 border나 padding이 눈에 보이더라도 line-height에 의해 높이가 조절된다는 점에 주의하길 바란다. 즉, 인라인 레벨 박스에 padding-top:10px; padding-bottom:10px을 넣었다고 하더라도 그렇게 보이기만 할 뿐 실제 그 높이가 바뀌는 건 아니다.


여기서 inline-block이라는 다소 특이한 게 나타나는데, 이 displayinline 요소처럼 한 줄에 나타나지만 block 박스처럼 그 높이를 계산한다. 즉 line-height에 의존하는 게 아닌 기존 블록 레벨 박스와 동일하게 보여준다.


여러 상황에서 유용하게 쓰이지만 inline-block으로 레이아웃을 구성하는 경우 코드 상의 띄어쓰기(white-space)만큼 사이 간격이 발생한다. 즉 margin-left나 margin-right로 사이 간격을 주더라도 띄어쓰기가 발생하면서 임의의 간격이 더 생길 수 있고 이 간격은 font-size에 의해 달라지기 때문에 케이스별로 상이하다.


이런 케이스를 막기 위해 다양한 방법을 쓸 수 있으나 거의 대부분은 편법이므로 반드시 사용해야 하는 상황에서만 사용하는 걸 권장한다. 본인은 HTML을 다 작성한 후 코드 압축기를 활용하여 HTML 코드의 공백 문자를 제거하는 방법을 사용하기도 하였다.


FLOAT LAYOUT

CSS Float 속성을 이용한 레이아웃 구성 방법은 아마 가장 전통적이고 오래된 레이아웃 구성 방법 이리라 생각한다. 실제 현재까지도 꽤 많은 사이트에서 Float를 이용해 레이아웃을 구성하고 있으며 만약 본인의 사이트가 IE까지 대응해야 한다고 하면 Float 속성을 이용하는 것이 유지보수 측면에서나 지원율에서나 좋다.


기본적인 블록 박스와 인라인 박스는 일반 흐름(Normal flow)에 따른다. 일반 흐름이라는 건 박스가 위에서부터 아래로, 좌에서 우로 꾸준히 쌓여나가는 형태이며 정상적인 흐름에 따를 경우 레이아웃이 틀어지지 않고 아름답게 보인다.



Float 속성은 원래 이미지 옆에 텍스트를 꽉 채워서 넣고 싶어서 사용하는 것이었다.


예를 들어 현재 좌측에 우리 집 시골 강아지인 황구인데 황구는 아주 잘생겼다.


다른 이름을 가지고 있었던 거 같은 기분도 들지만 나한테는 어찌 되었던 황구라는 이름이다. 황구는 귀엽기 때문이다.



Float 속성은 이렇게 원래 이미지가 좌측이나 우측에 있고 그 옆에 텍스트를 채우고 싶을 때 사용하는 CSS 속성이다. Float 속성을 지정하지 않아도 이미지는 마찬가지로 텍스트와 같이 뜨지만, 이미지 옆에는 한 줄의 텍스트만 나타난다.


이런 Float 속성을 잘 이용하면 블록 박스의 기본 형질인 위에서부터 아래로 쌓이는 형태가 아닌 좌에서 우로 쌓이는, 혹은 우에서 좌로 쌓이는 형태의 레이아웃을 구현할 수 있다. 이렇게 Float 속성을 사용해 구현하는 레이아웃을 Float 레이아웃이라고 부른다.


Float는 일반 흐름(Normal Flow)에 존재하지 않기 때문에 Float 박스의 이전 / 다음(before / after) 블록 박스는 Float가 존재하지 않는 것처럼 쌓이며, Float 옆에 생성된 라인 박스는 필요에 따라 Float의 margin box를 위한 공간을 만든다. 만약 Float 옆에 생성된 라인 박스가 나타내기에 충분한 공간을 가지고 있지 않다면 그 내용은 text-align 속성에 따라 박스 아래로 이동한다.


위를 바탕으로 (1) Float 박스를 포함하고 있는 부모 요소는 Float 박스가 일반 흐름에 존재하지 않기 때문에 Float 박스의 높이를 알 수 없다. (2) Float 박스 옆에 생성된 라인 박스는 충분한 공간을 가져야 한다. 를 알 수 있다.


예제 1. Float 박스가 Flow 박스를 넘치고 있다.

예제(1) Float 박스를 포함하고 있는 부모 요소는 Float 박스가 일반 흐름에 존재하지 않기 때문에 Float 박스의 높이를 알 수 없다. 상황을 재현하는 예제이다.


Float 콘텐츠는 Float가 새로운 쌓임 문맥(New stacking context)을 생성한 것처럼 쌓인다. 실제로 새로운 쌓임 문맥은 Float의 부모 쌓임 문맥(Parent stacking context)에 포함된다. Float는 일반 흐름에서 다른 박스와 겹칠 수 있으며, 이 경우 Float는 position 되지 않은 flow 내 블록 앞이나 flow 내 인라인 뒤에 렌더링 된다.


위 같은 경우 의도하였다면 올바른 레이아웃이라 판단할 수 있겠지만, 대부분은 의도하지 않은 상황에서 위 같은 문제를 겪게 된다. 부모 박스의 border를 넘어서는 상황 및 다른 박스의 border를 가리는 상황은 대체로 의도하지 않은 상황인 경우가 많으며 이런 경우를 해소하기 위해 다양한 노력을 할 수 있다. 이런 문제가 생기는 가장 큰 이유는 Float 박스가 Float만의 새로운 쌓임 문맥을 가지고 있기 때문이다.


클리어픽스

클리어픽스(clearfix)는 위와 같은 Float 레이아웃에서 부모 요소가 높이를 계산하지 못하는 이슈를 해결하기 위한 다양한 해결방법을 제안한다. 보통 4개 방법을 제안하지만 여기서는 가장 효율적인 한 가지 방법을 제안한다.


.clearfix:after {

  content:'';

  display:block;

  clear:both; /* 이 요소보다 앞에 있는 Float가 가진 자체 흐름을 normal flow로 해체해준다 */

}


위 CSS는 clearfix라는 클래스(.clearfix)를 가진 요소에 가상 요소 셀렉터(:after)를 사용하여 모든 콘텐츠의 마지막 부분에 임의의 요소를 생성하여 넣어준다. 가상 요소 셀렉터는 CSS2 문법(:after)과 CSS3 문법 (::after)이 있는데 CSS2 문법이 IE8까지 지원하기 때문에 PC까지 대응해야 하는 경우에는 CSS2 문법을 사용하는 걸 권장한다.


이 클래스는 Float 박스를 포함하는 부모 요소에 넣어주어야 하며, 부모 요소에 넣어서 정상적으로 작동하는 경우 Float 요소의 자체 흐름을 해체하여 부모 요소가 일반 흐름인 가상 요소를 인식하여 높이를 제대로 계산할 수 있게 한다.


예제 2. clearfix가 들어가 높이를 제대로 인식하는 박스

예제 2는 Float 박스를 가진 요소의 부모 요소에 clearfix 기법을 적용시켜서 Float 박스의 높이를 인식시키는 예제다. Float 레이아웃을 작성함에 있어 가장 깔끔한 방법이라고 본인은 생각한다.


FLEXBOX LAYOUT

플렉스 박스(Flexbox) 혹은 플렉시블 박스 (Flexible box) 혹은 플렉스(Flex) 레이아웃은 유저 인터페이스 디자인을 위해 최적화된 CSS 박스 모델이다.


플렉스 레이아웃 모델(flex layout model)에서는, 플렉스 컨테이너의 자식 요소를 모든 방향으로 배치 가능하고, 사용하지 않는 공간을 채우기 위해 자식 크기를 키우거나, 부모 영역을 넘치는 걸 피하기 위해 자식 크기를 줄일 수도 있다.


또한 자식 요소의 수평 / 수직 정렬 모두 쉽게 할 수 있고, Flex 박스를 중첩하여 다차원 레이아웃을 구현할 수도 있다. (가로로 쌓이지만 내부는 세로거나, 세로로 쌓이지만 내부는 가로거나)


플렉스 레이아웃은 크게 플렉스 컨테이너(Flex container)와 그 자식 요소인 플렉스 아이템(Flex item)으로 이루어진다. 플렉스 컨테이너는 display:flexdisplay:inline-flex 속성을 가진 특정 요소이며, 블록이나 인라인 레이아웃과 달리 플렉스 방향(flex direction)에 기초하여 레이아웃을 구성한다.


flexbox가 최근에 나온 스펙이기 때문에 여러 브라우저에서 지원하기 위해서는 벤더 접두사(vendor prefix)를 붙여야 하며, 벤더 접두사는 각 브라우저 제조사에서 최신 스펙을 먼저 지원하기 위해 붙이는 접두사다. 위 display 속성을 대부분의 모던 브라우저에서 지원하기 위해서는 아래와 같이 코드를 작성해야 한다.


.flex {

  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -moz-flex;
  display: -webkit-flex;

  display: flex;

}

row 플렉스 컨테이너의 사이즈 관련 용어와 다양한 방향

메인 축 / 메인 차원 (main axis / main dimension)

메인 축은 플렉스 컨테이너 내 플렉스 아이템을 배치할 때 주된 축이다. 이는 메인 차원에서 확장한다.


메인 시작 / 메인 끝 (main-start / main-end)

플렉스 컨테이너 내 플렉스 아이템들은 메인 시작으로부터 메인 끝까지 위치한다.


메인 사이즈 / 메인 사이즈 속성 (main size / main size property)

플렉스 아이템의 width나 height 중 어느 쪽의 메인 차원은 아이템의 메인 사이즈다.

플렉스 아이템의 메인 사이즈 속성은 width나 height 속성 중 어느 쪽의 메인 차원이다.


크로스 축 / 크로스 차원 (cross axis / cross dimension)

메인 축에 수직 하는 축을 크로스 축이라고 부른다. 이는 크로스 차원에서 확장한다.


크로스 시작 / 크로스 끝 (cross-start / cross-end)

플렉스 라인은 플렉스 아이템으로 채워지고 플렉스 컨테이너의 크로스 시작에서부터 크로스 끝까지 컨테이너로 배치된다.


크로스 사이즈 / 크로스 사이즈 속성 (cross size / cross size property)

플렉스 아이템의 width나 height 중 어느 쪽의 크로스 차원은 아이템의 크로스 사이즈다.

플렉스 아이템의 크로스 사이즈 속성은 width나 height 속성 중 어느 쪽의 크로스 차원이다.




플렉스 컨테이너는 플렉스 서식 문맥(flex formatting context)을 생성한다. 플렉스 서식 문맥은 블록 서식 문맥과 동일하게 보이겠지만, 블록 레이아웃 대신 플렉스 레이아웃을 사용한다는 차이가 있다. 예를 들어, float는 플렉스 컨테이너를 방해하지 않으며, 플렉스 컨테이너의 margin은 그 콘텐츠의 margin과 결합되지 않는다.


플렉스 컨테이너 내 자식들의 디스플레이는 플렉스 아이템으로 바뀐다. 플렉스 컨테이너 내에 요소로 감싸 지지 않은 콘텐츠가 있다면 익명 블록 박스(anonymous block box)를 생성하여 그 박스를 플렉스 아이템으로 보이게 한다.


예제 3. 플렉스 컨테이너 안 다양한 차일드

예제 3은 플렉스 컨테이너 안에 (1) 일반 블록 요소 (2) float:left가 들어간 블록 요소 (3) 익명 요소 (4) 인라인 요소가 들어가 있다. 넷 다 서로 다른 문맥에서 동작하지만 플렉스 컨테이너 안에서 모두 플렉스 아이템처럼 보인다.


플렉스 컨테이너는 그 자체만으로도 굉장히 강력하게 레이아웃을 억제하며, 편하게 레이아웃을 구성할 수 있게 한다. 많은 사람들이 착각하는 것 중 하나가 플렉스 컨테이너를 구성할 때 그 자식 요소에 반드시 flex 속성을 넣어야 한다는 인식으로 반드시 그래야 할 필요는 없다. 플렉스 아이템이 비율에 맞추어 늘어나거나 줄어들거나 / 혹은 서로 같은 사이즈를 가져야 하는 상황이 발생했을 때 자식 요소에 flex 속성을 넣으면 된다.


플렉스 방향 및 순서

플렉스 레이아웃 모델에서는, 플렉스 컨테이너의 자식 요소를 모든 방향으로 배치 가능하다. 기존에는 float 속성 및 clear 속성을 사용하는 핵을 사용해야만 했던 것들도 플렉스 레이아웃 모델에서는 비교적 쉽게 구성할 수 있다. 관련 속성으로 크게 flex-direction, flex-wrap, order 속성을 사용할 수 있다.


flex-direction 

플렉스 컨테이너에 적용하며, 플렉스 아이템의 메인 축을 결정한다. 값은 row(기본값), row-reverse, column, column-reverse가 있다.


row메인 축을 수평으로 하며, 플렉스 아이템이 좌측부터 우측으로 쌓이게 한다.

row-reverse메인 축을 수평으로 하며, 플렉스 아이템이 우측부터 좌측으로 쌓이게 한다.

column메인 축을 수직으로 하며, 플렉스 아이템이 위부터 아래로 쌓이게 한다.

column-reverse메인 축을 수직으로 하며, 플렉스 아이템이 아래부터 위로 쌓이게 한다.


flex-wrap

플렉스 컨테이너에 적용하며, 플렉스 아이템이 플렉스 컨테이너를 넘쳤을 때 처리방법을 결정한다. 값은 nowrap(기본값), wrap, wrap-reverse가 있다.


nowrap은 콘텐츠가 넘쳐도 상관없이 계속 그 방향으로 쌓이게 한다.

wrap은 콘텐츠가 넘칠 경우 다음 줄로 넘긴다.

wrap-reverse는 동작은 wrap과 동일하나, 크로스 시작 및 크로스 반대 방향이 서로 바뀐다.


order

플렉스 아이템에 적용하며, 플렉스 컨테이너 내에서 플렉스 아이템의 쌓이는 순서를 변경한다. 값은 숫자로 지정하며 기본값은 0이므로 0보다 큰 값을 지정할 경우 해당 컨테이너의 마지막에 위치한다. 음수 값을 지정할 수 있으며, 0보다 작은 값을 지정할 경우 해당 컨테이너의 제일 첫 번째로 존재하게 할 수 있다.


플렉스를 유연하게

플렉스 레이아웃 모델의 핵심 중 하나는 단언컨대 유연성(Flexibility)이다. 플렉스 레이아웃에서 플렉스 아이템을 유연하게 지정하며, 플렉스 아이템의 width/height는 메인 차원에서 사용 가능한 공간을 가득 채울 수 있는 기능이다.


플렉스 컨테이너는 컨테이너를 채우기 위해 나머지 공간을 플렉스 아이템에 분배(이는 flex-grow에 의존한다)하거나, 아이템이 넘치는 걸 막기 위해 플렉스 아이템을 축소(이는 flex-shrink에 의존한다)시킬 수도 있다.


플렉스를 유연하게 하는 데에는 flex 속성을 사용하며, flex 속성은 flex-grow, flex-shrink, flex-basis 속성을 축약하여 표현한다.


flex

플렉스 아이템에 적용한다. flex 속성은  flex-grow, flex-shrink, flex-basis 속성의 축약형이기 때문에 각각의 사용법에 대해서 아는 게 중요하다. display 속성과 마찬가지로 flex가 최신 스펙이기 때문에 flex 속성을 지정할 때에도 벤더 접두사를 붙여아 한다.


.flex-item {

  -webkit-box-flex: 1;

  -moz-box-flex: 1;

  -webkit-flex: 1;

  -ms-flex: 1;

  flex: 1;

}


다소 귀찮겠지만 대부분의 브라우저를 대응하기 위한 작업이므로 반드시 작성해주는 걸 권장한다. 다만 일부 벤더 접두사는 사용하지 않는 경우도 있기 때문에 실제로 개발하면서 사용하지 않는 접두사들은 제거해나가는 걸 권장한다.


flex-grow는 플렉스 컨테이너에 남은 공간이 생겼을 때 플렉스 아이템이 얼마나 공간을 차지할지 결정한다. 값은 숫자로 지정하며, 기본 값은 0이다.


모든 플렉스 아이템의 flex-grow 값이 동일한 경우 플렉스 아이템의 크기는 동일하다.

만약 3개의 플렉스 아이템 중, 하나만 flex-grow 값이 큰 경우 해당 박스는 다른 박스에 비해 해당 숫자 비율만큼 커진다. 즉 나머지는 해당 숫자만큼 커진 박스에 맞춰져서 자동으로 줄어든다.


flex-shrink는 플렉스 컨테이너에 비해 플렉스 아이템이 더 커졌을 때 플렉스 아이템을 얼마나 줄일지 결정한다. 값은 숫자로 지정하며, 기본 값은 1이다.


모든 플렉스 아이템의 flex-shrink 값이 동일할 경우 플렉스 아이템의 크기는 동일하다.

만약 3개의 플렉스 아이템 중, 하나만 flex-shrink 값이 큰 경우 해당 박스는 다른 박스에 비해 해당 숫자 비율만큼 작아진다. 흔히 착각할 수 있는 게 flex-grow와 동일하게 생각하여 해당 숫자만큼 커진다고 생각할 수 있는데 해당 숫자만큼 작아진다. 즉 나머지는 해당 숫자만큼 작아진 박스에 맞춰져서 자동으로 줄어든다.


flex-basis는 플렉스 아이템의 기본 사이즈를 결정한다. 값은 auto, content, <width>으로 넣을 수 있다.

값이 auto인 경우 flex-basis에 적용된 메인 사이즈 속성 값을 찾는다. 만약 그 값이 auto인 경우 content로 넣는다. 값이 content인 경우 플렉스 아이템 내 콘텐츠의 길이에 의존한다. 값이 <width>인 경우에는 말 그대로 width 값을 기본으로 한다.


플렉스 아이템을 정렬

여타 레이아웃과 마찬가지로 플렉스 박스에서도 플렉스 아이템의 정렬이 가능하다. 다만 기존 Float 레이아웃에서 구현하기 어려웠던 몇 가지 것들도 플렉스 박스에서는 구현하기 좀 더 쉽다.


정렬에는 크게 플렉스 컨테이너의 메인 축(main axis)에 따라 정렬하는 justify-content, 플렉스 컨테이너의 크로스 축 (cross axis)에 따라 정렬하는 align-items, 플렉스 컨테이너의 크로스 축(cross axis)에 따라서 플렉스 컨테이너의 라인을 justify-content처럼 정렬해주는 align-content가 있다.


각 값을 하나하나 설명하기보단 그림으로 보는 게 이해가 더 높기 때문에, 각 아이템이 어떻게 정렬되는지 그림으로 살펴보도록 하자.


justify-content의 다섯가지 값과 각각 보여주는 형태


justfy-content는 플렉스 컨테이너의 메인 축에 따라서 플렉스 아이템들을 어떻게 정렬할지 결정한다. 기본 값은 flex-start이며, 플렉스 컨테이너에 속성을 부여한다. 주의해야 할 점 중 하나는 만약 flex-basis와 flex-grow를 동일한 값으로 넣었을 경우 모든 박스가 자동으로 늘어나기 때문에 justify-content 속성을 부여하여 정렬을 바꾸어도 그렇게 티가 나지 않는 이슈가 발생할 수 있다.


align-items의 다섯가지 값과 각각 보여주는 형태

align-items는 플렉스 컨테이너의 크로스 축에 따라서 플렉스 아이템들을 어떻게 정렬할지 결정한다. 기본값은 stretch이며, 플렉스 컨테이너에 속성을 준다. align-items를 별도로 설정하지 않는다면 플렉스 아이템들은 자동으로 늘어나게 된다.


align-content의 여섯가지 값과 각각 보여주는 형태

지금까지 다른 속성들이 대체로 한 라인 내에서 박스를 어떻게 정렬할지 결정하였다면 align-content는 여러 개의 박스가 있는 라인들을 어떻게 정렬할지 결정한다. 기본 값은 stretch이며, 플렉스 컨테이너에 속성을 주입한다.


플렉스박스는 CSS로 레이아웃을 구성하기 위한 다양한 모델 중 모던 브라우저에서 (특히 모바일 브라우저에서) 지원율이 높은 편에 속하기 때문에 지금 당장 웹사이트에 반영해도 크게 이슈가 없을 정도로 잘 작동한다. 따라서 만약 모바일 레이아웃을 고려하고 있다면 플렉스박스를 한번 사용해보는 것을 추천한다.


POSITION

CSS에는 크게 세 가지 위치 지정 체계(positioning scheme)가 존재한다.


일반 흐름 (Normal flow) - 블록 레벨 박스의 블록 서식, 인라인 레벨 박스의 인라인 서식 및 블록 레벨 및 인라인 레벨 박스의 상대 위치 지정(relative positioning)을 포함한다.


플로트 (Floats) - Float 모델에서, 박스는 일반 흐름(normal flow)에 따라 배치된 후, 흐름에서 벗어나 가능한 한 왼쪽 혹은 오른쪽으로 달라붙는다. 콘텐츠는 플로트의 측면을 따라 흐를 수 있다.


절대 위치 지정 (Absolute Positioning) - 절대 위치 지정 모델에서, 박스는 일반 흐름에서 완전히 제거되고 (형제 요소에 영향을 주지 않아요), 컨테이닝 블록에 따라 위치를 지정한다.


flow가 float 되었거나, absolute 포지션이거나, 루트 요소라면 flow를 벗어난 요소라 부른다. 만약 flow를 벗어나지 않았다면 in-flow 요소라 부른다. 요소 A의 flow는 A와 가장 가까운 flow를 벗어난 조상이 A인 모든 in-flow 요소의 집합이다.


position 속성은 위치 지정 체계를 지정하는 CSS 속성이다. position 속성에는 static(기본값), relative, absolute, fixed 네 가지 값이 있다. 현재 sticky라는 새로운 모델이 추가되고 있지만 브라우저 지원율이 아주 현저히 낮기 때문에 이 글에서는 다루지 않는다.


position 속성은 좁게 보면 (1) 박스를 어떻게 흐르게 할지 결정하지만 넓게 보면 (2) left, top, right, bottom 속성과 함께 박스의 위치를 결정하고 (3) z-index 속성으로 레이어가 쌓이는 순서를 결정한다. 아래에서 left, top, right, bottom을 합쳐 박스 오프셋 속성이라 부르겠다.


static은 position 속성을 지정하지 않더라도 기본값으로 들어가 있으며 박스는 일반 박스로, 일반 흐름을 따르도록 한다. 박스 오프셋 속성 z-index 전부 동작하지 않는다. 상황에 따라서 position을 초기화시켜줘야 할 때 relative로 초기화시키는 케이스가 종종 있는데 static으로 초기화시켜주는 게 실제 position 기본값이기 때문에 좋다.


relative는 일반 흐름으로 동작 하나 박스 오프셋 속성 z-index를 이용할 수 있다. 박스 오프셋 속성을 사용할 때 각 속성들이 특정한 좌표를 기준으로 이동하여야 하는데, relative에서는 자기 자신을 기준으로 한다. 만약 left:10px이라고 한다면 자기 자신의 왼쪽으로부터 10px 이동한다.


absolute fixed절대 위치 지정(Absolute Positioning)으로 동작하며, 박스 오프셋 속성과 z-index를 사용할 수 있다. 절대 위치 지정 모델에서, 박스는 일반 흐름에서 완전히 제거된다 (형제 요소에 영향을 주지 않아요). 


절대 위치로 지정한 박스일반 흐름 자식 및 (fixed를 제외한) 절대 위치 지정 조상 요소가 되기 위한 새로운 컨테이닝 블록을 생성하지만, 절대 위치로 지정한 요소의 콘텐츠는 다른 박스 주변으로 흐르지 않는다. 이 말은 절대 위치로 지정한 박스가 다른 일반 흐름 박스 혹은 절대 위치로 지정한 박스를 덮어씌울 수 있으며, 그로 인해 다른 박스의 콘텐츠를 방해할 수 있다는 것이다.


absolute절대 위치 조상 요소가 되기 위한 컨테이닝 블록을 기준으로 하여 위치를 지정한다. 절대 위치 조상 요소는 position 속성을 가진 요소 중 그 값이 static이 아닌 요소를 의미한다. 만약 절대 위치 조상 요소가 존재하지 않는다면 그 요소의 기준점은 body를 기준으로 한다. 부모 요소가 아닌 조상 요소이기 때문에 조상 요소를 탐색하다가 하나라도 발견한다면 해당 요소를 기준으로 함에 유의하여야 한다.


fixedabsolute와 동일하나 브라우저의 window를 기준으로 고정하기 때문에 스크롤을 하더라도 해당 위치에 고정되어있다는 특징이 있다. 따라서 브라우저의 스크롤과 상관없이 요소를 특정 위치에 고정시키고 싶다면 fixed를 사용하는 것이 바름 직하다.




이 글에서는 웹에서 사용하는 레이아웃의 가장 기본적인 것들을 다루어보았다. 다음에는 더 복잡한 것을 해보도록 하자.

매거진의 이전글 1년 6개월만에 만난 테스트 코드
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari