AD JB Toolbox 01

CSS 강좌 / Flexbox 정렬·간격·줄바꿈·크기 조절하기

Flexbox의 정렬은 주축에 justify-content, 교차축에 align-items를 사용합니다. 줄바꿈은 flex-wrap, 항목 간격은 gap, 크기 분배는 아이템의 flex로 조절하며, 여러 줄의 묶음을 정렬하는 align-content는 별도의 조건이 필요합니다.

정렬 속성을 축과 적용 대상으로 구분하기

속성 적용 대상 확인할 조건
justify-content 컨테이너의 주축 방향 아이템 분배 아이템 크기를 정한 뒤 남는 공간
align-items 각 아이템의 교차축 정렬 아이템의 교차축 크기와 줄 높이
align-self 특정 아이템의 교차축 정렬 컨테이너 기본 정렬을 개별적으로 변경
align-content 여러 줄의 묶음 wrap 가능한 컨테이너와 교차축의 남는 공간
gap 인접 아이템·줄 사이 간격 정렬로 더해진 공간과 구분

row에서 justify-content는 주로 가로, align-items는 세로를 조절합니다. column으로 바꾸면 주축이 세로가 되어 두 속성의 물리적인 방향도 바뀝니다. 특히 column의 justify-content를 비교하려면 컨테이너 높이에 남는 공간이 있어야 합니다. 높이가 내용에 딱 맞으면 center나 space-between을 바꿔도 이동할 공간이 거의 없습니다.

justify-content: center는 아이템 묶음을 가운데에 놓고 space-between은 첫 항목과 마지막 항목을 양 끝에 놓은 뒤 사이 공간을 나눕니다. gap은 지정한 간격이며 space-between은 남는 공간을 분배합니다. 함께 사용하면 실제 사이 간격은 gap보다 커질 수 있습니다. 아이템의 flex-grow가 남는 공간을 모두 사용하거나 주축 방향의 auto margin이 공간을 가져가면 justify-content의 변화가 눈에 보이지 않을 수 있습니다.

align-items: center는 한 줄 안에서 높이가 다른 항목을 가운데에 맞춥니다. align-content: center는 여러 줄 전체를 교차축 가운데에 모읍니다. 둘을 같은 기능으로 생각하면 안 됩니다. align-content는 nowrap인 한 줄 컨테이너에는 효과가 없고, wrap 컨테이너라도 줄들이 차지한 크기와 컨테이너 높이가 같으면 비교할 여유가 없습니다. MDN의 Flexbox 정렬 안내에서 적용 조건을 확인할 수 있습니다.

전체 예제로 아이템과 줄 묶음 정렬 비교하기

아래 코드를 flex-align.html로 저장해 엽니다. 첫 구역은 높이가 다른 세 항목, 둘째 구역은 두 줄이 생기는 네 항목입니다. 둘째 구역은 높이를 280px로 지정해 줄 묶음을 옮길 여유를 만들었습니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>flex-align.html</title>
  <style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
