나는 Flex를 매우 유용하게 사용하고 컴포넌트 배치를 할 때에도 Flex를 거의 100% 사용한다고 할 정도로 정말 잘 쓴다. 그러나 정작 Flex를 말 그대로 유동적으로 사용하고 있는가?라고 생각해 보았을때 그렇지 않다는 것을 깨달았다.
이번 기회에 Flex를 잘 이용하기 위하여 정리를 해야겠다는 생각이 들었고, 휴학하자마자 가장 먼저 하고 싶었던 일이었다.
시간이 없다는 핑계로 미뤄두었던 정리를 이제 해보고자 한다.
Flex에 대한 속성을 정리하는 데 있어 가장 큰 도움을 얻은 것은 일분코딩님의 강좌와 블로그 글이다.👇👇
https://studiomeal.com/archives/197
해당 글은 멋사 교육 시절에도 많이 참고했던 것인데 천천히 정독하다보니 정말 얻을 것이 많아서 글로 남기고자 한다.
Flex속성은 부모 요소인 container안에 자식 요소들인 items를 잘 조절하는 데 있어서 잘 사용한다고 확인할 수 있다.
이러한 item 요소를 잘 사용하는 것은 바로 flex 속성을 이용하는 것이다.
flex 속성은 세 가지 속성의 축약형으로, 아래와 같은 세 가지 속성이 들어가 있다.
auto로 설정되어 있으나, width와 height를 설정하여 해당 아이템이 가질 기본적인 크기를 지정할 수 있다. flex-basis의 값보다 커질 수 있는지 결정하는 속성이다. 0보다 큰 값이 들어가면 유연한 박스로 설정되어, 내가 설정한 값보다 남는 공백이 존재한다면 그 공백을 자연스럽게 채우게 된다.flex-basis에서 지정한 값보다 작아질 수 있는지 없는지 결정하는 것으로, 1보다 큰 값이 들어가면 flex-basis보다 작아질 수 있다고 설정하는 것이다. default 값은 0이다. 그럼 이 많은 내용들을 어떻게 flex라는 속성 안에 녹여낼까?
flex : 1 1 auto;
/ flex-grow : 1; flex-shrink: 1; flex-basis: auto; /
차례대로 flex-grow 속성, flex-shrink속성, flex-basis 속성을 가지고 있다. 다만 주의해야 할 점이 있는데,
flex: 1;
이렇게 지정하게 되면 flex-basis값이 0으로 설정되어서 wrap을 설정해도 줄바꿈이 일어나지 않는 경우가 생길 수 있으므로(실제 아이템이 차지하는 영역은 0이라고 인식하는 것이다..) 주의해야 한다.
아래 코드는 flex 속성을 이용하여 코드를 작성한 예시이다.

