CSS flex justify-content와 align-items 차이
Flexbox로 요소를 가운데 정렬할 때 justify-content와 align-items를 함께 사용한다.
두 속성 모두 정렬을 담당하지만 기준이 되는 축이 다르다.
justify-content는 주축에서 flex item을 정렬한다.align-items는 주축과 직각인 교차축에서 flex item을 정렬한다.
처음에는 justify-content는 가로, align-items는 세로라고 외우기 쉽다.
하지만 flex-direction이 column으로 바뀌면 두 방향도 함께 바뀐다.
그래서 가로와 세로보다 주축과 교차축으로 이해하는 편이 정확하다.
flex container와 flex item
Flexbox 정렬을 사용하려면 먼저 부모 요소를 flex container로 만들어야 한다.
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
</div>.container {
display: flex;
}display: flex가 적용된 .container가 flex container다.
그 바로 아래 자식인 .item 세 개가 flex item이 된다.
justify-content와 align-items는 기본적으로 부모인 flex container에 작성한다.
자식에 속성을 적으면 원하는 정렬이 일어나지 않는 경우가 많다.
display가 요소의 바깥 배치에 미치는 영향은 CSS display block inline inline-block 차이에서 별도로 정리했다.
주축과 교차축
Flexbox에는 정렬의 기준이 되는 두 축이 있다.
- 주축인 main axis는 flex item이 나열되는 방향이다.
- 교차축인 cross axis는 주축과 직각을 이루는 방향이다.
주축은 flex-direction이 결정한다.
기본값인 row에서는 item이 왼쪽에서 오른쪽으로 놓이므로 가로가 주축이다.
세로는 교차축이 된다.
.container {
display: flex;
flex-direction: row;
}이 상태에서는 justify-content가 가로 정렬을 담당한다.align-items는 세로 정렬을 담당한다.
.container {
display: flex;
justify-content: center;
align-items: center;
}flex-direction: column으로 바꾸면 item이 위에서 아래로 놓인다.
세로가 주축이 되고 가로가 교차축이 된다.
.container {
display: flex;
flex-direction: column;
}이제 justify-content는 세로 정렬이고 align-items는 가로 정렬이다.
justify-content의 역할
justify-content는 flex container의 주축에 남은 공간을 어떻게 배분할지 정한다.
item을 시작점, 가운데, 끝점에 모으거나 item 사이에 공간을 나눌 수 있다.
.container {
display: flex;
justify-content: center;
}기본 flex-direction: row에서는 item들이 가로 방향 가운데에 모인다.
자주 사용하는 값은 다음과 같다.
.container {
justify-content: flex-start;
}flex-start는 item을 주축의 시작점에 모은다.
Flexbox에서 기본적으로 보이는 배치다.
.container {
justify-content: flex-end;
}flex-end는 item을 주축의 끝점에 모은다.
.container {
justify-content: center;
}center는 item 묶음을 주축 가운데에 놓는다.
.container {
justify-content: space-between;
}space-between은 첫 item을 시작점에, 마지막 item을 끝점에 놓는다.
남은 공간은 item 사이에만 같은 크기로 나눈다.
.container {
justify-content: space-around;
}space-around는 각 item의 양쪽에 같은 크기의 공간을 배정한다.
그 결과 container 가장자리의 공간은 item 사이 공간의 절반처럼 보인다.
.container {
justify-content: space-evenly;
}space-evenly는 container 가장자리와 모든 item 사이의 공간을 같은 크기로 만든다.
align-items의 역할
align-items는 flex item을 교차축에서 정렬한다.
한 flex line 안에서 모든 item의 기본 정렬을 한 번에 지정할 때 사용한다.
.container {
display: flex;
min-height: 200px;
align-items: center;
}기본 flex-direction: row에서는 교차축이 세로다.
따라서 item들이 container의 세로 가운데에 놓인다.
자주 사용하는 값은 다음과 같다.
.container {
align-items: stretch;
}stretch는 cross size가 auto인 item을 교차축 방향으로 늘린다.
Flexbox에서 align-items의 기본 동작으로 자주 보이는 값이다.
.container {
align-items: flex-start;
}flex-start는 item을 교차축의 시작점에 놓는다.
.container {
align-items: flex-end;
}flex-end는 item을 교차축의 끝점에 놓는다.
.container {
align-items: center;
}center는 item을 교차축 가운데에 놓는다.
.container {
align-items: baseline;
}baseline은 item 안의 텍스트 기준선을 맞춘다.
글자 크기가 서로 다른 메뉴나 가격 표시를 정렬할 때 유용하다.
두 속성의 핵심 차이
두 속성은 가로와 세로가 아니라 축을 기준으로 구분한다.
justify-content는 주축의 남은 공간을 배분한다.align-items는 교차축에서 각 item의 기본 정렬을 정한다.- 주축은
flex-direction을 따라간다. - 교차축은 주축과 직각이다.
- 두 속성은 flex item이 아니라 flex container에 작성한다.
row에서는 justify-content가 가로, align-items가 세로다.column에서는 justify-content가 세로, align-items가 가로다.
이 두 문장만 기억해도 대부분의 정렬 문제를 풀 수 있다.
가로와 세로 가운데 정렬
부모 안에서 자식을 가로와 세로 모두 가운데에 놓으려면 두 속성에 center를 지정한다.
<div class="box">
<span>가운데</span>
</div>.box {
display: flex;
justify-content: center;
align-items: center;
width: 320px;
height: 180px;
border: 1px solid #d8dee4;
}justify-content: center는 주축 가운데를 담당한다.align-items: center는 교차축 가운데를 담당한다.
row에서는 결과적으로 가로와 세로 가운데 정렬이 된다.column에서도 두 축 모두 center이므로 화면에 보이는 결과는 같은 가운데 정렬이다.
container에 item보다 큰 높이가 없다면 세로 방향의 남은 공간도 없다.
이 경우 align-items: center를 추가해도 움직임이 잘 보이지 않을 수 있다.
flex-direction row의 정렬 기준
flex-direction: row는 기본값이다.
item이 문서의 inline 방향을 따라 한 줄로 배치된다.
.toolbar {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}이 toolbar에서 justify-content: space-between은 가로 남은 공간을 양쪽에 배치한다.align-items: center는 높이가 다른 item을 세로 가운데에 맞춘다.
헤더의 로고와 메뉴를 양쪽 끝에 놓거나, 카드 제목과 버튼을 한 줄에 배치할 때 자주 쓰는 조합이다.
<header class="toolbar">
<strong>프로젝트</strong>
<button type="button">설정</button>
</header>.toolbar {
display: flex;
justify-content: space-between;
align-items: center;
min-height: 56px;
padding-inline: 16px;
}안쪽 여백과 바깥 간격의 기준이 헷갈린다면 CSS margin과 padding 차이를 함께 확인하면 좋다.
flex-direction column의 정렬 기준
flex-direction: column에서는 item이 위에서 아래로 놓인다.
주축이 세로로 바뀌기 때문에 두 정렬 속성의 화면상 방향도 바뀐다.
.empty-state {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 320px;
}justify-content: center는 콘텐츠 묶음을 세로 가운데에 놓는다.align-items: center는 각 item을 가로 가운데에 놓는다.
<div class="empty-state">
<strong>표시할 항목이 없습니다.</strong>
<button type="button">새 항목 만들기</button>
</div>텍스트와 버튼을 세로로 쌓으면서 전체를 화면 가운데에 놓는 빈 상태 UI에 잘 맞는다.
column-reverse나 row-reverse를 사용하면 시작점과 끝점도 반대로 바뀐다.
단순히 화면 위치만 보고 flex-start와 flex-end를 외우면 reverse 값에서 헷갈릴 수 있다.
justify-content가 적용되지 않는 원인
justify-content는 주축에 남은 공간이 있어야 눈에 보이는 효과를 만든다.
item이 container를 이미 가득 채우면 배분할 공간이 없다.
.item {
flex: 1;
}모든 item에 flex: 1을 주면 item이 남은 공간을 나눠 가진다.
이 상태에서는 justify-content: space-between을 추가해도 item 사이에 새로 배분할 여유 공간이 거의 없을 수 있다.
다음 항목을 순서대로 확인하면 원인을 찾기 쉽다.
- 속성을 작성한 요소에
display: flex가 있는지 확인한다. - 정렬할 item이 그 요소의 바로 아래 자식인지 확인한다.
flex-direction이row인지column인지 확인한다.- 주축에 실제로 남은 공간이 있는지 확인한다.
- item의
flex-grow또는margin: auto가 공간을 먼저 사용하고 있는지 확인한다.
Flexbox에서는 auto margin이 정렬보다 먼저 남은 공간을 흡수할 수 있다.
.login-button {
margin-left: auto;
}위 코드는 row 방향에서 .login-button을 오른쪽으로 밀 수 있다.
같은 줄에서 justify-content 결과가 예상과 다르다면 item의 auto margin도 살펴봐야 한다.
align-items가 적용되지 않는 원인
align-items도 교차축에 정렬할 공간이 있어야 변화가 보인다.
.container {
display: flex;
align-items: center;
}container 높이가 item 높이와 같다면 세로로 이동할 공간이 없다.
예제를 확인할 때는 height나 min-height로 교차축 공간을 만들어 보면 차이가 선명하다.
.container {
display: flex;
min-height: 200px;
align-items: center;
}item에 교차축 크기가 명시되어 있으면 stretch 효과가 나타나지 않을 수 있다.
.item {
height: 80px;
}또한 text-align: center는 flex item 자체를 가운데로 옮기는 속성이 아니다.
item 안의 inline 콘텐츠를 정렬하는 속성이므로 Flexbox의 축 정렬과 역할이 다르다.
align-self로 하나만 다르게 정렬
align-items는 container의 모든 flex item에 공통 기본값을 준다.
특정 item 하나만 교차축에서 다르게 정렬하려면 align-self를 사용한다.
<div class="container">
<div class="item">A</div>
<div class="item featured">B</div>
<div class="item">C</div>
</div>.container {
display: flex;
align-items: flex-start;
min-height: 180px;
}
.featured {
align-self: flex-end;
}전체 item은 교차축 시작점에 놓이지만 .featured만 끝점에 놓인다.
align-self는 교차축에서 개별 item을 조정한다.
주축에서 item 하나를 따로 밀고 싶다면 상황에 따라 auto margin을 사용하는 방식이 더 직접적이다.
align-content와의 차이
align-items와 align-content도 이름이 비슷해 자주 혼동된다.
align-items는 한 flex line 안에서 item을 교차축으로 정렬한다.align-content는 여러 flex line 자체를 교차축에서 정렬한다.
align-content가 동작하려면 item이 여러 줄로 나뉘어야 한다.
따라서 보통 flex-wrap: wrap과 교차축의 남은 공간이 필요하다.
.container {
display: flex;
flex-wrap: wrap;
align-content: center;
width: 320px;
height: 240px;
}
.item {
width: 120px;
}item이 두 줄 이상이 되면 align-content: center가 줄 묶음을 교차축 가운데에 놓는다.
한 줄뿐인 flex container에서는 align-content를 바꿔도 효과가 없다.
정리하면 item 정렬은 align-items, 여러 줄 정렬은 align-content다.
gap으로 item 사이 간격 만들기
정렬 속성은 container의 남은 공간을 배분한다.
item 사이에 항상 일정한 간격을 만들고 싶다면 gap이 더 명확하다.
.actions {
display: flex;
justify-content: flex-end;
align-items: center;
gap: 12px;
}justify-content: flex-end는 버튼 묶음을 주축 끝으로 보낸다.gap: 12px은 버튼 사이의 간격을 일정하게 유지한다.
space-between은 남은 container 너비에 따라 간격이 달라진다.
고정된 디자인 간격이 필요하다면 gap, 남은 공간 전체를 분배하려면 space-* 값을 사용하는 편이 자연스럽다.
실전 선택 기준
item이 나열되는 방향에서 정렬하려면 justify-content를 사용한다.
.navigation {
display: flex;
justify-content: center;
}item이 나열되는 방향과 직각인 축에서 정렬하려면 align-items를 사용한다.
.navigation {
display: flex;
align-items: center;
min-height: 64px;
}가로와 세로 모두 가운데라면 두 속성에 center를 준다.
.container {
display: flex;
justify-content: center;
align-items: center;
}특정 item 하나만 교차축에서 다르게 놓으려면 align-self를 사용한다.
여러 줄 전체를 교차축에서 정렬하려면 align-content를 사용한다.
item 사이에 고정 간격이 필요하면 gap을 사용한다.
요소를 일반 흐름에서 꺼내 정확한 좌표에 겹쳐야 하는 상황이라면 Flexbox 정렬보다 position이 목적에 맞을 수 있다.
CSS position relative와 absolute 차이에서 그 기준을 확인할 수 있다.
정리
justify-content는 flex container의 주축에서 item을 정렬하고 남은 공간을 배분한다.align-items는 교차축에서 모든 item의 기본 정렬을 정한다.
기본 row에서는 주축이 가로이고 교차축이 세로다.column에서는 주축이 세로이고 교차축이 가로다.
두 속성이 적용되지 않는다면 display: flex, flex-direction, 남은 공간, container 크기, item의 flex-grow와 auto margin을 순서대로 확인하면 된다.
가장 중요한 기준은 속성 이름을 가로와 세로로 외우지 않는 것이다.
item이 흐르는 주축은 justify-content, 그와 직각인 교차축은 align-items가 담당한다.
참고 자료



