02 — Flex Item: flex shorthand와 min-width: 0
이 문서가 답하는 질문:
flex: 1,flex: 1 1 0,flex: 1 1 auto는 어떻게 다르며, 왜min-width: 0이 필요한가?
한 줄 답
flex는growshrinkbasis세 값의 shorthand다.flex: 1 1 0은 0부터 균등 분배,flex: 1 1 auto는 콘텐츠 폭부터 시작해서 남은 공간만 분배. flex item의 **기본min-width: auto**는 콘텐츠 최소 폭(긴 단어, 이미지)을 보장하므로, 텍스트 ellipsis가 필요하면min-width: 0을 명시해야 한다.
Why — 왜 세 값이 필요한가
“공간을 어떻게 나눌까?”는 세 가지 결정을 동시에 요구한다.
- 늘어날 때 얼마나 가져갈 것인가 →
flex-grow - 줄어들 때 얼마나 양보할 것인가 →
flex-shrink - 시작점은 어디인가 (콘텐츠 폭? 0? 고정값?) →
flex-basis
이 셋이 분리되어 있으면 “균등 분배 + 콘텐츠 무시”, “콘텐츠 우선 + 늘어나기만” 같은 다양한 패턴을 표현할 수 있다.
How — 어떻게 분배되는가
1) 분배 알고리즘 (간단히)
핵심: shrink는 basis 가중치와 함께 곱해진다. 큰 항목이 더 많이 줄어든다.
2) flex: 1 1 0 vs flex: 1 1 auto — 가장 흔한 혼동
| 케이스 | basis | 결과 |
|---|---|---|
flex: 1 1 0 | 0 | 모두 0에서 시작, 컨테이너 폭을 grow 비율로 균등 분배 → 칸이 같음 |
flex: 1 1 auto | auto | 콘텐츠 폭에서 시작, 남은 공간만 grow 비율로 분배 → 칸이 다름 |
flex: 1 | 0 | shorthand에서 단일 숫자는 grow만 → 나머지는 1 0 (shrink=1, basis=0) |
/* 균등 3분할 — 어떤 콘텐츠가 들어와도 동일 폭 */
.equal > * { flex: 1 1 0; }
/* 콘텐츠 비례 + 남은 공간만 균등 — 짧은 칸은 좁게 */
.proportional > * { flex: 1 1 auto; }3) flex: <num> shorthand 단축
| 입력 | 해석 |
|---|---|
flex: 1 | 1 1 0% |
flex: 2 | 2 1 0% |
flex: auto | 1 1 auto |
flex: none | 0 0 auto (고정) |
flex: initial (기본) | 0 1 auto (안 늘지만 줄 수 있음) |
단일 숫자
flex: 1이1 1 0인 게 함정. basis가 0이라 콘텐츠 폭이 0으로 시작한다.
What — 세부 사양
항목 속성
| 속성 | 기본값 | 의미 |
|---|---|---|
flex-grow | 0 | 여유 공간을 가져가는 비율 |
flex-shrink | 1 | 부족 공간에서 양보하는 비율 (basis 가중) |
flex-basis | auto | 시작 크기 — <length> / <percentage> / auto / content |
flex | 0 1 auto | shorthand |
align-self | auto | cross 축 개별 정렬 — align-items 오버라이드 |
order | 0 | 시각적 순서 (DOM 순서는 그대로) |
min-width: auto (Flex item 기본값)
Flex item은 min-width: auto가 기본이다 (block의 min-width: 0과 다름).
auto 값의 동작:
- 콘텐츠가 깨질 수 없는 길이(긴 단어,
white-space: nowrap텍스트, 이미지 intrinsic width)를 최소로 보장. - 즉, flex item은 콘텐츠 최소 폭 아래로 줄어들지 않는다.
이것이 “텍스트가 부모를 뚫고 나가는” 가장 흔한 원인이다.
.flex {
display: flex;
}
.flex > .text {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
/* 위 셋만으로는 안 됨 — min-width: auto가 콘텐츠 폭을 보장 */
min-width: 0; /* ← 이게 핵심 */
}What-if — 잘못 쓰면
1) 텍스트 ellipsis가 안 먹는다
증상:
<div style="display:flex; width:300px;">
<div style="flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</div>
</div>→ 부모를 뚫고 나간다.
원인: flex item의 min-width: auto가 콘텐츠 최소 폭을 보장.
해결:
.item { min-width: 0; }같은 함정이 overflow-x: auto 자식 스크롤 영역에서도 발생한다. flex item 안에 <table>이나 가로 스크롤 컨테이너를 넣으면 부모를 늘려버린다 — 역시 min-width: 0.
2) flex: 1로 균등 분배했는데 칸 폭이 다르다
원인: 의도적으로 flex: 1 1 auto(또는 flex: auto)를 썼거나, basis를 명시 안 했는데 콘텐츠 폭이 다름.
해결: 항상 flex: 1 1 0을 명시 (또는 flex: 1로 축약). 콘텐츠 비례가 필요하면 flex: auto.
3) 이미지가 의도보다 작게 보인다
원인: flex-shrink: 1(기본)으로 이미지가 줄어듦. 이미지는 보통 줄지 않아야 한다.
해결:
.flex > img { flex-shrink: 0; } /* 또는 flex: none */4) order로 순서 바꿨더니 키보드 포커스 순서가 이상하다
원인: order는 시각적 순서만 바꿈, DOM·tab order는 그대로.
해결: 시각/논리 순서가 다르면 안 됨. DOM 자체를 재배치하거나, order 사용을 포기.
5) flex item의 height: 100%가 안 먹는다
원인: cross 축이 column일 때만 의미가 명확. row일 때 align-items: stretch 기본이라 보통 자동으로 같은 높이.
해결: 컨테이너에 align-items를 확인. align-self: stretch로 항목별 오버라이드.
Insight — 0이 auto가 아닌 이유
CSSWG가 flex: 1의 basis를 0으로 정한 건 “콘텐츠가 다른데 칸이 같아야 한다”는 게 더 흔한 요구였기 때문이다.
flex-basis: 0의 의미는 “내 콘텐츠를 무시하고 grow 비율만 봐달라”. flex-basis: auto는 “내 콘텐츠 폭을 존중해줘”.
대시보드 카드, 네비게이션 항목, 폼 그리드처럼 *“칸이 같아야 한다”*가 핵심인 경우가 압도적으로 많아서 flex: 1 = 1 1 0이 되었다.
min-width: auto 기본값도 비슷한 트레이드오프다. 만약 0이 기본이었다면 “이미지가 0폭으로 사라진다” 같은 더 큰 함정이 더 자주 일어났을 것이다. CSSWG는 “안전한 기본값 + 명시적 opt-out”을 택했다 — 그 비용이 min-width: 0 보일러플레이트.
흥미로운 역사: min-width: auto는 2014년 Flexbox 스펙에 나중에 추가된 동작이다. 초기 구현은 0이 기본이어서 이미지 squashing 버그가 대량 발생했고, 그 결과 auto 정책이 들어왔다. 즉 min-width: 0은 CSS의 “기본값을 되돌리는” 패턴이다 — box-sizing: border-box와 같은 종류의 카운터-디폴트.
요약 + Mermaid
flex는grow shrink basisshorthand.flex: 1=1 1 0.flex: 1 1 0(균등) vsflex: 1 1 auto(콘텐츠 비례) 차이를 의식적으로 선택.- Flex item은
min-width: auto가 기본 — ellipsis가 필요하면min-width: 0필수. - 이미지는 **
flex-shrink: 0**으로 보호.
다음: 03-grid-basics — Grid template과 fr 단위.