.toolbar { display: flex; gap: 12px; justify-content: space-between; align-items: center;
 width: 100%; max-width: 640px; min-height: 120px; border: 2px solid #789; padding: 12px; }
 .toolbar > div { padding: 8px; background: #dceefa; }
 .lines { display: flex; flex-wrap: wrap; gap: 12px; width: min(100%, 360px); height: 280px;
 align-items: center; align-content: flex-start; border: 2px solid #789; padding: 12px; }
 .lines > div { flex: 0 0 140px; padding: 8px; background: #e8f5de; }
 .tall { min-height: 60px; }
  </style>
</head>
<body>
<h1>한 줄 정렬과 여러 줄 정렬</h1>
<h2>도구 모음</h2><div class="toolbar"><div>짧은 항목</div><div>두 줄 항목<br>둘째 줄</div><div>버튼 자리</div></div>
<h2>줄 묶음</h2><div class="lines"><div>1</div><div class="tall">2<br>둘째 줄</div><div>3</div><div class="tall">4<br>둘째 줄</div></div>
</body>
</html>
  1. .toolbar의 justify-content를 center로 바꿔 세 항목이 가운데로 모이는지 확인합니다. flex-start도 비교한 뒤 space-between으로 되돌립니다. 아이템 크기와 gap은 그대로 두세요.
  2. .toolbar의 align-items를 flex-start로 바꿔 위쪽에 정렬되는지 확인합니다. stretch로 바꾸면 교차축 크기가 auto인 항목이 늘어납니다. 비교 후 center로 복원합니다.
  3. .lines의 align-content만 center로 바꿉니다. 각 줄의 아이템 관계를 유지하면서 두 줄 묶음이 내려옵니다. 다시 flex-start로 돌린 뒤 align-items만 flex-start로 바꾸면 각 줄 안의 짧은 항목 위치가 바뀝니다.
  4. .lines의 flex-wrap만 nowrap으로 바꾸면 모든 항목이 한 줄을 유지하려고 하며 이 예제는 축소를 끄고 있어 가로로 넘칩니다. 이 상태에서는 align-content로 여러 줄을 정렬할 수 없습니다. 확인 후 wrap으로 복원합니다.

flex-grow·flex-shrink·flex-basis 이해하기

flex: 1 1 192px은 순서대로 grow, shrink, basis입니다. basis는 주축의 공간 분배를 시작할 기준 크기이고 최종 너비를 보장하는 값이 아닙니다. grow는 남는 공간에 대한 확대 비율, shrink는 공간이 부족할 때의 축소 비율입니다. shorthand의 숫자 한 개나 auto는 생략값 규칙이 있으므로 학습 예제에서는 세 값을 명시해 비교합니다.

선언 공간이 남을 때 공간이 부족할 때
flex: 0 1 192px 기준 크기를 유지 축소에 참여
flex: 1 1 192px 남는 공간을 분배받음 축소에 참여
flex: 0 0 192px 기준 크기를 유지 축소하지 않음. nowrap이면 넘칠 수 있음

예를 들어 콘텐츠 너비가 640px인 부모 안에 기준 크기 100px인 항목 세 개와 gap 두 개(각 20px)가 있으면 남는 공간은 640 − 300 − 40 = 300px입니다. grow 비율이 1:2:1이면 추가되는 공간은 75px, 150px, 75px이며 최종 너비는 175px, 250px, 175px입니다. 콘텐츠 최소 크기나 min/max 제약이 개입하지 않는 조건의 계산입니다.

축소량은 shrink 숫자만으로 균등 분배하지 않습니다. 축소 비율과 기준 크기를 함께 고려합니다. 기준 크기가 200px와 100px이고 shrink가 둘 다 1인 두 항목에서 60px을 줄여야 한다면, 제약이 없는 단순한 조건에서는 40px과 20px을 줄입니다. padding·border·최소 콘텐츠 크기 등이 있으면 결과가 달라질 수 있으므로 적용값을 실제로 확인해야 합니다. MDN의 flex 설명에 shorthand와 크기 조건이 설명되어 있습니다.

크기 분배와 줄바꿈 카드 실습하기

다음 코드는 flex-size.html로 저장합니다. 계산 구역은 별도 padding·border 없이 최대 너비 640px로 만들어 위 계산과 대응합니다. 카드 목록은 너비 192px를 줄바꿈의 기준으로 사용하되 남는 공간을 채우도록 합니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>flex-size.html</title>
  <style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
.calc { display: flex; gap: 20px; width: min(100%, 640px); background: #eef2f6; }
 .calc > div { flex: 1 1 100px; min-width: 0; height: 80px; background: #dceefa; }
 .calc > div:nth-child(2) { flex-grow: 2; }
 .cards { display: flex; flex-wrap: wrap; gap: 16px; list-style: none; padding: 0; }
 .cards > li { flex: 1 1 192px; min-width: 0; padding: 16px; background: #e8f5de; overflow-wrap: anywhere; }
  </style>
</head>
<body>
<h1>flex 값과 공간 분배</h1><div class="calc"><div>grow 1</div><div>grow 2</div><div>grow 1</div></div>
<h2>줄바꿈 카드</h2><ul class="cards"><li>첫째 카드</li><li>둘째 카드</li><li>셋째 카드</li><li>넷째 카드</li></ul>
</body>
</html>
  1. 브라우저를 넓혀 .calc의 너비가 640px인 상태에서 개발자 도구로 세 항목의 너비를 확인합니다. 175px·250px·175px가 됩니다. 둘째 항목의 grow만 1로 바꾸면 세 항목은 200px씩 됩니다. 비교 후 2로 복원합니다.
  2. .cards > li의 grow만 0으로 바꾸어 마지막 줄 카드가 남는 너비를 채우지 않는지 확인합니다. 다시 1로 복원하면 마지막 줄도 공간을 분배받습니다.
  3. 화면을 좁혀 한 줄에 놓이는 카드 수가 줄어드는지 확인합니다. wrap은 배치할 줄을 결정하고 각 줄은 따로 남는 공간을 분배합니다. 마지막 줄과 앞 줄의 카드 너비가 반드시 일치하지는 않습니다.
  4. 줄바꿈 대신 한 줄 넘침을 보려면 flex-wrap을 nowrap, 아이템을 flex: 0 0 192px로 바꿉니다. 두 조건을 확인한 뒤 원래 wrap과 1 1 192px로 복원합니다.

긴 문자열은 최소 크기와 줄바꿈을 함께 확인하기

Flex 아이템의 자동 최소 너비 때문에 긴 주소나 식별자가 들어간 영역이 줄어들지 못할 수 있습니다. min-width: 0은 아이템의 축소를 허용하고, overflow-wrap: anywhere는 문자열 자체가 줄바꿈될 수 있게 합니다. 상자를 줄였다고 그 안의 글자가 자동으로 잘리는 것은 아니므로 두 문제를 구분해야 합니다.

아래 코드는 flex-long-text.html로 저장합니다. 실제 주소가 아닌 공백 없는 긴 식별자를 넣었습니다. 화면을 좁혀도 안내 영역 옆의 문자열이 여러 줄로 나뉘어 읽힙니다. MDN의 overflow-wrap 설명에서 줄바꿈 규칙을 확인할 수 있습니다.

<!doctype html>
<html lang="ko">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>flex-long-text.html</title>
  <style>
* { box-sizing: border-box; }
body { margin: 16px; font: 16px/1.6 sans-serif; color: #243447; }
h1 { font-size: 24px; } h2 { font-size: 20px; margin-top: 32px; }
a { color: #145f8f; } a:focus-visible { outline: 3px solid #b4470b; outline-offset: 3px; }
.notice { display: flex; gap: 12px; max-width: 600px; border: 2px solid #789; padding: 12px; }
 .icon { flex: 0 0 48px; background: #ffe4b5; }
 .text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; background: #dceefa; }
 .text p { margin: 0; }
  </style>
</head>
<body>
<h1>긴 문자열과 최소 크기</h1><div class="notice"><div class="icon">안내</div><div class="text"><p>ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</p></div></div>
</body>
</html>
  1. .text에서 overflow-wrap만 normal로 바꿉니다. 아이템 너비는 줄어들어도 문자열이 경계 밖으로 넘칠 수 있습니다. anywhere로 복원합니다.
  2. 최소 너비의 영향을 따로 보려면 overflow-wrap: normal을 유지한 상태에서 min-width: 0을 제거합니다. 긴 문자열의 최소 크기가 아이템 배치에 미치는 영향을 확인한 뒤 두 선언을 원래 값으로 복원합니다.

정렬이 안 될 때는 먼저 부모의 축과 남는 공간을 확인하고, 크기가 안 줄어들 때는 아이템의 최소 크기와 내부 문자열을 확인하세요. 문제를 감추려고 전체 부모에 overflow: hidden을 넣으면 내용이나 포커스 표시를 잃을 수 있습니다. 레이아웃의 크기와 콘텐츠의 표시를 별도로 해결하는 편이 결과를 판단하기 쉽습니다.

같은 카테고리의 다른 글
CSS / Tutorial / 마우스 호버 효과 / 다른 이미지 보여주는 방법

CSS / Tutorial / 마우스 호버 효과 / 다른 이미지 보여주는 방법

이미지에 마우스를 올렸을 때 다른 이미지가 나타나는 효과를 CSS로 만들어보겠습니다. 다음과 같이 이미지 두 개를 넣고 div로 감쌉니다.

CSS 강좌 / display와 기본 배치 흐름 이해하기

CSS 강좌 / display와 기본 배치 흐름 이해하기

block·inline·inline-block의 줄바꿈과 크기 적용을 같은 요소로 비교합니다. display: none과 visibility: hidden의 공간 차이, 인라인 이미지의 크기 예외를 실행하며 확인합니다.

CSS 강좌 / 미디어 쿼리와 콘텐츠 기준 분기점 만들기

CSS 강좌 / 미디어 쿼리와 콘텐츠 기준 분기점 만들기

카드의 최소 폭과 여백을 기준으로 미디어 쿼리 분기점을 정합니다. 1·2·3열 전체 예제와 경계값 비교로 조건이 적용되는 과정을 확인합니다.

CSS / Tutorial / position의 값이 fixed일 때 가운데 정렬하는 방법

CSS / Tutorial / position의 값이 fixed일 때 가운데 정렬하는 방법

position의 fixed를 이용하여 요소의 위치를 고정시킬 수 있습니다. 예를 들어 상단에 고정되는 메뉴바를 만들 때 사용합니다. 그런데, fixed를 하면 요소가 한쪽으로 치우칩니다. 만약 가운데에 위치시키고 싶다면 어떻게 할까요? transform 속성으로 해결할 수 있습니다.

CSS / Tutorial / 마우스 호버 효과 / 텍스트 나오게 하는 방법

CSS / Tutorial / 마우스 호버 효과 / 텍스트 나오게 하는 방법

CSS로 특정 요소에 마우스를 올렸을 때 보이지 않던 특정 요소가 보이게 할 수 있습니다. 아래는 문단에 마우스를 올렸을 때 div 요소가 나오게 하는 예제입니다. div 요소 안에 텍스트가 있지만, 텍스트가 아닌 이미지 등 다른 것도 가능합니다.

CSS 강좌 / Grid 반복 열·자동 배치·영역 이름 사용하기

CSS 강좌 / Grid 반복 열·자동 배치·영역 이름 사용하기

repeat·auto-fit·auto-fill의 차이와 자동 배치 순서를 실행 예제로 비교합니다. grid-template-areas로 페이지를 구성하고 모바일 전환, 영역 이름 오류와 읽기 순서도 확인합니다.

CSS / Tutorial / 원 또는 타원 만드는 방법

CSS / Tutorial / 원 또는 타원 만드는 방법

CSS의 border-radius 속성으로 원 또는 타원을 만들 수 있습니다. HTML 문서에 다음과 같이 내용이 없는 요소를 하나 만듭니다. 적절히 크기를 정하여 정사각형을 만들고, 배경색을 넣습니다. border-radius 속성을 추가하고, 값에 50%를 넣으면 원이 만들어집니다.

CSS / Tutorial / 마름모 만드는 방법

CSS / Tutorial / 마름모 만드는 방법

CSS로 삼각형을 만들 수 있다면 마름모는 쉽게 만들 수 있습니다. 삼각형을 두 개 붙이면 마름모가 되기 때문입니다. 마름모는 네 변의 길이가 같은 사각형이므로, 이등변삼각형 두 개를 붙이며 됩니다.

CSS / Tutorial / 변수 사용하는 방법

CSS / Tutorial / 변수 사용하는 방법

CSS 사용자 지정 속성을 :root와 특정 구성 요소에 선언하고 var()로 색과 간격을 재사용하는 방법을 설명합니다. 상속 범위, 값이 없을 때의 대체값, 유효하지 않은 값의 처리도 예제로 확인합니다.

CSS 강좌 / 표와 셀의 크기 조절하기

CSS 강좌 / 표와 셀의 크기 조절하기

표의 자동·고정 레이아웃, 30:70 열 너비, 긴 문자열의 영향을 같은 데이터로 비교합니다. 모바일 가로 스크롤과 키보드 이동을 확인하고 말줄임 원문을 보존하는 방법을 설명합니다.