FLEXBOX? 강좌1 스크롤100%레이아웃,내비게이션영역
-
385회 연결
-
0회 연결
본문
마크업 개발자들은 종종 "이 레이아웃은 구현이 불가능합니다.", "CSS만으로는 안될 것 같습니다. 개발 처리가 필요합니다."라고 이야기합니다. 이 말은 사실입니다. 일반적으로 웹 페이지의 레이아웃은 CSS의 display
, float
, position
등과 같은 속성을 사용해 구현합니다. 하지만 이 속성을 사용하면 구현 방법이 복잡하고 레이아웃을 표현하는 데 많은 한계가 있습니다.
구현이 어려운 레이아웃을 간단하게 구현할 수 있게 CSS3에 추가된 레이아웃 방식이 flexbox입니다. flexbox를 사용하면 요소의 크기와 순서를 유연하게 배치할 수 있습니다.
이 글에서는 실무에서 많이 사용하지만 기존의 방식으로는 구현이 어렵거나 불가능한 레이아웃 10개를 선별해 flexbox로 구현하는 방법을 주요 속성 위주로 설명합니다.
flexbox란?
flexbox는 뷰포트나 요소의 크기가 불명확하거나 동적으로 변할 때에도 효율적으로 요소를 배치, 정렬, 분산할 수 있는 방법을 제공하는 CSS3의 새로운 레이아웃 방식이다. flexbox의 장점을 한 마디로 표현하면 '복잡한 계산 없이 요소의 크기와 순서를 유연하게 배치할 수 있다'라고 할 수 있다. 정렬, 방향, 순서, 크기 등을 유연하게 조절할 수 있기 때문에 별도의 분기 처리를 줄일 수 있고, CSS만으로 다양한 레이아웃을 구현할 수 있다.
flexbox의 구성
flexbox는 복수의 자식 요소인 flex item과 그 상위 부모 요소인 flex container로 구성된다.
flexbox를 만드는 방법은 간단하다. 정렬하려는 요소의 부모 요소에 다음과 같이 display: flex
속성을 선언하면 된다.
.flex_container {
display: flex;
}
display: flex
속성이 적용된 요소는 flex container가 되고, flex container의 자식 요소는 flex item이 된다. flex container와 flex item은 부모 요소와 자식 요소를 한 세트로 사용하는 ul
과 li
를 생각하면 쉽게 이해할 수 있다.
flex item은 주축(main axis)에 따라 정렬된다. 주축의 방향은 flex container의 flex-direction
속성으로 결정한다. flex-direction
속성을 따로 지정하지 않으면 기본값인 row
가 적용된다. 속성값 row
는 주축의 방향을 왼쪽에서 오른쪽 방향으로 흐르게 한다. flex-direction
속성의 또 다른 속성값인 column
은 주축의 방향을 위에서 아래 방향으로 흐르게 한다.
부모 요소와 자식 요소에 정의하는 속성 구분
flexbox에서 사용하는 속성은 부모 요소인 flex container에 정의하는 속성과 자식 요소인 flex item에 정의하는 속성으로 나누어진다. 전체적인 정렬이나 흐름에 관련된 속성은 flex container에 정의하고, 자식 요소의 크기나 순서에 관련된 속성은 flex item에 정의한다. 이를 분리해 적용하는 것이 중요하다.
- flex container 속성:
flex-direction
,flex-wrap
,justify-content
,align-items
,align-content
- flex item 속성:
flex
,flex-grow
,flex-shrink
,flex-basis
,order
flexbox 지원 범위
flexbox는 Internet Explorer 10 이상이 지원한다. 하지만 Internet Explorer 10 이상이 완전히 지원하지는 않아 Internet Explorer 10과 Internet Explorer 11에서 버그가 발견되기도 한다. 그래서 PC용 서비스에 flexbox를 적용하기에는 아직 이른 감이 있다. 만약 Internet Explorer를 지원하지 않는 서비스를 운영한다면 flexbox를 적용해 봐도 좋다.
모바일 브라우저의 flexbox 지원율은 매우 높다. 거의 대부분의 iOS용 브라우저와 Android용 브라우저가 지원한다고 생각해도 된다(Can I use 사이트의 'flex' 검색 결과 참고).
flexbox를 활용한 10가지 레이아웃 사례
이 글에서는 실무에서 많이 사용하는 다음 10가지 레이아웃을 flexbox로 구현하는 방법을 소개한다. 이 레이아웃은 기존의 display
속성이나 float
속성, position
속성 등으로는 구현이 어렵거나 구현이 불가능하다. 하지만 flexbox를 사용하면 쉽게 구현할 수 있다.
- 레이아웃 1 - 스크롤 없는 100% 레이아웃
- 레이아웃 2 - 내비게이션 영역
- 레이아웃 3 - 브라우저 화면 아래에 붙는 푸터
- 레이아웃 4 - 정렬이 다른 메뉴
- 레이아웃 5 - 폼 레이블 수직 중앙 정렬
- 레이아웃 6 - 중앙 정렬 아이콘
- 레이아웃 7 - 유동 너비 박스
- 레이아웃 8 - 말줄임과 아이콘
- 레이아웃 9 - 위아래로 흐르는 목록
- 레이아웃 10 - 가로세로 비율을 유지하는 반응형 박스
레이아웃 1 - 스크롤 없는 100% 레이아웃
스크롤 없는 100% 레이아웃은 전체 페이지를 구성할 때 자주 사용할 수 있는 레이아웃이다. 다음 그림과 같이 콘텐츠의 길이에 상관없이 브라우저 화면 전체를 채우는 레이아웃이다.
이 레이아웃에서 웹 페이지의 위에 있는 메뉴 영역의 높이는 고정되어 있다. 부모 영역에서 메뉴 영역을 뺀 나머지 영역 전체를 자식 요소가 채운다. 콘텐츠의 길이가 길어지면 스크롤 막대가 브라우저가 아니라 콘텐츠 영역에 나타난다.
스크롤 없는 100% 레이아웃을 구현하는 기본 CSS는 다음과 같다. 구현 예제는 CodePen 사이트의 "1. 스크롤이 없는 100% 레이아웃"에서 확인할 수 있다.
.flex_container {
display: flex;
flex-direction: column;
height: 100%;
}
.flex_item {
flex: 1; /* flex: 1 1 0 */
overflow: auto;
}
flex container(.flex_container
클래스)에 flex-direction: column
속성을 적용해 flex item을 수직으로 정렬한다. flex item(.flex_item
클래스)에는 flex: 1
속성을 적용해 flex item이 빈 공간을 채우게 한다.
flex-direction: column
속성으로 수직 방향 정렬 설정
flexbox 레이아웃에서 주축의 방향은 왼쪽에서 오른쪽으로 향하는 수평 방향이 기본이다. 하지만 요소를 수직으로 배열하려면 주축이 위에서 아래로 향하게 해야 한다. flex container의 flex-direction
속성의 값을 column
으로 설정하면 주축의 방향을 바꿀 수 있다.
flex : 1
속성으로 자식 요소의 크기 확장
flex item에 적용한 flex
속성은 flex item의 크기와 관련된 속성이며, 다음과 같이 flex-grow
속성과 flex-shrink
속성, flex-basis
속성을 축약한 표현이다.
앞의 그림에서 표현한 flex: 1 1 0
속성은 다음과 같은 flex-grow: 1
속성과 flex-shrink: 1
속성, flex-basis: 0
속성을 줄인 표현이다.
.flex-item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
flex: 1 1 0
은 다음과 같이 flex: 1
로 표현할 수도 있다.
.flex-item {
flex: 1;
/* flex: 1 1 0 */
}
flex-grow
속성
flex-grow
속성은 flex item의 확장에 관련된 속성이다. 0
과 양의 정수를 속성값에 사용한다.
속성값이 0
이면 flex container의 크기가 커져도 flex item의 크기가 커지지 않고 원래 크기로 유지된다. flex container의 크기가 커질 때 flex item의 크기도 커지게 하려면 1
이상의 값을 속성값으로 설정한다. 속성값이 1
이상이면 flex item의 원래 크기에 상관없이 flex container를 채우도록 flex item의 크기가 커진다.
flex-shrink
속성
flex-shrink
속성은 flex item의 축소에 관련된 속성이다. 0
과 양의 정수를 속성값에 사용한다. 기본값은 1
이다.
속성값이 0
이면 flex container의 크기가 flex item의 크기보다 작아져도 flex item의 크기가 줄어들지 않고 원래 크기로 유지된다. 속성값이 1
이상이면 flex container의 크기가 flex item의 크기보다 작아질 때 flex item의 크기가 flex container의 크기에 맞추어 줄어든다.
flex-basis
속성
flex-basis
속성은 flex item의 기본 크기를 결정하는 속성이다. 기본값은 auto
다.
width
속성에서 사용하는 모든 단위(px, %, em, rem 등)를 속성값에 사용할 수 있다. flex-basis
속성의 값을 30px
이나 30%
와 같이 설정하면 flex item의 크기가 고정된다.
flex-basis
속성에서 auto
와 함께 자주 사용하는 속성값이 0
이다. flex-basis
속성의 값을 0
으로 설정하면 flex item은 절대적 flex item(absolute flex item)이 되어 flex container를 기준으로 크기가 결정된다.
주의
flex-basis
속성의 값을0
으로 선언할 때에는flex-basis: 0px
,flex-basis: 0%
와 같이 단위도 함께 설정해야 한다.
flex-basis
속성의 값을 auto
로 설정하면 flex item은 상대적 flex item(relative flex item)이 되어 콘텐츠의 크기를 기준으로 크기가 결정된다.
flex: 1
의 의미
flex-grow
속성과 flex-shrink
속성, flex-basis
속성을 축약해서 flex
속성으로 표현할 때 flex: 1
속성은 flex: 1 1 0
속성을 의미한다. 즉, flex-grow
속성의 값이 '1'이고 flex-shrink
속성의 값이 '1'이기 때문에 flex container의 크기에 따라 flex item의 크기도 커지거나 작아진다는 의미다.
flex
속성의 값으로 정수 하나만 선언하면 선언한 값은 flex-grow
속성의 값이 된다. 나머지는 기본값인 flex-shrink: 1
속성과 flex-basis: 0
속성이 적용된다. 다시 말해 flex
속성에 한 개의 정숫값만 있으면 이것은 flex-grow
속성의 값만 지정하는 단축 속성이다. 즉, flex: 2
는 flex: 2 1 0
을, flex: 3
은 flex: 3 1 0
을 나타내다.
레이아웃 2 - 내비게이션 영역
내비게이션은 웹 페이지에서 자주 사용하는 레이아웃이다. 다음 그림과 같이 메뉴의 대부분을 내비게이션 영역의 왼쪽으로 정렬하고, 1~2개의 메뉴만 오른쪽으로 정렬한 내비게이션을 쉽게 볼 수 있다. 주로 GNB(global navigation bar)에 해당하는 요소나 로그인 버튼을 오른쪽으로 정렬한다.
내비게이션 영역을 구현하는 기본 CSS는 다음과 같다. 구현 예제는 CodePen 사이트의 "2. 네비게이션"에서 확인할 수 있다.
.flex-container {
display: flex;
}
.flex-item {
flex: none;
/* flex: 0 0 auto */
}
.flex-item-gnb {
margin-left: auto;
}
크기가 고정되어야 하는 flex item(.flex-item
클래스)에는 flex: none
속성을 적용한다. 오른쪽으로 정렬할 GNB나 로그인 버튼에 해당하는 요소(.flex-item-gnb
클래스)에는 margin-left: auto
속성을 적용한다.
flex: none
속성으로 자식 요소의 크기 고정
내비게이션 영역의 기본 구조에서는 'logo' 요소와 'search' 요소, 'gnb' 요소의 크기가 커지거나 작아지지 않게 디자인했다. flex item의 크기에 관련된 속성인 flex
속성의 기본값은 flex: 0 1 auto
다. 기본값을 적용하면 flex container의 크기가 flex item 전체의 크기보다 작아질 때 flex item의 크기가 작아진다. flex item의 크기를 고정하려면 반드시 flex: none
속성을 적용해야 한다.
flex: none
은 flex-grow: 0
속성과 flex-shrink: 0
속성, flex-basis: auto
속성을 축약해 표현한 것이다. 하나의 정수를 사용해 축약하는 방법("flex: 1
의 의미" 참고) 외에 세 개의 키워드인 initial
, none
, auto
를 flex
속성의 값으로 설정해 속성을 축약할 수 있다.
flex
속성에 사용하는 키워드에 따라 축약되는 속성의 설정값은 다음과 같다.
flex | flex-grow | flex-shrink | flex-basis |
---|---|---|---|
initial(기본값) | 0 | 1 | auto |
none | 0 | 0 | auto |
auto | 1 | 1 | auto |
양의 정수 | 숫자 | 1 | 0 |
flex
속성의 값에 따라 flex item의 크기는 다음과 같이 변한다.
initial
(기본값): flex container의 크기가 작아지면 flex item의 크기가 작아진다. 하지만 flex container의 크기가 커져도 flex item의 크기는 커지지 않는다.none
: flex item의 크기가 커지거나 작아지지 않는다. flex container의 크기에 영향을 받지 않고, flex item의 원래 크기를 유지한다.auto
: flex container의 크기에 맞추어 flex item의 크기가 커지거나 작아진다.- 양의 정수: flex container를 일정한 비율로 나눠 가지면서 flex container의 크기에 따라 flex item의 크기가 커지거나 작아진다.
margin-left: auto
속성으로 자식 요소를 오른쪽에 배치
요소의 바깥 여백(margin)을 설정하는 속성에 속성값으로 auto
를 적용하면 flexbox에서 flex item을 쉽게 배치할 수 있다. 예를 들어 margin: auto
속성을 적용하면 flex item의 바깥 여백이 자동으로 확장되어 flex item이 flex container의 가운데에 위치하게 된다.
flex item을 수평으로 배치할 때 다음과 같이 'auto' 속성값을 사용할 수 있다.
margin-right: auto
: 바깥 여백이 오른쪽의 모든 공간을 차지하기 위해 flex item을 오른쪽에서 왼쪽으로 민다.margin: 0 auto
: 바깥 여백이 flex item을 양쪽에서 밀기 때문에 flex item이 수평 중앙에 위치한다.margin-left: auto
: 바깥 여백이 왼쪽의 모든 공간을 차지하기 위해 flex item을 왼쪽에서 오른쪽으로 민다.
flex item을 수직으로 배치할 때 다음과 같이 'auto' 속성값을 사용할 수 있다.
margin-bottom: auto
: 바깥 여백이 아래쪽의 모든 공간을 차지하기 위해 flex item을 아래쪽에서 위쪽으로 민다.margin: auto 0
: 바깥 여백이 flex item을 위아래로 밀기 때문에 flex item이 수직 중앙에 위치한다.margin-top: auto
: 바깥 여백이 위쪽의 모든 공간을 차지하기 위해 flex item을 위쪽에서 아래쪽으로 민다.
flexbox에서 margin: auto
속성으로 레이아웃을 구현하는 방법이 핵(hack)이라고 생각하거나 버그를 일으키는 요인이 될 수도 있다고 생각할 수 있다. 하지만
댓글목록 0