Skip to content
This page has been auto-translated and may contain errors.View in English

Flexbox

docs.scrimba.com

버튼 세 개를 한 줄에 나란히, 간격을 균등하게, 높이를 똑같이, 그리고 텍스트 양이 달라도 항상 수직 중앙에 오도록 배치하고 싶다고 해봅시다. 예전에는 이런 걸 하려면 float와 clearfix를 쓰고 이런저런 값을 계속 추측해가며 맞춰야 했습니다. flexbox는 바로 이런 상황을 위해 만들어진 도구입니다. 컨테이너 하나에 자식들을 한 줄로 배치하라고 지시하면, 그다음 두 축을 따라 조금씩 밀어가며 원하는 위치에 맞출 수 있습니다. 웹에서 흔히 보는 레이아웃, 즉 내비게이션 바, 툴바, 카드가 줄지어 있는 형태는 대부분 그 안에 flex 컨테이너가 자리 잡고 있습니다.

flex 컨테이너

flexbox는 부모 요소에 한 줄만 추가하면 시작됩니다. 컨테이너에 display: flex를 설정하면 그 직계 자식들이 한 줄로 나란히 늘어섭니다. 이제 이 컨테이너는 **flex 컨테이너**가 되고, 그 안의 각 자식은 flex 항목이 됩니다.

css
.nav {
  display: flex;    /* 자식들이 이제 한 줄로 늘어선다 */
}

항목들은 두 방향을 따라 배치됩니다. 메인 축은 왼쪽에서 오른쪽으로, 항목들이 줄지어 서는 방향입니다. 교차 축은 위에서 아래로, 그 줄을 가로지르는 방향입니다. 이 두 축을 따라 항목을 조정하게 될 것이므로 지금 미리 그려보면 도움이 됩니다. 메인 축은 항목들이 놓이는 선이고, 교차 축은 그것을 가로지르는 방향입니다.

display: flex는 요소를 **flex 컨테이너**로 만들고, 그 직계 자식들을 flex 항목으로 만듭니다. 오직 직계 자식만 이 배치에 참여하며, 더 깊이 중첩된 것들은 각자의 부모가 배치를 담당합니다. 기본적으로 항목들은 왼쪽에서 오른쪽으로 한 줄에 놓이며, 각각 콘텐츠의 너비만큼 줄어든 크기가 됩니다.

css
.nav {
  display: flex;    /* 직계 자식들이 flex 항목의 한 줄이 된다 */
}

이 모델 전체는 두 축을 기준으로 동작합니다. 메인 축은 항목이 흘러가는 방향으로, 기본값으로는 한 줄이므로 왼쪽에서 오른쪽입니다. 교차 축은 그것과 수직으로, 위에서 아래로 흐릅니다. 앞으로 만나게 될 모든 정렬 속성은 이 두 축 중 하나에서 동작하므로, 이 둘을 구분해서 기억해 두면 나머지 내용이 자연스럽게 이해됩니다.

display: flex는 요소에 **flex 포맷팅 컨텍스트**를 부여합니다. 즉 직계 자식들이 flex 항목이 되어 일반적인 흐름이 아니라 flex 알고리즘으로 배치됩니다. 오직 직계 자식만 이 배치에 참여하며, 텍스트 런과 더 깊이 중첩된 요소는 그 아래 단계에서 처리됩니다. 이는 마진 상쇄를 막는 경계와 같은 종류의 것으로, flex 레이아웃이 예전의 float-and-clear 방식보다 더 예측 가능하게 동작하는 이유 중 하나입니다.

css
.nav {
  display: flex;    /* flex 포맷팅 컨텍스트를 만든다 */
}

모든 것은 두 축이 지배합니다. 메인 축flex-direction으로 결정되고(기본값은 row이므로 inline-start에서 inline-end 방향), 교차 축은 그것과 수직입니다. 이 구분은 단순한 겉모습이 아닙니다. justify-content는 항상 메인 축을 따라 동작하고 align-items는 항상 교차 축을 따라 동작하므로, flex-directioncolumn으로 바꾸는 순간 이 두 속성이 미는 방향도 서로 바뀝니다. "가로"와 "세로"가 아니라 축으로 레이아웃을 이해해야, 방향이 바뀌어도 일관되게 다룰 수 있습니다.

css
.nav {
  display: flex;
}

