CSS 박스 정렬(Box alignment) 모듈은 다양한 CSS 박스 레이아웃 모델(Grid, Flexbox 등)에서 박스의 '정렬'과 관련된 CSS 기능들을 정의하는 명세입니다. 이 모듈의 핵심 목표는 흩어져 있던 정렬 방식들을 CSS 전반에 걸쳐 일관되게 만드는 거예요. CSS 박스 정렬 속성들을 활용하면 수평 및 수직 정렬을 완벽하게 제어할 수 있답니다.
이 가이드에서는 이 모듈에서 다루는 전반적인 개념들을 자세히 살펴볼 거예요. 플렉스박스(flexbox), 그리드 레이아웃(grid layout), 다단 레이아웃(multiple-column layout), 그리고 블록, 절대 위치 지정 및 테이블 레이아웃에서의 박스 정렬에 대한 더 자세한 정보는 링크된 추가 가이드에서 확인하실 수 있습니다. 텍스트 정렬 자체는 CSS 텍스트(CSS text) 및 CSS 인라인 레이아웃(CSS inline layout) 모듈에서 다루고 있으니 이 부분도 헷갈리지 마세요!
💡 강사님의 꿀팁: 예전 웹 개발에서는 요소를 수직 중앙 정렬하려고
margin: auto를 주거나transform,position: absolute등 온갖 꼼수를 동원해야만 했어요. 하지만 이 박스 정렬 모듈이 등장한 이후로는 Grid나 Flexbox에서 아주 우아하고 직관적으로 요소를 떡하니 정렬할 수 있게 되었습니다. 정말 고마운 기능이죠!
명세서에서는 특정 레이아웃 방식(예: Flexbox나 Grid)에 얽매이지 않고 정렬 속성들을 쉽게 이해하고 논의할 수 있도록 몇 가지 정렬 관련 용어들을 정의해 두었습니다. 또한 모든 레이아웃 방식에 공통으로 적용되는 핵심 개념들도 존재한답니다.
정렬은 '쓰기 모드(Writing modes)'와 아주 밀접하게 연결되어 있습니다. 우리가 어떤 요소를 정렬할 때, 화면의 물리적인 방향인 '위, 오른쪽, 아래, 왼쪽'을 기준으로 생각하지 않아요. 대신, 우리가 작업하고 있는 특정 축(차원)의 시작(start)과 끝(end)이라는 논리적 개념으로 정렬을 설명합니다. 이렇게 기준을 잡으면 문서가 어떤 쓰기 모드(가로쓰기, 세로쓰기, 우측에서 좌측으로 쓰기 등)를 사용하든 정렬이 동일한 방식으로 찰떡같이 작동하도록 보장할 수 있습니다.
박스 정렬 속성을 사용할 때는 두 개의 축 중 하나를 기준으로 콘텐츠를 정렬하게 됩니다. 바로 인라인(Inline, 또는 메인) 축과 블록(Block, 또는 교차) 축이에요.
인라인 축은 현재 사용 중인 쓰기 모드에서 문장 속 '단어들이 흘러가는 방향'의 축입니다. 예를 들어 영어(또는 한국어)의 경우 인라인 축은 가로(수평) 방향이 되겠죠. 반면 블록 축은 단락(paragraph) 요소와 같은 '블록'들이 순서대로 쌓이는 방향의 축을 말하며, 인라인 축을 가로질러(수직으로) 이어집니다.

