: 프로젝트를 진행하면서 레거시 코드를 수정할 일이 있었는데, 그 과정에서 flex: 1
이 꽤나 많이 쓰이고 있는 것을 알게 됐고, 정확히 어떤 역할로 이걸 쓰고 있는지를 공부해봤다.
: flex: 1이 뭔지를 알기 전에 알아야할 3가지 속성이 있다.
예시에 쓰인 JSX
<div className=".flex-container ">
<div className="box box1">O</div>
<div className="box box2">O</div>
<div className="box box3">O</div>
</div>
: flex-basis는 flex container를 구성하는 item 들이 있을 때, 해당 item에 줄 수 있는 속성으로 item에서 기본 크기를 세팅할 때 쓴다. 만약 flex-basis가 auto로 돼있으면(default) item에 걸어준 width, height 값이 해당 item의 넓이 혹은 높이로 적용된다(이건 flex-direction에 따라 다를 것이다). 또한, 이런식으로 item의 flex-basis를 110px 정도로 세팅해놔도 item 내의 컨텐츠에 의해 width가 flex-basis를 넘어가게 된다. 추가로, 콘텐츠가 없다면 즉, 빈 div 태그 등을 놓고 flex-basis 속성을 110px 이렇게 줘도 결국 width는 0으로 표현된다. 이 flex-basis는 뒤에서 설명할 flex-grow, flex-shrink의 기준이 된다.
: flex-grow는 flex-basis를 제외하고 남는 여백이 있을 때, 그 여백을 해당 item이 얼마만큼의 비율을 가지고 차지할 것인가를 결정하는 속성이다. default 값은 0으로 여백에 대해서 늘어나는 현상이 없는게 default이다. 하지만, flex-grow: 1
이렇게 설정해주면 flex-basis를 제외하고 남는 여백에 대해 1의 비율만큼 해당 item이 차지하는 것으로 설정하는 것이다. 따라서, 이렇게 사용할 수 있다. 이런식으로 본래
.box {
flex-basis: 100px;
background-color: blue;
}
.box1 {
flex-grow: 1;
}
.box2 {
flex-grow: 2;
}
.box3 {
flex-grow: 3;
}
flex-basis는 100px으로 맞춰놨고, flex-container가 div 태그이고, width를 주지 않았을 때, 즉 길이 제한이 없기 때문에 div 태그의 특성상 width는 viewport에서 padding, margin 값을 뺀 width 가 된다. 따라서, flex-basis 3개(100 + 100 + 100 = 300px)을 제외하고, 남는 여백을 flex-grow 비율대로 가져가게 되고 그 결과가 위의 이미지이다. 1/6, 2/6, 3/6 이렇게 가져갔다고 생각하면 된다. 추가로 2개는 값을 정해놓고 쓰고, 나머지 여백을 하나 남은 item으로 채울 때도 쓸 수 있다.
.flex-container {
font-family: sans-serif;
text-align: center;
display: flex;
gap: 5px;
}
.box {
flex-basis: 110px;
background-color: blue;
}
.box1 {
flex-grow: 1;
}
.box2 {
}
.box3 {
}
: 마지막으로 flex-shrink는 flex-basis를 기준으로 flex-grow와 반대로 작아질 수 있는지 없는지를 결정해주는 속성이다. flex-shrink는 default로 1의 값을 갖는데, 이는 작아질 수 있음을 의미한다. 반대로 0은 작아질 수 없는 고정을 의미한다(작아지는 측면에서의 고정이지 늘어나는 측면까지 flex-shrink가 결정하는 것은 아니다). min-width을 쓰는 것처럼 쓰면 되는데, 예를 들어, 특정 item이 100px 보다는 작아지면 안되는 경우에 flex-shrink를 이런식으로 0으로 줘서 쓸 수 있다.
.flex-container {
font-family: sans-serif;
text-align: center;
display: flex;
gap: 5px;
width: 700px;
}
.box {
background-color: blue;
}
.box1 {
width: 100px;
}
.box2 {
width: 100px;
}
.box3 {
width: 600px;
}
이 때, 만약 두번째 item을 무조건 100px로 유지해야한다고 해보자. 지금은 전체 width인 700px에 맞춰 100px, 100px, 600px의 비중만큼 나눠가지며 자동으로 배분이 된 상태이다. 즉, 100, 100, 600px을 갖지 않고, 조금씩 다른 값을 갖는다(86.25px, 86.26px, 517.5px). 이 때, 가운데 item의 width를 100px로 고정시키고 싶다면, 이렇게 써주면 된다.
.flex-container {
font-family: sans-serif;
text-align: center;
display: flex;
gap: 5px;
width: 700px;
}
.box {
background-color: blue;
}
.box1 {
width: 100px;
}
.box2 {
flex-shrink: 0;
width: 100px;
}
.box3 {
width: 600px;
}
미세한 차이처럼 보이지만 가운데가 첫번째 item보다 커졌고 넓이도 정확히 100px이 된 것을 볼 수 있다. 이처럼 flex-shrink는 최소값을 고정시키고 싶을 때 쓰면 된다.
: 그럼 다시 본론으로 들어와서 flex: 1은 뭘까. flex: 1은 앞서 설명한 세개의 속성을 한번에 관리할 수 있는 속성이다. 정확히 flex: 1은 다음과 같다
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
위에서 살펴본 내용에 따르면, 위의 flex: 1은 결론적으로 flex-basis가 0%이기에 본연의? 넓이 혹은 높이는 포기한 채로 남은 여백에 의해 길이가 결정되는 것(flex-grow: 1로 늘려지든 flex-shrink: 1로 줄여지든)
으로 볼 수 있다. 그래서 만약 높이가 정해져 있는 flex-container 안에서 두개의 item이 있는데, 한개의 item 높이는 고정이라면 그리고 나머지 item에 대해서 남는 여백을 다 차지하고 싶도록 하고 싶다면 나머지 item에 대해 flex: 1을 써주면 간편하다.
위와 같이 이미지 보관함 파트가 36px로 고정이고 전체 container의 높이가 600px로 고정일 떄 나머지 list 부분은 flex: 1로 처리하면 간단하게 구현할 수 있다.
import "./styles.css";
export default function App() {
const ImageComponent = () => (
<img
className="image"
src="data-src"
alt="image_url"
/>
);
return (
<div className="container">
<div className="title">이미지 보관함</div>
<div className="list">
<div className="box box1">
<ImageComponent />
</div>
<div className="box box2">
<ImageComponent />
</div>
<div className="box box3">
<ImageComponent />
</div>
<div className="box box4">
<ImageComponent />
</div>
<div className="box box5">
<ImageComponent />
</div>
<div className="box box6">
<ImageComponent />
</div>
</div>
</div>
);
}
.container {
display: flex;
flex-direction: column;
width: 200px;
height: 600px;
background-color: black;
}
.title {
height: 36px;
font-size: 17px;
font-weight: 700;
text-align: center;
line-height: 36px;
background-color: yellow;
margin-bottom: 10px;
}
.list {
display: flex;
flex-direction: column;
gap: 10px;
overflow-y: scroll;
flex: 1;
}
.image {
width: 100%;
height: 100%;
object-fit: contain;
}
위와 같이 flex: 1을 현업 코드에서 꽤나 자주쓰는 것을 보게 됐고, 나도 앞으로 활용하면 좋을 것 같다는 생각을 했다.
추가로 flex 라는 속성 자체는 flex-grow, flex-shrink, flex-basis를 한 번에 쓸 수 있는 축약형 속성이다.
.item {
flex: 1;
/* flex-grow: 1; flex-shrink: 1; flex-basis: 0%; */
flex: 1 1 auto;
/* flex-grow: 1; flex-shrink: 1; flex-basis: auto; */
flex: 1 500px;
/* flex-grow: 1; flex-shrink: 1; flex-basis: 500px; */
}
이런식으로 쓸 수 있는데, 주의할점은 flex: 1처럼 쓰게 되면 뒤의 flex-basis가 자동으로 0%가 된다는 것이다. flex: 1 1 auto
처럼 세가지 값을 한번에 써주는게 아니라면 flex: 1 500px; 이런식으로 쓰게 될텐데 이렇게 쓰면 뒤의 px 값이 flex-basis로 들어가고, 앞의 1이 flex-grow, flex-shrink로 설정되는 구조다. 속성 세팅에 대한 상세한 설명은 정식 문서를 가져와본다.
값이 한 개일 때, 그 값은 다음 중 하나여야 합니다.
<number>를 지정하면 <flex-grow>입니다.
<length> 또는 <percentage>를 지정하면 <flex-basis>입니다.
none, auto, initial 중 하나를 지정할 수 있습니다.
값이 두 개일때, 첫 번째 값은 <number>여야 하며 <flex-grow>가 됩니다. 두 번째 값은 다음 중 하나여야 합니다.
<number>를 지정하면 <flex-shrink>입니다.
<length>, <percentage>, 또는 auto를 지정하면 <flex-basis>입니다.
![](https://velog.velcdn.com/images/0715yk/post/ba9f887f-efc5-4ccb-a9f0-713a3bc72710/image.png)
![](https://velog.velcdn.com/images/0715yk/post/27e57a16-b471-4475-b45a-f465740903f9/image.jpg)
![](https://velog.velcdn.com/images/0715yk/post/5955bf3a-095f-408f-a07b-6a1347772795/image.jpg)
![](https://velog.velcdn.com/images/0715yk/post/fa75d2b1-7947-4b00-b94e-1a9f1d51ac91/image.jpg)
값이 세 개일 때는 다음 순서를 따라야 합니다.
<flex-grow> 에 사용할 <number>
<flex-shrink> 에 사용할 <number>
<flex-basis> 에 사용할 <length>, <percentage>, 또는 auto