레이아웃은 디자인을 위해 중요한 요소 중 하나이지만, 아직까지 레이아웃을 코드로 잘 표현하는 최적의 방법을 찾아내지는 못했다.
레이아웃의 흑역사와 flex 의 등장 배경을 알아보자!
가장 먼저 Table 로 표현하려는 시도가 있었다.
표는 격자모양으로 생겼다는 점에 착안해서, 많은 개발자와 디자이너들이 table 태그를 이용해 레이아웃을 잡았다.
그런데 여기에는 심각한 문제가 있었다. 표는 구조화된 정보를 정리정돈하기 위한 ‘정보'로서의 의미가 있는데, 이것을 의미가 없는 레이아웃에 사용하다보니 스크린리더나 검색엔진 등 정보를 읽는 것이 중요한 기술들 입장에서 테이블 태그를 만났을 때 그것이 정보전달을 위한 표로 사용된 것인지, 레이아웃으로 사용된 것인지 구분하기가 어려웠다. 또한 테이블 태그를 짜는 것은 쉬워도 나중에 변경하기가 어렵다는 단점이 있었다.
각 요소들의 위치를 조정해 원하는 곳에 배치하는 방식. 지금도 많이 사용되는 방식이다.
플로팅은 이미지 옆에 글자를 흘려보내는 효과를 위해 사용되었는데, 이것을 활용해 레이아웃을 잡는데 활용되었다. 그러나 레이아웃을 위해 고안된 것이 아니었고, 이해가 어렵다는 단점이 있었다.
이런 저런 시도를 거쳐, 레이아웃을 표현하기 위해 고안된 것이 flex 이다.
플렉스를 사용하기 위해서는 두 단계의 태그를 개념적으로 이해해야 한다.
정렬하고자 하는 각각의 아이템은 그 부모에 해당되는 컨테이너에 속한다.
컨테이너와 아이템은 각각 다음과 같은 속성을 가질 수 있다.
flex 를 사용하기 위해 가장 먼저 해야 할 것은 container 에 해당하는 태그에 display: flex 를 부여하는 것이다.
그리고 flex-direction 을 설정해주면 아이템들을 행으로 정렬할 것인지, 열로 정렬할 것인지, 역순으로 정렬할 것인지 선택할 수 있다.
.container{
background-color: powderblue;
height:200px;
display:flex;
flex-direction:row;
}
.item{
background-color: tomato;
color:white;
border:1px solid white;
}
아이템은 컨테이너의 크기에 따라 커질 수도, 작아질 수도 있다.
기본적으로는 아이템들 밖의 여백이 존재할때 까지는 아이템의 크기를 유지하다가, 여백이 더 이상 존재하지 않게 되는 순간 아이템이 가져간 여백의 크기를 줄여간다.
작아지고, 커지는 비율을 지정하는 방법이 grow&shrink 이다.
💡 아이템의 기본 크기를 설정하려면 flex-basis: 200px 를 넣어 주면 된다.아이템들이 컨테이너의 여백을
일정하게 채우도록 하려면 컨테이너 안의 모든 아이템들에 flex-grow: 1
을 부여하면 된다. 컨테이너가 커지고 줄어들 때 모든 아이템이 같은 비율로 늘어나고 줄어든다.
특정한 한 아이템이 다른 아이템들에 비해 2배만큼 여백을 가지도록 하고 싶다면 특정 아이템에만 flex-grow:2
를 주면 된다. 이 아이템은 컨테이너가 커지고 줄어들 때 다른 아이템보다 여백을 2배 많이 가지게 된다.
컨테이너의 여백을 그대로 남겨 둔다.
.container {
background-color: powderblue;
display: flex;
flex-direction: row;
height: 200px;
}
.item {
color: white;
background-color: red;
border: 1px solid white;
}
모든 아이템이 여백을 공평하게 나눠가진다. 컨테이너가 커지면 같은 비율을 유지하면서 늘어난 여백을 공평하게 나눈다.
.container {
background-color: powderblue;
display: flex;
flex-direction: row;
height: 200px;
}
.item {
color: white;
background-color: red;
border: 1px solid white;
flex-grow: 1;
}
모든 아이템의 flex-grow가 1인 상황에서 아이템 A의 flex-grow 가 2 라면 A가 다른 아이템보다 여백을 2배 더 많이 가진다.
그러나 다른 아이템의 flex-grow 가 0이거나 없을 때 A만 flex-grow 를 0보다 큰 수로 가진다면 A가 모든 여백을 다 가진다.
.container {
background-color: powderblue;
display: flex;
flex-direction: row;
height: 200px;
}
.item {
color: white;
background-color: red;
border: 1px solid white;
flex-grow: 1;
}
.item:nth-child(2) {
flex-grow: 2;
}
.container {
background-color: powderblue;
display: flex;
flex-direction: row;
height: 200px;
}
.item {
color: white;
background-color: red;
border: 1px solid white;
flex-grow: 0;
}
.item:nth-child(2) {
flex-grow: 2;
}
여백을 나눠가진 아이템들에게, 컨테이너가 작아졌을 때 같이 줄어들 것인지 여부를 설정할 수 있다.
그 긴축의 정도를 설정하기 위해서는 flex-shrink 의 값을 조정해 주면 된다.
flex-shrink:0 인 아이템은 컨테이너가 줄어들어도 같이 줄어들지 않는다. (자기가 가진 여백을 그대로 유지한다)
그러나 flex-shrink값이 0보다 커지면 여백을 줄이기 시작한다.
아이템 A와 B가 둘 다 flex-shrink 값으로 1을 가진다면, 컨테이너가 줄어들 때 두 아이템의 크기도 같이 줄어든다.
A와 B의 flex-shrink 값이 다르다면 둘 중 큰 값을 가진 아이템의 크기가 더 많이 줄어든다.
그러나 A의 flex-shrink 는 0, B의 flex-shrink 는 1이라면, 컨테이너가 줄어들어도 A의 크기는 유지되고, B의 크기만 줄어든다.
💡 정리 flex-shrink는 컨테이너의 크기가 아이템이 차지하는 크기보다 작아질 때 아이템이 차지하는 공간을 줄이는 정도를 의미한다. 어느날 갑자기 소득이 줄어든 가족을 생각해 보자. flex-shrink:0 은 가족의 소득이 줄어도 소비를 전혀 줄이지 않는 구성원과 같다. 아이템이 차지하는 공간이 그대로 유지됨을 의미한다. flex-shrink 값이 1보다 크다는 것은 줄어든 소득만큼 자신의 소비를 줄이는 것을 의미한다. 다른 가족들이 전부 0일때 나혼자 1이라면, 나홀로 소비를 줄이는 것이고, 구성원 A가 1만큼 줄일때 구성원 B가 2만큼 줄일 수도 있다.소비보다 소득이 많을 때(컨테이너가 충분히 커서, 아이템이 컨테이너를 다 차지하고도 여백이 충분할때)는 문제가 되지 않지만, 소득이 줄어들면 문제가 발생한다.
2라는 아이템은 소득(컨테이너의 크기)이 줄어든다고 해도 자신의 소비(2가 차지하고 있던 여백)를 줄일 의사가 전혀 없기 때문에, 컨테이너가 줄어들어도 크기를 그대로 유지한다.
.item {
color: white;
background-color: red;
border: 1px solid white;
}
.item:nth-child(2) {
flex-basis: 700px;
flex-shrink: 0;
}
이제 2번 아이템은 소득이 줄어든 만큼 자신의 소비를 줄이기로 했다. 컨테이너의 크기가 줄어들면 2번이 차지하고 있던 여백도 차차 줄어든다.
.item {
color: white;
background-color: red;
border: 1px solid white;
}
.item:nth-child(2) {
flex-basis: 700px;
flex-shrink: 1;
}
1번 아이템도 소득이 줄어들 때 같이 소비를 줄이기로 했다. 그런데 2번이 좀 더 많이 부담하기로 했으므로, 컨테이너가 줄어들면 2번이 더 빠르게 줄어든다.
.item {
color: white;
background-color: red;
border: 1px solid white;
}
.item:nth-child(1) {
flex-basis: 700px;
flex-shrink: 1;
}
.item:nth-child(2) {
flex-basis: 700px;
flex-shrink: 2;
}