선언 하나로 어떤 블록의 자식들이든 위에서 아래로 쌓이던 것을 멈추고 한 줄로 늘어서게 됩니다. 이 장의 나머지 내용은 모두 컨테이너 안에 들어간 이 항목들을 어떻게 조정하는지에 관한 것입니다.

Junoflex 컨테이너 부모에 display: flex를 지정하면 직계 자식들이 한 줄로 늘어섭니다. 이 부모가 flex 컨테이너이고, 자식들이 flex 항목입니다. 항목들은 두 방향을 따라 움직입니다. 메인 축은 항목들이 놓이는 선이고, 교차 축은 그것을 가로지르며, 여러분은 이 두 축을 따라 항목을 밀게 됩니다.
Junoflex 컨테이너display: flex는 컨테이너가 직계 자식들을 flex 항목의 한 줄로 배치하게 만듭니다. 오직 직계 자식만 참여하며, 더 깊이 중첩된 것은 참여하지 않습니다. 두 축을 머릿속에 명확히 구분해 두세요. 메인 축은 흐름 방향이고, 교차 축은 그것과 수직이며, 모든 정렬 속성은 둘 중 하나에서 동작합니다.
Junoflex 컨테이너display: flex는 flex 포맷팅 컨텍스트를 시작하므로, 직계 자식은 flex 알고리즘으로 배치되고 그 안에서는 마진 상쇄가 일어나지 않습니다. "가로"와 "세로"가 아니라 축으로 레이아웃을 이름 붙이세요. justify-content는 메인 축을, align-items는 교차 축을 따라갑니다. flex-directioncolumn으로 바꾸면 이 둘이 미는 방향이 서로 바뀝니다.

축을 따라 정렬하기

항목들이 한 줄로 늘어서면, 두 속성으로 이들을 움직일 수 있습니다. **justify-content**는 항목들이 놓인 방향, 즉 메인 축을 따라 간격을 조정합니다. align-items는 교차 축을 따라, 즉 줄 안에서 위아래로 항목을 움직입니다.

css
.nav {
  display: flex;
  justify-content: space-between;   /* 줄을 따라 항목들을 서로 밀어낸다 */
  align-items: center;              /* 수직 중앙에 맞춘다 */
}

justify-content의 자주 쓰는 값으로는 flex-start(왼쪽에 몰림), center(가운데에 몰림), flex-end(오른쪽에 몰림), space-between(항목 사이에만 간격, 양 끝에는 없음), space-around(각 항목의 양쪽에 간격)가 있습니다. align-itemscenter를 가장 많이 쓰게 됩니다.

양쪽 방향으로 모두 중앙에 맞추려면, 누구나 처음 배우는 방법이 있습니다. 둘 다 center로 설정하는 것입니다.

css
.hero {
  display: flex;
  justify-content: center;   /* 메인 축을 따라 중앙 정렬 */
  align-items: center;       /* 교차 축을 따라 중앙 정렬 */
}

정렬을 담당하는 속성은 두 개이며, 각각 하나의 축을 맡습니다. **justify-content**는 메인 축을 따라 항목을 분배하고, align-items는 교차 축에서 항목의 위치를 정합니다. 서로 다른 축을 담당하기 때문에 이 둘은 절대 충돌하지 않으며, 서로 수직인 방향을 가리킵니다.

css
.nav {
  display: flex;
  justify-content: space-between;   /* 메인 축을 따라 항목을 펼친다 */
  align-items: center;              /* 교차 축에서 중앙에 맞춘다 */
}

justify-content에서 알아둘 값은 flex-start, center, flex-end, space-between(항목 사이 간격이 동일하고 양 끝에 붙음), space-around(각 항목 주변에 동일한 공간이 생기므로 끝 간격이 중간 간격의 절반)입니다. align-items의 기본값은 stretch로, 모든 항목이 컨테이너 높이만큼 늘어나게 만듭니다. 그래서 카드를 한 줄로 나열하면 콘텐츠가 달라도 높이가 똑같이 나오는 것입니다. align-items: center로 설정하면 항목들이 콘텐츠 높이로 다시 줄어들고 중앙에 놓이게 됩니다.

두 축 모두를 중앙 정렬하는 것이 flexbox를 유명하게 만든 속성 조합입니다.

css
.hero {
  display: flex;
  justify-content: center;   /* 메인 축 */
  align-items: center;       /* 교차 축 */
}

