Flex Item 요소의 최종 크기 계산
본 문서에서는 flex-direction: row 기준으로 설명 드리도록 하겠습니다.
즉, Flex Items의 최종 너비가 계산되는 원리를 설명 합니다.
flex-basis
초기값: auto, 해당 요소의 내부 콘텐츠 크기 만큼 자동 계산.
flex-basis는 flex-grow, flow-shrink속성이 동작 하는 기준 값입니다. flex-basis속성 값을 먼저 이해해야 flex-grow, flex-shrink속성을 차례로 이해 할 수 있습니다.
- flex-basis: 0: 내부 콘텐츠 크기와 관계없이, 기준 값을 0으로 설정.
- flex-basis: 200px: 내부 콘텐츠 크기와 관계없이, 기준 값을 200px 고정값으로 설정.
flex-grow
초기값: 0, 확장 시키지 않음.
flex-grow속성은 Flex Items요소의 너비를 확장 시킬 수 있는 방법입니다. 구체적인 수치값으로 너비 확장을 만들어 내는 방식이 아닌, 가용 공간(아직 할당되지 않은 공간)을 비율로 나누어 해당 요소의 너비를 확장 할 수 있게 만듭니다.
최초에는 flex-basis속성값만으로 각 요소의 크기가 결정 되어있는 상태입니다.
<div class="flex-container">
<div class="flex-item">FrogFrogFrog</div>
<div class="flex-item">FrogFrog</div>
<div class="flex-item">Frog</div>
</div>
.flex-container {
display: flex;
}
.flex-item {
/* flex-basis: auto; flex-basis속성의 초기값 -> 내부 콘텐츠 크기 만큼 */
flex-grow: 1;
box-shadow: inset 0 0 20px red;
}
세개의 flex-item요소가 가용 공간을 1 : 1 : 1 비율로 나누어 가지는 것을 예상 해 볼 수 있습니다.
하지만 실제 결과는, 가용 공간을 단순히 3등분한 결과가 아닌 것을 확인 할 수 있습니다.
flex-grow속성 값은 기준 크기가 되는 flex-basis속성 값에 더해지는 값이기 때문입니다.
첫번째 .flex-item의 내부 콘텐츠 크기에 가용 공간의 1/3 너비가 할당 되었음을 알 수 있습니다.
.flex-container {
display: flex;
}
.flex-item {
flex-basis: 0; /* 또는 200px과 같은 고정값 */
flex-grow: 1;
box-shadow: inset 0 0 20px red;
}
이렇게 flex-basis: auto를 고정 값 개념으로 바꾸게 된다면, 내부 콘텐츠의 크기와 관계없이 flex-grow속성만으로 크기가 결정 되게 할 수 있습니다.
flex-basis: 0은 flex-grow만으로 해당 요소의 너비를 결정 지을 수 있는 방법이 됩니다. 즉, 가용 공간만을 너비로 취하여 단순한 방식으로 가변 레이아웃 구성을 만드는 것입니다.
flex-shrink
초기값: 1, 상황에 따라 수축 됨.
Flex Items요소에게 지정된 flex-basis속성 값은, 상황에 따라 보장 되지 못하고 수축이 될 수 있습니다. flex-shrink속성은 수축에 대한 비율을 의미합니다. Flex Items들의 모든 너비가 직계 부모 Flex Container요소의 크기를 넘어서게 된다면, Flex Items요소에게 지정된 기준 값인 flex-basis속성 값이 수축 되게 될 것입니다. Flex Items요소가 수축 되어야 하는 상황에 도달되면, 모든 요소가 같은 비율로 수축되게 됩니다. 만약 flex-shrink: 0을 지정하게 되면, 해당 요소의 flex-basis속성의 값이 어떠한 경우에도 수축되지 않고 유지 되게 됩니다.
flex-shrink: 1 이지만 수축 현상이 발생하지 않는 케이스
- flex-wrap: wrap이 지정되면 수축이 필요한 상황이 발생될 가능성이 낮아지게 됩니다.
- 내부 텍스트가 적절한 띄어쓰기로 구성 되어있다면, 수축이 필요한 상황에서 줄바꿈이 일어나게 되고, 이로 인해 해당 요소의 너비를 재계산 합니다. 결국 실질적인 수축 현상은 발행하지 않게 됩니다.
min-width
초기값 auto
Flex Items의 min-width: auto가 계산 되는 원리를 알아 보겠습니다. width속성의 사용 유무에 따라 달라집니다.
- width속성이 특정 값으로 지정 되어있을 때: width속성에 지정된 특정 값으로 min-width가 계산 됩니다. (동기화)
- width속성이 auto일 때, 즉 지정 되지 않았을 때: 내부 콘텐츠 크기만큼으로 계산됩니다. 즉, Flex Items의 크기는 내부 콘텐츠의 크기보다 더 작아 질 수 없습니다. 결과적으로, 내부 콘텐츠의 크기만큼 직계 부요 요소의 크기를 증가시키는 결과를 가지고 오는 것입니다.
flex-basis의 속성 값을 0으로 지정하면 어떤 일이 발생할까요?
flex-basis 속성의 값을 0으로 지정해도 해당 요소의 실제 크기는 0이 되지 않습니다. 즉, flex-basis: 0속성 값을 지정해도 내부 콘텐츠가 존재한다면 (텍스트 또는 이미지) 해당 요소는 결코 0이 될 수 없습니다. (물론 flex-basis속성 값을 기준으로 동작하는 flex-grow는 flex-basis: 0 기준에서 정상 동작 됩니다.)
이때 min-width: 0으로 지정하게 된다면 auto가 아니므로, 해당 Flex Items는 내부 콘텐츠의 크기보다 더 작아 질 수 있는 상태가 됩니다.
이 개념은 내부에 어떤 요소도 안정적으로 담아 낼 수 있는 레이아웃 개념을 만들어 낼 때에 특히 중요합니다.
Flex Items요소의 min-width: auto가 내부 콘텐츠 크기 만큼으로 계산 되어지는 것은 사실 매우 자연스러운 스펙입니다. 해당 개념은 일반적인 케이스에서는 유용한 개념으로 활용됩니다.
width
- flex-basis값과 width값이 동시에 지정 되어있다면 flex-basis 값이 더 우선시 됩니다.
- width속성 값을 특정 값으로 지정한 상태에서 다음과 같은 속성이 지정 되어있지 않다면 다음과 같이 계산 되어 집니다.
- flex-basis: auto일때: width속성 값으로 동기화 됨.
- min-width: auto일때: width속성 값으로 동기화 됨.
특히 width속성 값을 특정 값으로 지정 하였을 때 min-width속성 값도 똑같이 계산되어 진다는 점에 주목 할 필요가 있습니다. 즉, min-width관련 된 이슈 사항이 발생되지 않습니다.
.flex-item {
width: 200px;
/* width속성 값을 직접 지정함으로서, 자동으로 계산되는 다른 속성들!
flex-basis: auto => 200px로 계산
min-width: auto => 200px로 계산
*/
}
width속성또한 flex-shrink: 1에 의해 수축 됩니다. width속성 값이 flex-shrink: 1에 의해 수축 될 때, flex-basis, min-width 모두. 수축되는 width속성 값과 동일하게 다시 계산 되어 집니다.
width vs. flex-basis
일반적인 경우에 이 두개의 속성 모두 요소의 너비를 지정하기 위해 쓰입니다.
해당 요소의 너비를 좀 더 명확하게 강제하고 싶을 땐 width속성을, 해당 요소의 너비를 가변으로 가져가고 싶을 땐 flex-basis속성을 활용하는 편입니다.
물론 다른 여러 속성과 결합하여 효과를 만들어 내기 때문에 이러한 패턴을 암기하기 보다는, 각 속성의 스펙을 자세히 검토하여 맥락에 맞게 활용 하는편이 좋습니다.
너비 강제하기
.flex-item {
width: 300px; /* min-width: auto는 더이상 내부 콘텐츠 크기 만큼이 아니게 됨. 내부 콘텐츠의 변화에도 안정성 유지 가능 */
flex-shrink: 0; /* flex-shrink: 1이라면 상황에 따라 수축될 가능성이 있음. 너비를 좀 더 강력히 강제하기 위해 0 지정 가능 */
}
width속성의 값으로 300px을 지정하게 되면, 내부 콘텐츠의 크기가 300px이상이 된다고 해도 해당 요소의 너비가 변하지 않습니다. (width속성 값이 특정값으로 지정 되어 min-width: auto의 의미가 변경됨. width 속성 값과 동기화). 이는 곧 안정적인 레이아웃으로 볼 수 있는 상황입니다.
하지만, 여전히 flex-shrink: 1속성 값에 의해 width: 300px 값이 유지 되지 않고 수축 될 수 있으니 flex-shrink: 0속성을 부여하기도 합니다. min-width속성 값을 아예 300px로 잡아 버리는 것도 가능합니다만, 동일한 수치인 300px을 두번 적게 됨으로서 추천하지 않습니다.
같은 결과물을 width속성을 사용하지 않고 flex-basis속성을 이용하면 다음과 같습니다.
.flex-item {
flex-basis: 300px;
min-width: 0; /* 내부 콘텐츠의 크기가 부모 컨테이너보다 클때, 부모 컨테이너의 크기가 같이 커지지 않게 막기 */
flex-shrink: 0; /* flex-basis: 300px이 보장되게 */
}
콘텐츠와 관계없이 flex-grow속성으로만 가득 채우기
주로 가변 레이아웃을 만들어 낼 때에 활용합니다.
.flex-item {
flex-basis: 0; /* flex-grow속성의 기준 값을 0으로 설정. 내부 콘텐츠의 크기가 중요하지 않음. */
min-width: 0; /* 내부 콘텐츠의 크기가 부모 컨테이너보다 클때, 부모 컨테이너의 크기가 같이 커지지 않게 막기 */
flex-grow: 1; /* 가용 공간을 모두 채우기 */
}
width속성 이용도 가능합니다.
.flex-item {
width: 0; /* flex-basis: 0, min-width: 0 */
flex-grow: 1;
}