인라인 축을 기준으로 항목을 정렬할 때는 justify-로 시작하는 속성들을 사용합니다:
블록 축을 기준으로 항목을 정렬할 때는 align-으로 시작하는 속성들을 사용합니다:
💡 강사님의 꿀팁: 실무에서 속성 이름이 헷갈린다면 "'justify'는 글자가 써지는 방향(가로), 'align'은 줄이 바뀌는 방향(세로)"이라고 외워두시면 훨씬 기억하기 쉽습니다!
다만, 플렉스박스(Flexbox)에서는 상황이 약간 더 복잡해집니다. 위에서 설명한 공식은 플렉스박스의 flex-direction이 row(가로)로 설정되어 있을 때만 딱 맞아떨어지거든요. 만약 flex-direction을 column(세로)으로 변경하면 이 두 속성의 역할이 서로 뒤바뀌게 됩니다.
따라서 플렉스박스를 다룰 때는 '인라인'과 '블록'이라는 용어보다는 메인 축(main axis)과 교차 축(cross axis)으로 생각하는 것이 일반적으로 훨씬 안전하고 이해하기 쉽습니다. 플렉스박스에서 justify- 속성들은 항상 '메인 축'을 기준으로 정렬하고, align- 속성들은 '교차 축'을 기준으로 정렬한다는 원칙을 꼭 기억해 주세요!
정렬 대상(alignment subject)은 말 그대로 정렬이 적용되는 '대상'을 뜻합니다.
justify-self나 align-self를 사용할 때, 또는 justify-items나 align-items로 그룹 전체에 값을 설정할 때, 이 정렬 대상은 해당 속성이 적용되는 요소의 마진 박스(margin box) 전체가 됩니다. 반면 justify-content와 align-content 속성은 사용하는 레이아웃 방식(Flex, Grid 등)에 따라 정렬 대상이 약간씩 다르게 적용됩니다.
정렬 컨테이너(alignment container)는 정렬 대상이 그 안에서 움직이고 정렬되는 '상자(box)'를 의미합니다. 보통은 정렬 대상의 컨테이닝 블록(부모 요소)이 이에 해당하죠. 하나의 정렬 컨테이너 안에는 하나 또는 여러 개의 정렬 대상이 들어있을 수 있습니다.
아래 이미지는 두 개의 정렬 대상(subject)이 나란히 들어있는 정렬 컨테이너의 모습을 잘 보여줍니다.

명세서에서는 크게 세 가지의 다른 정렬 방식을 설명하고 있으며, 각각 고유한 키워드 값들을 사용합니다.
위치 정렬(Positional alignment)은 정렬 컨테이너 내에서 정렬 대상이 어디에 위치할지를 정하는 아주 직관적인 방식입니다. 위치 정렬을 위한 키워드 값들이 미리 정의되어 있으며, 이 값들은 justify-content와 align-content를 통한 콘텐츠 덩어리 전체 정렬뿐만 아니라 justify-self와 align-self를 통한 개별 자기 자신(self) 정렬에도 사용할 수 있습니다.
center (중앙)start (시작)end (끝)self-startself-endflex-start (플렉스박스 전용)flex-end (플렉스박스 전용)left (물리적 왼쪽)right (물리적 오른쪽)화면의 물리적인 방향과 직접 연관된 left와 right 값을 제외한 나머지 모든 값들, 즉 <self-position>과 <content-position> 값들은 논리적인 값(logical values)들이며 콘텐츠의 쓰기 모드(writing mode)와 강력하게 연관되어 있습니다.
예를 들어, CSS 그리드 레이아웃을 사용할 때 언어가 영어(또는 한국어)로 되어 있고 justify-content를 start로 설정했다면, 항목들은 인라인 차원의 시작 부분, 즉 화면의 '왼쪽'으로 찰싹 붙어 이동하게 됩니다. 영어 문장은 페이지의 왼쪽에서 시작하기 때문이죠.
하지만 만약 우측에서 좌측으로 읽는(Right-to-Left) 아랍어를 사용 중이라면, 똑같이 start 값을 주더라도 항목들은 '오른쪽'으로 이동하게 됩니다. 아랍어 문장은 페이지의 오른쪽에서 시작하니까요!