정렬은 축에 따라 명확히 나뉩니다. **justify-content**는 메인 축을 따라 남는 공간을 분배하고, align-items는 모든 항목의 기본 교차 축 위치를 정합니다. 서로 수직인 축에서 동작하기 때문에 충돌할 수 없지만, 둘 다 어느 방향이 "메인"인지에 따라 달라지므로 flex-direction: column을 설정하면 각각이 담당하는 방향도 서로 바뀝니다.

css
.nav {
  display: flex;
  justify-content: space-between;   /* 남는 공간이 항목 사이에 들어간다 */
  align-items: center;              /* 각 항목이 교차 축에서 중앙에 온다 */
}

사람들이 자주 헷갈리는 지점은, justify-content는 메인 축에 남는 공간이 있을 때만 의미가 있다는 점입니다. 이 속성은 남는 공간을 분배하므로, 항목들이 이미 컨테이너를 가득 채우거나(또는 넘치면) space-betweencenter는 분배할 공간이 없어 똑같아 보입니다. 반면 align-items는 컨테이너의 교차 축 크기 안에서 각 항목을 독립적으로 배치하며, 초기값은 stretch입니다. 즉 교차 축 크기가 고정되지 않은 항목은 컨테이너를 채우도록 늘어납니다. 카드를 한 줄로 나열했을 때 높이가 똑같이 나오는 것은 align-items: stretch가 기본 동작을 하고 있는 것입니다. 항목별로 이를 재정의하려면 align-self를 쓰는데, 이는 아래 크기 조정 섹션에서 다룹니다.

css
.hero {
  display: flex;
  justify-content: center;   /* 메인 축 중앙 정렬 */
  align-items: center;       /* 교차 축 중앙 정렬, stretch 기본값을 덮어씀 */
}

항목 두 개와 컨테이너에 지정한 min-height, 그리고 둘 다 center로 설정하면, 한 세대의 개발자들이 절대 위치와 음수 마진으로 흉내 내려 애썼던 중앙 정렬 문제를 이렇게 간단히 해결할 수 있습니다.

Juno축을 따라 정렬하기justify-content는 메인 축을 따라 항목 간격을 조정하고, align-items는 교차 축을 따라 항목을 움직입니다. 첫 번째 속성에서 꼭 기억할 값은 center, space-between, flex-start입니다. 둘 다 center로 설정하면 안에 든 것이 정확히 중앙에 오는데, 이 방법은 앞으로 계속 쓰게 됩니다.
Juno축을 따라 정렬하기 축마다 속성이 하나씩입니다. 메인 축에는 justify-content, 교차 축에는 align-items입니다. 기본값인 align-items: stretch 덕분에 별다른 설정 없이도 카드 줄의 높이가 똑같이 나오는 것입니다. 그리고 둘 다 center로 설정하는 것은 무엇이든 중앙에 놓는 방법으로 꼭 외워둘 만합니다.
Juno축을 따라 정렬하기justify-content는 메인 축에 남은 공간을 분배하므로, 항목들이 이미 줄을 가득 채우고 있으면 아무 일도 하지 않습니다. "왜 중앙 정렬이 안 되지"라는 상황의 원인이 대부분 여기에 있습니다. align-items는 각 항목을 교차 축에서 배치하며 기본값이 stretch라서 별다른 설정 없이 높이가 같은 줄을 얻게 됩니다. flex-direction을 바꾸면 두 속성이 작동하는 축도 서로 바뀐다는 것을 기억하세요.

방향과 줄바꿈

기본적으로 flex 컨테이너는 항목들을 한 줄로 배치합니다. 이를 바꾸려면 **flex-direction**을 사용합니다. 이를 column으로 설정하면 항목들이 나란히 놓이는 대신 위에서 아래로 쌓입니다.

css
.sidebar {
  display: flex;
  flex-direction: column;   /* 이제 항목들이 수직으로 쌓인다 */
}

한 줄에 놓인 항목들이 자리가 부족해지면 점점 더 좁게 눌립니다. 대신 새 줄로 넘어가게 하려면 flex-wrap: wrap을 추가합니다.

css
.card-row {
  display: flex;
  flex-wrap: wrap;   /* 자리가 부족한 항목은 다음 줄로 넘어간다 */
}

항목 사이 간격을 주려면 gap을 사용합니다. 이는 바깥쪽 가장자리에는 공간을 추가하지 않고, 모든 항목 사이에 일정한 간격만 추가합니다.

css
.card-row {
  display: flex;
  gap: 16px;   /* 각 항목 사이에 16px */
}

