본문으로 건너뛰기
김도현

Flexbox, 제대로 알아보기

공간을 나누고 아이템을 배치하는 레이아웃의 원리

display: flex를 주면 자식들이 한 줄로 늘어선다. 이후에 쓰는 속성은 대부분 주축(main axis)과 교차축(cross axis) 위에서 정의된다. 두 축의 방향은 flex-direction이 정한다.

기준속성
축을 어디로 놓을까flex-direction, flex-wrap
주축에서 어떻게 놓을까justify-content, gap
교차축에서 어떻게 놓을까align-items, align-content, align-self
아이템이 얼마나 늘고 줄까flex-grow, flex-shrink, flex-basis

align-self와 크기 관련 속성은 아이템에, 나머지는 컨테이너에 건다.

flex-direction, 축을 정하는 속성

주축은 아이템이 늘어서는 방향, 교차축은 그에 수직인 방향이다. 기본값 row에서는 주축이 가로, column에서는 세로다.

justify-*는 주축을, align-*은 교차축을 다룬다. 이 규칙은 방향과 무관하게 유지되므로 flex-direction: column에서는 justify-content: center가 세로 가운데 정렬이 된다.

row-reverse는 아이템의 순서가 아니라 주축의 시작점을 옮긴다. 시작점이 오른쪽이 되므로 flex-start도 오른쪽을 가리킨다.

1
2
3

justify-content, 주축의 남는 공간

아이템을 모두 배치하고 남은 주축 공간을 어떻게 나눌지 정한다.

  • flex-start, center, flex-end: 남는 공간을 한쪽에 몰아준다.
  • space-between: 첫 아이템과 마지막 아이템을 양 끝에 붙이고 나머지를 사이에 균등하게 나눈다.
  • space-around: 아이템마다 양옆에 같은 여백을 준다. 여백이 겹치므로 가장자리 여백은 사이 여백의 절반이 된다.
  • space-evenly: 가장자리와 사이를 모두 같은 크기로 나눈다.

남는 공간이 없으면 아무 효과도 없다. flex-grow로 아이템이 공간을 다 채웠다면 값을 바꿔도 화면은 그대로다.

아이템 사이 간격은 gap으로 준다. margin과 달리 가장자리에는 여백이 생기지 않는다.

1
2
3

align-items, 한 줄 안의 교차축 정렬

한 줄 안에서 아이템을 교차축의 어디에 놓을지 정한다.

  • stretch: 기본값이다. 교차축 크기가 auto인 아이템을 줄 높이만큼 늘린다. 높이를 준 적 없는 아이템이 컨테이너 높이만큼 커지는 이유다.
  • flex-start, center, flex-end: 아이템이 자기 콘텐츠 크기가 된다.
  • baseline: 첫 줄 텍스트의 기준선을 맞춘다.

아이템 하나만 다르게 두려면 그 아이템에 align-self를 준다. 값은 align-items와 같다.

1
2
3

flex-wrap, 줄을 넘길지

기본값 nowrap은 아이템이 몇 개든 한 줄에 밀어 넣는다. 공간이 모자라면 줄을 바꾸는 대신 아이템이 줄어들고 더 줄어들 수 없으면 컨테이너를 넘친다.

wrap은 들어가지 않는 아이템을 다음 줄로 넘긴다. wrap-reverse는 줄이 쌓이는 방향, 즉 교차축의 시작점을 뒤집는다.

1
2
3
4
5
6

align-content, 줄 뭉치의 정렬

여러 줄이 된 뒤 줄 자체를 교차축 어디에 놓을지 정한다. 값은 justify-content와 같다.

속성무엇을 옮기나
justify-content줄 안의 아이템들주축
align-items줄 안의 아이템 하나교차축
align-content줄 전체교차축

줄이 하나뿐이면 효과가 없다. flex-wrap: wrap을 주지 않은 컨테이너에서 이 속성이 동작하지 않는 이유다.

1
2
3
4
5
6

flex, 아이템의 크기

flex-grow, flex-shrink, flex-basis의 단축 속성이고 기본값은 0 1 auto다.

  • flex-grow: 남는 공간을 나눠 가질 비율이다. 기본값 0이라 아이템은 저절로 늘어나지 않는다.
  • flex-shrink: 공간이 모자랄 때 줄어들 비율이다. 기본값이 1이라 아이템은 가만히 두면 줄어든다.
  • flex-basis: 늘리고 줄이기 전의 기준 크기다. auto면 주축 방향의 width(또는 height)를 보고 그것도 auto면 콘텐츠 크기가 된다.
풀어 쓰면
initial0 1 auto콘텐츠 크기에서 시작해 줄어들기만 한다
auto1 1 auto콘텐츠 크기에서 시작해 남는 공간도 나눠 갖는다
none0 0 auto콘텐츠 크기로 고정된다
11 1 0%기준 크기를 0으로 두고 전체 공간을 비율로 나눈다

flex: auto는 콘텐츠 크기가 기준이라 내용이 긴 아이템이 더 넓게 남고, flex: 1은 기준이 0이라 콘텐츠 길이와 관계없이 너비가 같아진다.

너비를 고정할 때 width: 240px만 주면 flex-shrink1로 남아 있어 공간이 부족하면 줄어든다. flex-basis로 적으면 그 문제가 없다.

.equal {
flex: 1;
}
.fixed {
flex: 0 0 240px;
}
짧게
조금 더 긴 내용
가장 긴 내용의 아이템

min-width, 줄어들지 않는 아이템

flex: 1을 준 아이템 안에서 긴 텍스트를 말줄임 처리했는데 말줄임표 대신 아이템이 컨테이너를 밀어내는 경우가 있다.

flex 아이템의 min-width 기본값이 0이 아니라 auto이기 때문이다. auto는 콘텐츠의 최소 크기(min-content) 아래로 줄어들지 않게 막고, white-space: nowrap이 걸린 텍스트는 min-content가 문장 전체 길이다.

min-width: 0을 명시하면 이 하한이 풀린다. 자동 최소 크기는 주축 방향 overflowvisible일 때만 적용되므로 아이템 자신에 overflow: hidden을 줘도 결과는 같다. 말줄임이 아이템 안쪽 요소에 걸려 있다면 아이템의 overflowvisible로 남으므로 min-width: 0이 필요하다. 주축이 세로라면 min-height: 0이다.

.cell {
flex: 1;
min-width: 0;
}
.cell .title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/posts/2026/flex-container-min-width-auto-overflow-issue-and-how-to-fix-it
사이드

order와 margin: auto

order는 아이템이 그려지는 순서를 바꾼다. 기본값은 0이고 값이 작을수록 앞에 온다. 키보드 탭 이동과 스크린 리더는 DOM 순서를 따르므로 둘이 어긋나면 보이는 순서대로 이동할 수 없다.

flex 컨테이너에서 auto 마진은 남는 공간을 전부 가져간다. 아이템 하나만 반대편으로 밀 때 justify-content 대신 쓸 수 있다.

.profile {
margin-left: auto;
}

정렬이 이상하면 주축이 어디인지, 크기가 이상하면 flex-basismin-width를 확인하면 된다. 행과 열을 동시에 잡는 일은 grid의 몫이다.

관련 글