위 이미지의 두 가지 경우 모두 동일하게 justify-content: start가 적용되었지만, 쓰기 모드가 다르기 때문에 논리적인 '시작(start)' 위치가 서로 다르게 나타나는 것을 명확히 볼 수 있습니다.
베이스라인 정렬(Baseline alignment)은 정렬 컨텍스트 내에 있는 여러 정렬 대상들의 베이스라인(글꼴의 기준선) 간의 관계를 서로 예쁘게 맞춰주는 방식입니다. 베이스라인 정렬 키워드인 <baseline-position> 값들은 여러 박스 그룹에 걸쳐 글자들의 밑단(베이스라인)을 나란히 일치시킬 때 사용하죠. 이 키워드들 역시 justify-content 및 align-content나, justify-self 및 align-self 속성에 값으로 쓰일 수 있습니다.
baselinefirst baselinelast baseline베이스라인 '콘텐츠' 정렬(Baseline content alignment) — 즉, justify-content나 align-content에 베이스라인 정렬 값을 지정하는 것 — 은 항목들을 행(row)으로 배치하는 레이아웃 방식에서 잘 작동합니다. 박스 내부에 패딩(padding)을 추가하는 방식으로 정렬 대상들의 베이스라인을 서로 감쪽같이 맞춰주게 됩니다.
베이스라인 '자기' 정렬(Baseline self-alignment)은 박스 외부에 마진(margin)을 추가하여 베이스라인을 기준으로 개별 박스들을 위아래로 이동시킵니다. 자기 정렬은 justify-self나 align-self를 사용해 단일 박스 단위로 수행하거나, justify-items와 align-items를 사용해 박스 그룹 단위로 일괄 수행할 수 있습니다.
💡 강사님의 꿀팁: 버튼 안에 있는 텍스트와 옆에 있는 아이콘의 크기가 달라서 위아래로 묘하게 어긋나 보인 적 있으신가요? 그럴 때 Flex 컨테이너에
align-items: baseline;을 주면 글자의 밑선이 딱! 맞아떨어지면서 시각적인 안정감이 엄청나게 올라갑니다.
분산 정렬(Distributed alignment)은 정렬 대상들 사이에 남아있는 '빈 공간(space)'을 어떻게 공평하게 분배할지 정의하는 정렬 방식입니다. 분산 정렬 키워드인 <content-distribution> 값들은 align-content 및 justify-content 속성과 짝을 지어 사용됩니다. 이 키워드들은 정렬 대상들이 모두 자리를 잡고 난 후 남는 여분의 공간(additional space)을 어떻게 처리할지를 현명하게 결정해주죠. 사용할 수 있는 값들은 다음과 같습니다:
stretch (빈 공간을 꽉 채우도록 항목들을 늘림)space-between (양끝 항목은 벽에 붙이고, 나머지 사이 공간을 동일하게 나눔)space-around (각 항목의 양쪽 주변 공간을 동일하게 할당)space-evenly (항목 사이사이와 양끝 벽과의 모든 여백을 완벽하게 동일하게 나눔)예를 들어볼게요. 플렉스 레이아웃에서 항목들은 기본적으로 flex-start로 몰려서 정렬되어 있습니다. 위에서 아래로 흐르는 수평 쓰기 모드(영어/한국어 등)에서 flex-direction을 row로 설정하면, 항목들은 맨 왼쪽에 다닥다닥 붙어서 시작하게 되고, 렌더링 후 남는 빈 공간은 전부 항목들 우측에 버려진 채 남게 됩니다.

이때 플렉스 컨테이너에 마법의 키워드 justify-content: space-between을 설정해 주면, 아까 우측에 방치되어 있던 여분의 공간이 이제 항목들 사이사이에 공평하게 분배되어 양끝 맞춤 정렬이 됩니다.

한 가지 명심해야 할 점은, 이러한 공간 분배 키워드들이 제 역할을 하려면 우리가 항목을 정렬하려는 차원(축)에 반드시 '나눌 수 있는 여분의 공간'이 존재해야만 합니다. 공간이 아예 꽉 차 있다면 분산시킬 공간도 없으니 아무 일도 일어나지 않겠죠.
백문이 불여일견이죠! 아래 예제들을 통해 그리드(Grid)와 플렉스박스(Flexbox)에서 박스 정렬 속성들이 실제로 어떻게 예쁘게 적용되는지 확인해 보세요.
이 그리드 레이아웃 예제에서는, 인라인(메인) 축을 기준으로 고정된 너비의 트랙들을 배치하고 났더니 그리드 컨테이너에 가로로 여분의 공간이 꽤 남았습니다. 이 공간은 justify-content를 space-between으로 설정해 사이좋게 분산시켰어요.
블록(교차) 축의 경우, 그리드 영역 내부 항목들의 정렬은 align-items를 start로 주어 위로 붙였습니다. 그런데 재미있게도 'One'이라고 적힌 첫 번째 항목만 align-self를 center로 설정했네요! 이렇게 하면 그룹 전체의 align-items 규칙을 가볍게 무시하고 자기 자신만 독자적으로 수직 중앙에 정렬하게 됩니다.
Play (Run example in MDN Playground)
<div class="box">
<div>One</div>
<div>Two</div>
<div>Three <br />has <br />extra <br />text</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
</div>
.box {
display: grid;
grid-template-columns: 120px 120px 120px;
align-items: start;
justify-content: space-between;
}
.box :first-child {
align-self: center;
}

이 예제에서는 세 개의 플렉스 항목(Flex items)이 justify-content를 사용해 메인 축(수평)으로 분산 정렬되고, align-items를 사용해 교차 축(수직) 위쪽으로 정렬됩니다. 앞선 그리드 예제와 마찬가지로, 첫 번째 항목은 align-self를 center로 설정하여 부모 그룹에서 지시한 align-items 설정을 쿨하게 무시하고 스스로 수직 중앙에 배치됩니다.
Play (Run example in MDN Playground)
<div class="box">
<div>One</div>
<div>Two</div>
<div>Three <br />has <br />extra <br />text</div>
</div>
.box {
display: flex;
align-items: flex-start;
justify-content: space-between;
}
.box :first-child {
align-self: center;
}