**flex-direction**은 메인 축을 정합니다. 기본값인 row는 왼쪽에서 오른쪽으로 흐르고, column은 메인 축을 수직으로 바꾸므로 항목들이 위에서 아래로 쌓입니다. 중요한 점은 이제 justify-content가 수직 간격을 조정하고 align-items가 수평 간격을 조정하게 된다는 것입니다. 순서를 뒤집어야 한다면 row-reversecolumn-reverse도 있습니다.

css
.sidebar {
  display: flex;
  flex-direction: column;   /* 메인 축이 이제 수직이다 */
  justify-content: center;  /* 즉 이 속성이 수직 중앙 정렬을 한다 */
}

기본적으로 flex 줄은 절대 끊어지지 않습니다. 항목들은 줄바꿈 대신 줄어들어 맞춰집니다. flex-wrap: wrap을 설정하면 들어갈 자리가 없는 항목이 새 줄로 넘어가는데, 이것이 미디어 쿼리 없이도 반응형 카드 그리드를 만들 수 있게 해주는 요소입니다.

css
.card-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;   /* gap은 두 축 모두에 적용된다: 행과 열 사이에 16px */
}

간격을 줄 때는 항목에 마진을 주는 대신 gap을 사용하세요. gap은 항목 사이에만 적용되고 바깥쪽 가장자리에는 절대 적용되지 않으므로, 마지막 자식에서 마진을 제거하는 작업을 할 필요가 없습니다.

**flex-direction**은 메인 축을 정의하고, 축에 의존하는 모든 속성이 이를 따릅니다. row(기본값)는 메인 축을 수평으로 만들고, column은 이를 수직으로 만들면서 동시에 justify-content를 수직 간격 조정으로, align-items를 수평 간격 조정으로 은연중에 재할당합니다. -reverse 변형들은 메인 축의 방향을 뒤집지만, 시각적으로만 순서를 바꾼다는 점에 주의해야 합니다. DOM 순서는 그대로이므로 키보드와 스크린 리더의 탐색 순서는 여전히 소스 순서를 따르며, row-reverse를 쓸 때는 이 점이 실질적인 접근성 문제가 됩니다.

css
.sidebar {
  display: flex;
  flex-direction: column;    /* 메인 축이 수직이 되어 justify-content가 수직 중앙 정렬을 한다 */
  gap: 8px;
}

flex-wrap: wrap은 한 줄 제한을 없애줍니다. 이것이 없으면 flex 컨테이너는 모든 항목을 한 줄에 강제로 밀어넣고 부족한 공간은 항목들을 줄여서 처리합니다. 이것이 있으면 메인 크기를 넘치는 항목이 새 줄로 넘어가고, 컨테이너는 여러 줄이 됩니다. 줄바꿈이 켜지면 align-content(align-items와는 다른 속성)가 교차 축에서 줄들 간의 간격을 조정합니다. gap은 항목 사이, 그리고 줄바꿈이 일어났을 때는 줄 사이의 간격을 설정하며, 이것이 올바른 도구입니다. 마진과 달리 아무것도 상쇄하지 않고, 가장자리에 공간을 추가하지도 않으며, 하나의 간격 결정으로 명확하게 읽힙니다.

css
.card-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 24px;   /* row-gap 16px, column-gap 24px */
}

여기서 CSS grid와의 경계도 드러납니다. flex wrap은 한 줄을 채운 뒤 줄바꿈을 하므로, 서로 다른 행에 있는 항목들이 열로 정렬되지는 않습니다. 행과 열이 모두 정렬되는 진짜 2차원 그리드가 필요하다면, 그것은 flexbox가 아니라 grid의 역할입니다.

Juno방향과 줄바꿈flex-direction: column은 항목을 한 줄로 놓는 대신 수직으로 쌓습니다. flex-wrap: wrap은 자리가 부족한 항목을 눌러 찌그러뜨리는 대신 새 줄로 넘깁니다. 그리고 gap은 가장자리에는 공간을 추가하지 않고 항목 사이에만 균등한 공간을 넣어주므로, 마진보다 먼저 떠올려야 할 도구입니다.
Juno방향과 줄바꿈flex-direction은 메인 축을 정하고, column으로 바꾸면 justify-content가 이제 수직 간격을 조정하게 되는데, 이는 한 번쯡은 놀라게 되는 부분입니다. flex-wrap: wrap은 미디어 쿼리 없이도 카드 줄이 다시 배치되게 해주는 핵심입니다. 마지막 항목의 남는 마진을 쫓아다니지 않으려면 간격 조정에는 gap을 사용하세요.
Juno방향과 줄바꿈flex-direction은 메인 축을 정의하고 축을 기반으로 하는 모든 속성이 이를 따르지만, -reverse 값들은 시각적으로만 순서를 바꾸고 DOM과 포커스 순서는 그대로 두므로 주의해서 써야 합니다. flex-wrap은 컨테이너를 여러 줄로 만들고 줄 간격을 align-content에 맡깁니다. 줄바꿈된 항목들이 진짜 열로 정렬되어야 한다면, 그것은 grid의 역할이지 flexbox의 역할이 아닙니다.

