우리가 직전 10단계 포스팅에서 다루었던 것은 오직 '부모(Flex Container)'의 입장이었습니다. 부모가 display: flex를 선언하고, 자식들을 왼쪽으로 밀어붙일지(justify-content), 세로로 중앙에 줄을 세울지(align-items)라는 전체적인 '정렬과 방향'의 규칙을 통제하는 법을 배웠습니다. 하지만 실무 레이아웃은 그렇게 호락호락하지 않습니다. "왼쪽의 메뉴바는 무조건 250px로 크기를 고정하고, 오른쪽 본문 영역은 사용자의 모니터가 커지면 커지는 대로 남은 빈 공간을 쫙쫙 다 빨아들여서 넓어지게 해주세요!" 같은 디테일하고 이기적인 요구사항들이 쏟아집니다. 이때 필요한 것이 바로 '자식(Flex Item) 요소'들에게 개별적으로 부여하는 고무줄 속성들입니다. Flexbox의 진짜 강력함은 부모의 정렬 명령에 얌전히 따르는 것을 넘어, 자식들끼리 남은 잉여 공간을 두고 치열하게 '비율 싸움'을 벌이거나, 좁은 공간에서 누가 덜 찌그러질지 눈치 게임을 하는 동적인(Flexible) 크기 조절에 있습니다. 이번 11단계 포스팅에서는 주니어 개발자들이 가장 헷갈려 하지만 반응형 UI의 절대 코어 기술인 flex-grow, flex-shrink, flex-basis의 수학적 팽창/수축 원리와, HTML 뼈대를 뜯어고치지 않고도 화면 순서를 마술처럼 바꿔치기하는 order 속성까지 상세히 알아보겠습니다.

1. 공간을 향한 탐욕: flex-grow (팽창 지수)
자식 박스들은 태어날 때 기본적으로 flex-grow: 0;이라는 속성을 가집니다. 즉, 부모 박스가 아무리 넓어서 옆에 빈 텅 빈 공간(여백)이 태평양처럼 남아돌아도, 자식들은 딱 자신의 알맹이(콘텐츠) 크기나 지정된 width 만큼만 공간을 차지하고 더 이상 욕심을 내지 않습니다.
하지만 특정 자식에게 flex-grow: 1;이라는 탐욕의 마법을 부여하는 순간 돌변합니다. 이 자식 요소는 부모 박스 내부에 남은 '잉여 공간'을 남김없이 쫙 빨아들여서 자기 덩치를 늘려버립니다.

만약 두 명의 자식에게 모두 flex-grow: 1;을 주면 어떻게 될까요? 남은 빈 공간을 정확히 1:1 비율로 공평하게 나누어 먹고 사이좋게 늘어납니다. 만약 첫 번째 자식에게 grow: 2를, 두 번째 자식에게 grow: 1을 준다면? 남은 공간을 2:1의 비율로 파이 나누듯이 쪼개 가져갑니다.이 속성을 이용하면 모니터가 커지든 작아지든 화면을 꽉 채우는 '스프링 같은' 반응형 그리드를 수학적 계산(px) 없이 완벽하게 구현해 냅니다.
2. 생존을 위한 다이어트: flex-shrink (수축 지수)
반대로, 부모 박스가 좁아져서 자식들이 살 공간이 부족해지면(Overflow 위기) 어떻게 될까요? 자식들의 기본값은 flex-shrink: 1;입니다. 즉, "공간이 부족하면 우리 모두 사이좋게 똑같은 비율로 자신의 덩치를 깎아서(수축해서) 이 비좁은 부모 박스 안에 어떻게든 다 같이 우겨 들어가자!"라는 훌륭한 희생정신을 가지고 있습니다.