때로는 정렬 대상이 컨테이너보다 너무 커서 화면을 뚫고 나가는(오버플로우) 사태가 발생할 수 있습니다. 이럴 때 <overflow-position> 키워드인 safe와 unsafe가 구원투수로 등장하여 브라우저의 행동 방침을 정의해 줍니다.
safe 키워드를 사용하면, 여러분이 지정한 정렬(예: center) 때문에 오히려 콘텐츠가 잘려나가는 오버플로우 상황이 감지될 때, 브라우저가 항목을 강제로 안전한 start 위치로 재정렬시킵니다. 항목의 일부가 컨테이너 밖으로 밀려나서 사용자가 스크롤을 해도 볼 수 없는 치명적인 "데이터 손실(data loss)" 상황을 막기 위한 브라우저의 배려죠.
반면에 unsafe를 지정하면 "데이터가 좀 잘려도 좋으니 내가 시킨 대로 무조건 중앙에 놔둬!"라는 뜻이 되어, 데이터 손실이 발생하더라도 설정한 정렬 방식을 곧이곧대로 강행하게 됩니다.
박스 정렬 명세에는 gap, row-gap, column-gap 속성도 당당히 포함되어 있습니다. 이 속성들은 요소들이 행(row)이나 열(column)로 배치되는 레이아웃에서 항목들 사이에 일관되고 깔끔한 간격(gap)을 띄울 수 있게 해주는 마법 같은 도구입니다.
gap 속성은 row-gap과 column-gap을 한 번에 설정할 수 있는 단축 속성(shorthand)입니다:
row-gap (위아래 행 간격)column-gap (좌우 열 간격)gap (둘 다 한 번에 설정)아래 예제를 보면, 그리드 레이아웃에서 gap 단축 속성을 사용하여 행 트랙(위아래) 사이에는 10px의 간격을, 열 트랙(좌우) 사이에는 2em의 간격을 아주 손쉽게 설정하고 있는 걸 확인할 수 있습니다.
Play (Run example in MDN Playground)
<div class="box">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
</div>
.box {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 10px 2em;
}
.box :first-child {
align-self: center;
}

초창기 그리드(Grid)가 브라우저에 도입될 때는 gap 속성들 앞에 grid-라는 접두사가 붙어 있었습니다. 다행히 지금은 모든 모던 브라우저들이 접두사 없는 깔끔한 속성들을 지원하지만, 예전에 작성된 코드베이스를 보다 보면 grid-row-gap, grid-column-gap, grid-gap 같은 낡은 문법을 만나실 수도 있습니다. 당황하지 마세요! 이런 접두사가 붙은 버전들은 단순히 최신 속성과 동일하게 작동하는 별칭(alias)으로 처리된답니다.
💡 강사님의 꿀팁: 사실
gap속성은 초기에 Grid 전용으로 나왔지만, 이제는 Flexbox에서도 완벽하게 동작합니다! 옛날처럼 요소들 사이를 띄우려고 일일이 자식들에게margin을 주고 마지막 요소의 마진을 빼느라 고생했던 시절은 완전히 끝났어요. 무조건gap을 사용하세요!
다만 주의할 점은, 시각적인 '여백'은 gap으로 설정한 수치 외에도 더 커질 수 있다는 것입니다. 앞서 배운 space-between 같은 공간 분배 키워드를 적용하거나, 개별 항목에 자체적으로 margin을 추가했다면 실제 화면상 벌어진 간격은 gap 설정값보다 더 넓어 보이게 됩니다.
CSS 박스 정렬 속성들은 어떤 레이아웃 모델(명세)과 결합하느냐에 따라 내부 구현 방식이 살짝씩 다르게 작동합니다. 각 레이아웃 방식에 맞춰 정렬 속성들을 완벽하게 다루는 법을 마스터하고 싶다면, 아래에 준비된 심화 가이드들을 차례대로 정독해 보시길 강력히 권해드립니다!
이 문서가 학습에 도움이 되셨나요? (Was this page helpful to you?)
[Yes][No]
문서 기여 방법 알아보기: Learn how to contribute
최종 수정일: 2025년 12월 15일 (MDN contributors 작성)
이 문서를 GitHub에서 보기 | 문서의 문제점 신고하기