항목의 유연한 크기 조정

flexbox의 핵심은 항목들이 늘어나거나 줄어들면서 공간을 나눠 가질 수 있다는 점입니다. 가장 많이 쓰게 될 축약 속성은 항목에 지정하는 flex: 1로, 이는 해당 항목에게 늘어나서 사용 가능한 공간을 균등하게 나눠 가지라고 지시합니다.

css
.card {
  flex: 1;   /* 모든 카드가 균등하게 늘어나 줄을 나눠 가진다 */
}

한 줄에 있는 카드 세 개에 모두 flex: 1을 주면 컨테이너가 세 개의 동일한 너비로 나뉩니다. 한 카드에만 flex: 2를 주면 다른 카드보다 두 배의 공간을 차지합니다. 이 숫자 하나가 항목들이 남는 공간을 나누는 방식을 결정합니다.

flex: 1 뒤에는 세 가지 독립적인 설정이 숨어 있습니다. 항목이 얼마나 늘어나는지, 얼마나 줄어드는지, 그리고 시작 크기입니다. 처음에는 이 값들을 하나씩 직접 설정할 일이 거의 없습니다. 축약 속성이 흔한 경우를 다 처리해주지만, 그 뒤에 이런 값들이 있다는 것을 알아두면 도움이 됩니다.

세 가지 속성이 항목들이 공간을 나눠 갖는 방식을 결정합니다. **flex-grow**는 남는 공간을 채우기 위해 항목이 얼마나 늘어나는지를 정합니다(0이면 늘어나지 않음). flex-shrink는 공간이 부족할 때 얼마나 양보하는지를 정합니다(기본값 1은 줄어들 수 있다는 뜻입니다). flex-basis는 늘어나거나 줄어들기 전 항목의 시작 크기를 정하며, 기본값은 auto로 "콘텐츠나 width를 사용하라"는 뜻입니다.

flex 축약 속성은 이 셋을 한꺼번에 지정하며, 실제로 자주 쓰는 값은 몇 가지뿐입니다.

css
.card {
  flex: 1;   /* grow 1, shrink 1, basis 0: 동일한 너비의 열 */
}

.sidebar {
  flex: 0 0 240px;   /* 늘어나지도 줄어들지도 않고 240px 유지 */
}

flex: 1은 가장 많이 쓰이는 값입니다. 콘텐츠와 무관하게 항목들이 줄을 균등하게 나눠 갖게 만드는데, 그 이유는 0 basis 때문에 항목들이 아무것도 없는 상태에서 시작해 오직 grow 비율만큼만 늘어나기 때문입니다. flex: 0 0 240pxflex: 1인 메인 영역 옆에 붙는 고정 너비 사이드바로, 앞으로 계속 만들게 될 레이아웃입니다.

항목의 크기는 컨테이너가 순서대로 평가하는 세 가지 속성으로 결정됩니다. **flex-basis**는 남는 공간이 분배되기 전 항목의 시작 메인 축 크기입니다. 기본값 auto는 항목의 width(또는 콘텐츠 크기)를 그대로 따릅니다. 그다음 컨테이너는 basis 값들의 합과 자신의 크기 사이의 차이를 계산합니다. 남는 공간이 있으면 각 항목의 flex-grow 비율에 따라 나눠줍니다. 부족한 공간이 있으면 각 항목의 flex-shrink를 basis로 가중한 값에 따라 다시 회수합니다.

css
/* flex: 1은 flex-grow: 1, flex-shrink: 1, flex-basis: 0%로 확장된다 */
.card {
  flex: 1;   /* basis 0이므로 항목이 콘텐츠 너비를 무시하고 grow 비율로만 공간을 나눈다 */
}