하지만 실무에서는 "왼쪽에 있는 프로필 사진 박스는 화면이 좁아져도 절대 찌그러지면 안 돼!"라는 요구가 생깁니다. 이때 프로필 사진 박스에 flex-shrink: 0; (수축을 거부함)을 주면, 이 박스는 강철처럼 단단해져서 공간이 아무리 좁아져도 자기 본래 크기를 절대 포기하지 않습니다. 대신 그 옆에 있는 가엾은 텍스트 박스들이 남은 몫까지 덤터기를 쓰고 엄청나게 쪼그라들며 화면을 방어하게 됩니다. 이것이 모바일 반응형 UI에서 특정 고정 크기 UI를 보호하는 핵심 스킬입니다.
3. 팽창과 수축의 출발선: flex-basis (기본 크기)
width 속성과 아주 비슷해 보이지만, Flexbox 생태계에서는 훨씬 강력하고 똑똑한 녀석입니다. flex-basis는 자식 박스들이 grow(팽창)나 shrink(수축)를 시작하기 전, "공간을 나누기 전 나의 쌩얼(최초) 크기는 이거야!"라고 브라우저에게 선언하는 기준점(Base)입니다.
기본값은 auto이며, 이는 자식 박스 안에 들어있는 글씨나 콘텐츠의 고유 크기를 출발선으로 삼겠다는 뜻입니다. 만약 flex-basis: 200px;을 주면, 일단 200px의 크기를 먹고 들어간 상태에서, 남은 공간을 grow 비율에 따라 더 가져오거나, 좁으면 shrink 비율에 따라 200px에서 살을 깎아내기 시작합니다. Flex 레이아웃 내부에서는 멍청한 width 속성을 지워버리고 유연한 flex-basis를 사용하는 것이 렌더링 버그를 막는 프론트엔드의 정석입니다.
4. 실무 최강의 압축 마법: flex 단축 속성 (Shorthand)
고수들은 위 세 가지 속성을 세 줄에 걸쳐 쓰지 않고, flex라는 단축 속성 하나로 우아하게 뭉뚱그려 사용합니다.
/* 💡 실무 Flex Item 삼위일체 공식 */
.item {
/* flex: [grow] [shrink] [basis] */
flex: 1 1 auto;
/* 해석: 공간이 남으면 1의 비율로 팽창하고, 모자라면 1의 비율로 수축하며, 최초 크기는 콘텐츠 알맹이 기준(auto)으로 해라! */
}
.fixed-sidebar {
flex: 0 0 250px;
/* 해석: 남는 공간을 먹지도 않고(0), 좁아져도 수축하지 않으며(0), 영원히 250px이라는 강철 같은 고정 크기를 유지하라! */
}
5. 마이웨이를 걷는 녀석들: align-self와 order
부모(Container)가 align-items: center;로 모든 자식들을 세로 정중앙에 집합시켰습니다. 그런데 막내 자식 하나만 "난 싫어! 난 위쪽에 붙을 거야!"라고 반항하고 싶을 때, 부모의 전체 명령을 개무시하고 혼자서만 튀는 정렬을 가능케 하는 속성이 바로 align-self: flex-start;입니다.
더욱 충격적인 것은 order 속성입니다. HTML 코드상으로는 1번, 2번, 3번 순서로 태그가 짜여 있더라도, 1번 요소에 order: 3;을, 3번 요소에 order: 1;을 줘버리면 브라우저 화면에는 3번이 제일 먼저 나오고 1번이 맨 끝으로 밀려나는 시각적 재배치 마술이 일어납니다. 자바스크립트로 DOM 구조를 뜯어고칠 필요 없이, 오직 CSS만으로 모바일 화면에서 특정 중요한 광고 박스나 메뉴를 맨 위로 끌어올리는 반응형 UX의 강력한 무기로 쓰입니다. 단, 시각적으로만 순서가 바뀌고 실제 시각 장애인용 스크린 리더기가 읽는 순서(HTML 구조)는 변하지 않으므로 접근성 측면에서는 남발해서는 안 됩니다.
정리하며
이번 11단계 포스팅에서는 부모의 통제 속에 놓인 자식들(Item)이 어떻게 서로 공간을 두고 밀당(Grow, Shrink)을 하며, 자신만의 고유한 비율(Basis)을 방어해 내는지에 대한 Flexbox의 심화 수학 모델을 상세 분석 해보았습니다. 1편의 Container 속성과 2편의 Item 속성을 완벽히 버무릴 줄 안다면, 지구상에 존재하는 그 어떤 1차원 배치의 UI(네비게이션, 푸터, 댓글 리스트)도 완벽하게 반응형으로 찍어낼 수 있습니다. 하지만, 인간의 욕망은 끝이 없습니다. "가로 한 줄 맞추는 건 알겠어. 그런데 바둑판처럼 가로세로를 동시에 완벽하게 바둑판 썰 듯이 나누고 그 칸 안에 요소들을 자유자재로 꽂아 넣을 순 없을까?" 1차원(선)의 한계를 부수고 2차원(면)의 세계로 진입하는 CSS 레이아웃의 끝판왕이자 최종병기!
다음 12단계 포스팅에서는 "CSS Grid (1편): Flexbox의 한계를 부수는 2차원 바둑판 레이아웃의 탄생"에 대해 상세히 파헤쳐 보겠습니다!
'StyleSheet > CSS' 카테고리의 다른 글
| [CSS] 실무에서 자주 쓰이는 Flexbox UI 패턴 5가지 완벽 정복 (0) | 2026.07.28 |
|---|---|
| [CSS] Grid (0) | 2026.07.28 |
| [CSS] Flexbox 컨테이너 속성 (0) | 2026.07.28 |
| [CSS] Flexbox (1편: Container) (0) | 2026.07.28 |
| [CSS] Variables (사용자 지정 속성) (0) | 2026.07.28 |