wrap을 적용했을때, DDDD그룹에 적용된 flex-grow 속성을 적용하고, 적용하지 않고의 차이이다. 이렇게 꽉 찬 화면을 구성하고 싶다면 전체적인 item에 flex-grow 속성을 적용하여 빈틈 없이 만들어보자.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>CSS Flex</title>
<link rel="stylesheet" href="default.css">
<style>
.flex-container {
display:flex;
flex-wrap: wrap;
}
.flex-item{
flex : 1 1 auto;
}
.flex-item:nth-child(1) {
flex : 0 1 20%;
}
.flex-item:nth-child(2) {
flex : 0 1 60%;
}
.flex-item:nth-child(3) {
flex : 0 1 20%;
}
</style>
</head>
다단컬럼을 만들어 상황에 따라서 칸이 자유롭게 나뉘고 싶은 상황을 만들고 싶을 때, width에 퍼센트를 지정하여 코드를 작성할 수 있다. flex-grow나 flex-basis만을 사용하게 된다면 flex 안의 아이템이 지나치게 많아질 때 그 내용물이 넘쳐버리는 경우가 다반사라 width 아이템의 기본적인 크기를 설정하는게 안전하다. 그러나 width만 쓰게 되면 유연한 코드의 가능성을 없앨 수 있기 때문에 득실을 잘 따져야 한다.
Flex 속성을 이용하여 화면 크기에 따라 달라지는 컬럼을 만들어 보자.
먼저 세로로 나열할 것이기 때문에, 컨테이너의 flex-direction 방향을 column으로 두어야 한다.
만들고자 하는 조건은 아래와 같다.
- 화면 크기가 600px 이상일 때, 2분할 컬럼으로 화면을 구성한다.
- 화면 크기가 800px 이상일 때, 3분할 컬럼으로 화면을 구성한다.
화면 크기가 600px 이상일 때부터는 flex-direction 방향을 row로 두고, wrap 속성을 두어 2분할이 가능하게끔 하되,
각각의 아이템의 가로 크기는 50%로 지정하여 화면에 꽉 찰 수 있도록 만든다.
이 때, flex-basis를 50%로 두어서 조작하면 안되나? 라는 생각이 들 수 있지만, 되도록이면 flex-basis는 auto로 두고, width를 조작하는 것이 예상하는 것과 같은 결과가 나와 예기치 못한 오류를 줄일 수 있다.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>CSS Flex</title>
<link rel="stylesheet" href="default.css">
<style>
.flex-container {
display: flex;
border: 10px solid red;
min-height: 100vh;
flex-direction: column;
}
.flex-item {
flex: 1 auto;
/* 아래 남는애는 자동으로 차게 만들어. */
}
@media (min-width:600px){
.flex-container{
display:flex;
flex-direction:row;
flex-wrap: wrap;
}
.flex-item{
width:50%;
}
}
@media (min-width:800px){
.flex-item {
width: 33%;
flex: 1 auto;
}
}
</style>
</head>
3분할 시, 100%인 화면의 크기를 어떻게 3으로 나누지? 라는 고민은 안해도 된다. flex-grow를 1로 지정해 두면 알아서 남은 부분을 채우니까! 내가 지정한 flex-basis보다 늘어날 수 있다.
전체 페이지에 flex: 1 auto 속성을 적용하면 전체 페이지가 항상 지정된 height를 가득 채우므로 그 아래 있는 요소들을 항상 바닥에 붙어 있을 수 있게끔 만들 수 있다. 이 때 주의해야 하는 것은 부모가 되는 container에 height를 꼭 지정해 주어야 한다는 것이다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>CSS Flex</title>
<link rel="stylesheet" href="default.css">
<style>
.page{
display:flex;
flex-direction: column;
min-height:100vh;
}
.content {
flex : 1 auto;
padding: 1.5rem;
}
</style>
</head>
<body>
<div class = "page">
<header class = "header flex-item">header</header>
<section class = "content">
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fuga esse sunt obcaecati voluptatem eaque ex laudantium ratione labore id nulla explicabo
magni perferendis expedita nobis enim non neque, praesentium minus.Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fuga esse sunt obcaecati voluptatem eaque ex laudantium ratione labore id nulla explicabo
magni perferendis expedita nobis enim non neque, praesentium minus.Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fuga esse sunt obcaecati voluptatem eaque ex laudantium ratione labore id nulla explicabo
magni perferendis expedita nobis enim non neque, praesentium minus.Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fuga esse sunt obcaecati voluptatem eaque ex laudantium ratione labore id nulla explicabo
magni perferendis expedita nobis enim non neque, praesentium minus.Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fuga esse sunt obcaecati voluptatem eaque ex laudantium ratione labore id nulla explicabo
magni perferendis expedita nobis enim non neque, praesentium minus.Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fuga esse sunt obcaecati voluptatem eaque ex laudantium ratione labore id nulla explicabo
magni perferendis expedita nobis enim non neque, praesentium minus.Lorem ipsum dolor sit, amet consectetur adipisicing elit. Fuga esse sunt obcaecati voluptatem eaque ex laudantium ratione labore id nulla explicabo
</section>
<footer class = "footer flex-item">footer</footer>
</div>
</body>
</html>

flex-shrink 를 사용하면 줄어들 수 있다는 속성을 가진 것을 앗아가겠다는 의미로, 내가 지정한 크기가 있다면 그 크기보다 줄어들지 않는다는 속성이 있다.
기본값이 1로 지정되어 있으니, 0으로 설정하게 되면 아무리 화면이 줄어들어도 내가 지정한 속성보다 줄어들지 않는다.
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>CSS Flex</title>
<link rel="stylesheet" href="default.css">
<style>
.flex-container {
display:flex;
}
.flex-item:nth-child(2){
flex-grow:1;
}
.flex-item:nth-child(1){
flex-shrink: 0;
width: 150px;
}
.flex-item:nth-child(3){
flex-shrink: 0;
width: 200px;
}
</style>
</head>

Flex item에 속하는 요소 하나만 정렬하고 싶다면 아래 세가지 요소를 이용할 수 있다. justify-content를 이용할 수 있다고 생각하겠지만, 이것은 하나의 요소만 움직이는 것이 아니라 모든 요소가 움직이기 때문에 사용에 유의해야 한다.
margin auto는 가운데 정렬을 할 때도 매우 자주 쓰이는 것인데, 이것은 남아 있는 여유 공간의 margin을 모두 활용한다는 뜻이다.
그렇기 때문에 3개의 요소 중 하나의 요소만 오른쪽으로 붙이고 싶을 때 다음과 같이 작성할 수 있다.

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>CSS Flex</title>
<link rel="stylesheet" href="default.css">
<style>
.flex-container{
display: flex;
height: 100vh;
align-items:center;
}
.flex-item:nth-child(2){
align-self: stretch;
}
</style>
</head>

요소 하나만으로 정렬할 수 있다.