🎨 Frontend CSS3. Flexbox & Grid02 — Flex Item (flex shorthand)

02 — Flex Item: flex shorthand와 min-width: 0

이 문서가 답하는 질문: flex: 1, flex: 1 1 0, flex: 1 1 auto는 어떻게 다르며, 왜 min-width: 0이 필요한가?


한 줄 답

flexgrow shrink basis 세 값의 shorthand다. flex: 1 1 00부터 균등 분배, flex: 1 1 auto콘텐츠 폭부터 시작해서 남은 공간만 분배. flex item의 **기본 min-width: auto**는 콘텐츠 최소 폭(긴 단어, 이미지)을 보장하므로, 텍스트 ellipsis가 필요하면 min-width: 0을 명시해야 한다.


Why — 왜 세 값이 필요한가

“공간을 어떻게 나눌까?”는 세 가지 결정을 동시에 요구한다.

  1. 늘어날 때 얼마나 가져갈 것인가 → flex-grow
  2. 줄어들 때 얼마나 양보할 것인가 → flex-shrink
  3. 시작점은 어디인가 (콘텐츠 폭? 0? 고정값?) → flex-basis

이 셋이 분리되어 있으면 “균등 분배 + 콘텐츠 무시”, “콘텐츠 우선 + 늘어나기만” 같은 다양한 패턴을 표현할 수 있다.


How — 어떻게 분배되는가

1) 분배 알고리즘 (간단히)

핵심: shrinkbasis 가중치와 함께 곱해진다. 큰 항목이 더 많이 줄어든다.

2) flex: 1 1 0 vs flex: 1 1 auto — 가장 흔한 혼동

케이스basis결과
flex: 1 1 00모두 0에서 시작, 컨테이너 폭을 grow 비율로 균등 분배 → 칸이 같음
flex: 1 1 autoauto콘텐츠 폭에서 시작, 남은 공간만 grow 비율로 분배 → 칸이 다름
flex: 10shorthand에서 단일 숫자는 grow만 → 나머지는 1 0 (shrink=1, basis=0)
/* 균등 3분할 — 어떤 콘텐츠가 들어와도 동일 폭 */
.equal > * { flex: 1 1 0; }
 
/* 콘텐츠 비례 + 남은 공간만 균등 — 짧은 칸은 좁게 */
.proportional > * { flex: 1 1 auto; }

3) flex: <num> shorthand 단축

입력해석
flex: 11 1 0%
flex: 22 1 0%
flex: auto1 1 auto
flex: none0 0 auto (고정)
flex: initial (기본)0 1 auto (안 늘지만 줄 수 있음)

단일 숫자 flex: 11 1 0인 게 함정. basis가 0이라 콘텐츠 폭이 0으로 시작한다.


What — 세부 사양

항목 속성

속성기본값의미
flex-grow0여유 공간을 가져가는 비율
flex-shrink1부족 공간에서 양보하는 비율 (basis 가중)
flex-basisauto시작 크기 — <length> / <percentage> / auto / content
flex0 1 autoshorthand
align-selfautocross 축 개별 정렬 — align-items 오버라이드
order0시각적 순서 (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: 0CSS의 “기본값을 되돌리는” 패턴이다 — box-sizing: border-box와 같은 종류의 카운터-디폴트.


요약 + Mermaid

  • flexgrow shrink basis shorthand. flex: 1 = 1 1 0.
  • flex: 1 1 0 (균등) vs flex: 1 1 auto (콘텐츠 비례) 차이를 의식적으로 선택.
  • Flex item은 min-width: auto가 기본 — ellipsis가 필요하면 min-width: 0 필수.
  • 이미지는 **flex-shrink: 0**으로 보호.

다음: 03-grid-basics — Grid template과 fr 단위.