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 강좌 / 문법

CSS 강좌 / 문법

CSS의 선택자·선언·구분 기호·주석을 예제로 설명합니다. 잘못된 속성값과 세미콜론 누락을 비교하고, 실행 가능한 예제와 오류 수정 실습으로 브라우저가 적용한 결과를 확인합니다.

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

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

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

CSS 강좌 / Grid로 행과 열 만들기

CSS 강좌 / Grid로 행과 열 만들기

Grid의 격자선·트랙·셀과 fr 단위를 이해하고 명시적 행, 자동 행, 열을 가로지르는 배치를 전체 예제로 익힙니다. 긴 콘텐츠와 모바일에서 생기는 넘침도 비교합니다.

CSS 강좌 / 넘치는 콘텐츠와 긴 문자열 처리하기

CSS 강좌 / 넘치는 콘텐츠와 긴 문자열 처리하기

같은 내용에 visible·hidden·auto·scroll을 적용해 넘침 처리를 비교합니다. 긴 URL 줄바꿈과 실제 말줄임표 예제를 실행하고, 원문 보존과 키보드 스크롤을 함께 확인합니다.

CSS / Tutorial / 마우스 호버 효과 /  이미지 확대하는 방법

CSS / Tutorial / 마우스 호버 효과 / 이미지 확대하는 방법

이미지에 마우스를 올렸을 때 이미지가 확대되는 효과를 만들어보겠습니다. 다음과 같이 이미지가 들어간 간단한 HTML 문서를 만듭니다.

CSS 강좌 / 색상 값과 px·em·rem·% 단위 이해하기

CSS 강좌 / 색상 값과 px·em·rem·% 단위 이해하기

색상 표기와 px·em·rem·%의 계산 기준을 비교합니다. 중첩된 글자 크기와 여백이 있는 상자 예제로 실제 크기를 계산하고 개발자 도구에서 확인할 수 있습니다.

CSS 강좌 / 브라우저 개발자 도구로 CSS 확인하고 수정하기

CSS 강좌 / 브라우저 개발자 도구로 CSS 확인하고 수정하기

브라우저 개발자 도구에서 안내 문단을 선택하고, Styles의 선언과 Computed의 최종 값을 확인합니다. 색상 변경·선언 끄기·원본 저장 실습과 적용되지 않는 CSS의 원인별 점검 방법을 제공합니다.

CSS 강좌 / 기본 선택자 - 요소, 클래스, ID, 속성

CSS 강좌 / 기본 선택자 - 요소, 클래스, ID, 속성

요소·클래스·ID·속성 선택자를 같은 HTML에 적용해 대상과 결과를 비교합니다. 복합 클래스, 공백으로 구분한 속성값, 필수 입력칸을 포함한 전체 예제와 선택자 수정 실습을 제공합니다.

CSS / Tutorial / placeholder의 색, 글자 모양 등 꾸미는 방법

CSS / Tutorial / placeholder의 색, 글자 모양 등 꾸미는 방법

placeholder는 HTML5에서 새로 나온 속성으로 input 요소나 textarea 요소에 안내문을 넣을 수 있습니다. 기본 모양은 회색의 글자로, 배경색이 하얀색 또는 밝은 색이면 보기에 괜찮습니다. 하지만 배경색이 어두운 색이거나 화려한 색이면 회색 글자가 어울리지 않을 수 있습니다. placeholder는 ::placeholder 선택자로 선택하여 꾸밀 수 있습니다.

CSS / Tutorial / 표 꾸미기 / 배경색

CSS / Tutorial / 표 꾸미기 / 배경색

배경색은 background-color 속성으로 만듭니다. table, tr, th, td, thead, tbody, tfoot에 적용할 수 있습니다. 다음 표를 기본으로 하고, 배경색을 여러 곳에 추가해보겠습니다.