미묘한 부분은 flex-basiswidth의 관계인데, 이 둘은 서로 상호작용합니다. flex-basis: 0(flex: 1처럼)은 항목이 콘텐츠를 무시하고 grow 비율만으로 공간을 나누게 만들어 진정한 동일 너비 열을 만들어줍니다. flex-basis: auto(flex: auto처럼, 또는 일반적인 width)는 각 항목이 콘텐츠 크기나 지정된 width로 시작하고 그다음에야 나머지를 나눠 갖게 만들어, 콘텐츠가 많은 항목이 결국 더 넓어지게 됩니다. 둘 중 무엇을 선택하느냐는 결국 콘텐츠가 최종 너비에 영향을 미치게 할지를 선택하는 문제입니다.

실무에서 알아둘 두 가지가 있습니다. 첫째, 둘 다 지정되어 있으면 flex-basiswidth를 이깁니다. 그러므로 어떤 요소가 flex 항목이 된 이상, 그 크기는 flex로 표현하는 것이 좋습니다. 둘째, 오버플로우와 관련된 함정이 있습니다. flex 항목은 기본값으로 min-width: auto를 가지므로, 콘텐츠의 고유 크기보다 작게 줄어들기를 거부합니다. 그래서 긴 단어나 넘치는 자식 요소가 줄 전체를 망가뜨릴 수 있습니다. 해결책은 줄어들 수 있어야 하는 항목에 min-width: 0을 지정하는 것입니다.

css
.main {
  flex: 1;
  min-width: 0;   /* 이 항목이 콘텐츠보다 작게 줄어들 수 있게 하여, 넘치는 대신 긴 텍스트가 잘리게 한다 */
}

align-self는 개별 항목에 대해 align-items를 재정의하므로, 다른 항목은 중앙에 정렬되어 있어도 한 항목만 flex-start에 놓을 수 있습니다. 그리고 도구 선택에 대한 조언입니다. 1차원 레이아웃, 즉 내비게이션 바, 툴바, 항목들이 한 줄이나 한 열로 이어지는 경우에는 flexbox를 쓰세요. 행과 열이 동시에 정렬되어야 한다면 CSS grid가 맞는 도구입니다. 이 모든 계산 아래에서 너비가 실제로 어떻게 결정되는지 궁금하다면, 크기 단위 문서에서 퍼센트와 다른 단위들이 여기서 어떻게 동작하는지 다룹니다.

css
.layout {
  display: flex;
  gap: 24px;
}
.sidebar {
  flex: 0 0 240px;   /* 고정 240px, 늘어나거나 줄어들지 않는다 */
}
.main {
  flex: 1;           /* 남는 공간을 모두 차지한다 */
}

고정된 사이드바 옆에 유연한 메인 열, 딱 세 줄로 의도를 표현했습니다. 이 한 가지 패턴에 앞서 나온 정렬된 내비게이션 바를 더하면, 앞으로 만들게 될 레이아웃의 상당 부분을 다룰 수 있습니다.

Juno항목의 유연한 크기 조정 항목에 지정한 flex: 1은 늘어나서 줄의 공간을 균등하게 나눠 가지라는 뜻이므로, flex: 1을 가진 카드 세 개는 같은 너비로 나옵니다. 하나를 flex: 2로 올리면 두 배의 공간을 차지합니다. 이 숫자 하나로 flex 항목들이 공간을 나누는 방식이 정해집니다.
Juno항목의 유연한 크기 조정flex 축약 속성은 grow, shrink, basis를 한꺼번에 지정합니다. flex: 1은 동일한 너비의 열을 만들어주는데, 그 0 basis 때문에 항목들이 아무것도 없는 상태에서 시작해 균등하게 늘어나기 때문입니다. flex: 0 0 240pxflex: 1인 메인 영역 옆에 붙는 고정 사이드바로, 앞으로 계속 쓰게 될 레이아웃입니다.
Juno항목의 유연한 크기 조정flex-basis는 공간이 나눠지기 전 시작 크기이며, flex 항목에서는 width를 이깁니다. 그래서 flex: 1(basis 0)은 공간을 균등하게 나누고, flex: auto는 콘텐츠가 너비에 영향을 미치게 합니다. 기본값인 min-width: auto를 주의하세요. 이 값은 항목이 콘텐츠보다 작게 줄어드는 것을 막아서 min-width: 0을 설정하기 전까지는 줄을 넘치게 만듭니다. 한 항목만 정렬에서 빼고 싶다면 align-self를 쓰고, 행과 열이 모두 정렬되어야 하는 순간에는 grid로 넘어가세요.