AD JB Toolbox 01

CSS 강좌 / 유동적인 크기로 반응형 레이아웃 시작하기

반응형 레이아웃은 화면과 콘텐츠가 사용할 수 있는 공간에 맞춰 크기와 배치를 조절하는 구성입니다. 먼저 고정 폭을 줄이고 부모 폭을 넘지 않는 유동적인 크기를 만든 뒤, 배치 자체를 바꿔야 할 때 미디어 쿼리를 추가하면 됩니다. 이 강의에서는 본문·글자·카드·이미지가 좁은 공간에 적응하도록 만드는 기본값을 다룹니다.

화면 폭과 요소가 사용할 수 있는 폭 구분하기

브라우저에서 웹페이지가 표시되는 영역을 뷰포트(viewport)라고 합니다. 그러나 본문 안 카드가 사용할 수 있는 폭은 뷰포트보다 작을 수 있습니다. 부모의 여백, 다른 열과의 간격, 최대 폭 제한을 제외하고 남은 공간에 카드가 들어가야 하기 때문입니다.

width: 100%의 백분율은 일반적인 블록 배치에서 요소를 감싸는 기준 영역의 폭을 사용합니다. 100vw는 뷰포트 폭을 기준으로 하므로 작은 카드 안에 넣어도 화면 전체만큼 커질 수 있습니다. 세로 스크롤바 처리와 바깥 여백까지 더해지면 가로 넘침을 만들기도 합니다. 본문 내부 요소의 폭에는 먼저 백분율이나 자동 크기를 검토하세요.

지정 좁은 부모 넓은 부모 사용 기준
width: 48rem 부모보다 클 수 있음 48rem 유지 줄어들어도 되는 본문의 기본값으로는 부적합
width: 100% 부모에 맞춰 줄어듦 부모 폭까지 계속 늘어남 부모를 채워야 하는 요소
width: 100%; max-width: 48rem 48rem보다 작게 줄어듦 최대 48rem 읽는 폭에 제한이 필요한 본문
min-width: 48rem 48rem 미만으로 줄지 않음 다른 크기 규칙에 따라 결정 필수 최소 크기가 있을 때만 사용

본문에 최대 폭과 여백 지정하기

*, *::before, *::after { box-sizing: border-box; }
.content {
  width: 100%;
  max-width: 48rem;
  margin-inline: auto;
  padding-inline: 1rem;
}

box-sizing: border-box이면 지정한 폭 안에 테두리와 안쪽 여백이 포함됩니다. 루트 글꼴 크기가 16px이고 부모 폭이 390px일 때 이 본문의 바깥 폭은 390px, 좌우 안쪽 여백을 뺀 콘텐츠 폭은 358px입니다. 부모가 1000px이면 바깥 폭은 768px에서 멈추고 남는 바깥 공간을 좌우 자동 마진으로 나눕니다.

같은 요소에 content-box를 적용하면 width: 100%에 안쪽 여백이 추가되어 부모보다 넓어질 수 있습니다. 반면 마진은 border-box에도 포함되지 않습니다. width: 100%와 양쪽의 고정 마진을 함께 지정할 때는 전체 합계를 확인해야 합니다. 최소 폭과 최대 폭이 충돌하면 최소 폭 때문에 더 커질 수 있으므로 min-width도 점검하세요.

min()과 clamp()로 값의 범위 정하기

min()은 후보 중 작은 값을 선택합니다. width: min(100%, 48rem)은 부모 폭과 48rem 중 작은 폭을 사용하므로, 앞서 지정한 100%와 최대 폭 제한을 하나의 선언으로 나타낼 수 있습니다.

.content { width: min(100%, 48rem); }
h1 { font-size: clamp(1.5rem, 1rem + 2vw, 2.5rem); }

clamp(최솟값, 선호값, 최댓값)는 가운데 값을 계산하되 양끝 범위를 벗어나지 않게 합니다. 위 제목에서 rem은 루트 글꼴 크기를, vw는 뷰포트 폭의 1%를 기준으로 합니다. 루트 크기가 16px이면 최솟값은 24px, 최댓값은 40px이고 선호값은 16px에 화면 폭의 2%를 더한 값입니다.

뷰포트 폭 가운데 값 계산 실제 제목 크기
320px 16 + 6.4 = 22.4px 최솟값 24px
600px 16 + 12 = 28px 28px
1200px 16 + 24 = 40px 40px
1600px 16 + 32 = 48px 최댓값 40px

본문 글자까지 화면 폭에만 의존하게 만들면 좁은 화면이나 확대 상황에서 너무 작아질 수 있습니다. 제목에 유동 크기를 쓸 때도 읽을 수 있는 하한을 두고, 본문은 rem 기반 크기로 유지하는 것이 출발점으로 알맞습니다. rem을 섞었다는 이유만으로 확대 접근성이 자동으로 확보되지는 않으므로 실제 브라우저 확대와 기본 글꼴 설정에서도 확인해야 합니다. MDN의 clamp() 정의와 접근성 설명에서 각 인수의 역할을 확인할 수 있습니다.

전체 예제: 카드·그림·긴 문자열 함께 줄이기

다음 코드를 UTF-8의 fluid-size.html에 저장하고 브라우저로 여세요. 그림은 파일에 포함된 SVG 데이터이므로 따로 내려받을 이미지나 외부 라이브러리가 필요하지 않습니다. 넓은 화면과 390px 정도의 좁은 화면에서 본문의 폭, 카드 열 수와 제목 크기를 비교합니다.

<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>fluid-size.html</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font: 1rem/1.6 sans-serif; color: #243447; }
h1, h2, p { margin-top: 0; } a { color: #145f8f; }
a:focus-visible, button:focus-visible, input:focus-visible { outline: 3px solid #ac4100; outline-offset: 3px; }
.content { width: min(100%, 48rem); margin-inline: auto; padding: 1rem; }
h1 { font-size: clamp(1.5rem, 1rem + 2vw, 2.5rem); line-height: 1.3; }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); gap: 1rem; }
.card { min-width: 0; padding: 1rem; background: #e8f3fa; overflow-wrap: anywhere; }
.card img { display: block; max-width: 100%; height: auto; margin-bottom: 1rem; }
.token { font-family: monospace; }
</style>
</head>
<body>
<main class="content">
<h1>화면과 내용에 맞춰 크기 조절하기</h1>
<p>본문은 최대 48rem이며, 화면이 작으면 부모 폭에 맞춰 줄어듭니다.</p>
<div class="cards">
  <article class="card"><img src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22400%22%20height%3D%22300%22%20viewBox%3D%220%200%20400%20300%22%3E%3Crect%20width%3D%22400%22%20height%3D%22300%22%20fill%3D%22%23287699%22%2F%3E%3Crect%20width%3D%22400%22%20height%3D%2235%22%20fill%3D%22%23205c32%22%2F%3E%3Crect%20y%3D%22265%22%20width%3D%22400%22%20height%3D%2235%22%20fill%3D%22%239e3131%22%2F%3E%3Ccircle%20cx%3D%22200%22%20cy%3D%22150%22%20r%3D%2270%22%20fill%3D%22%23f6ae4c%22%2F%3E%3Crect%20x%3D%2212%22%20y%3D%22120%22%20width%3D%2230%22%20height%3D%2260%22%20fill%3D%22white%22%2F%3E%3Crect%20x%3D%22358%22%20y%3D%22120%22%20width%3D%2230%22%20height%3D%2260%22%20fill%3D%22white%22%2F%3E%3C%2Fsvg%3E" width="400" height="300" alt="위아래 띠와 가운데 원이 있는 실습 그림"><h2>그림이 있는 카드</h2><p>이미지는 카드보다 넓어지지 않고 원래 비율을 유지합니다.</p></article>
  <article class="card"><h2>여러 줄로 이어지는 제목과 설명</h2><p>카드의 높이를 고정하지 않으면 글이 길어져도 아래로 늘어납니다.</p></article>
  <article class="card"><h2>긴 식별자</h2><p class="token">ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</p></article>
</div></main>
</body>
</html>

카드의 minmax(min(100%, 14rem), 1fr)는 기본 최소 폭 14rem을 쓰되 부모가 더 좁으면 100%까지 줄이게 합니다. auto-fit은 들어갈 수 있는 열을 만들고, 남은 폭을 1fr 열이 나눠 가집니다. 카드 안쪽 여백 때문에 실제 텍스트와 그림의 폭은 카드 바깥 폭보다 작습니다. 열 수를 기기 이름으로 판단하지 말고 부모의 이용 가능한 폭으로 확인하세요.

min-width: 0은 카드가 콘텐츠의 최소 폭 때문에 줄어들지 못하는 상황을 막고, overflow-wrap: anywhere는 긴 URL이나 식별자가 필요하면 중간에서 줄바꿈되게 합니다. 두 속성은 역할이 다릅니다. 최소 폭을 풀어도 문자열이 실제로 줄바꿈되지 않으면 여전히 밖으로 그려질 수 있습니다. 줄이 나뉘어도 복사한 문자열의 값이 바뀌는 것은 아닙니다.

한 가지씩 바꿔서 확인하는 실습

  1. 화면을 390px로 줄입니다. 본문은 화면 안에 들어가고 카드가 세로로 이어지며, 그림 위아래의 띠와 가운데 원을 모두 볼 수 있어야 합니다.
  2. .content의 폭만 48rem으로 바꿉니다. 좁은 화면에서 본문이 왜 넘치는지 확인한 뒤 min(100%, 48rem)으로 되돌립니다.
  3. 제목의 최댓값만 3rem으로 바꿔 넓은 화면에서 차이를 봅니다. 좁은 화면의 크기가 바뀌지 않는 이유를 가운데 값 계산으로 설명하고 2.5rem으로 복구합니다.
  4. .card에서 overflow-wrap: anywhere만 제거합니다. 긴 식별자가 카드 바깥으로 나오는지 확인하고 복구합니다. 이후 루트 크기를 바꾸는 실험과 브라우저 확대는 별개의 조건으로 기록합니다.

넘침을 숨기는 overflow-x: hidden을 페이지 전체에 넣기 전에 폭·여백·최소 폭·문자열을 확인하세요. 화면에서 안 보이게 가리면 원인을 해결하지 못한 채 콘텐츠나 조작 요소가 잘릴 수 있습니다. 반응형 구성의 기본 원리는 MDN의 반응형 디자인 안내도 참고할 수 있습니다.

같은 카테고리의 다른 글
CSS 강좌 / 문단과 목록의 간격, 정렬, 목록 표시 설정하기

CSS 강좌 / 문단과 목록의 간격, 정렬, 목록 표시 설정하기

문단 안의 줄 간격, 문단 사이 여백, 첫 줄 들여쓰기를 구분합니다. 긴 목록을 이용해 outside·inside 표시 위치와 항목 간격을 비교하고 정렬 문제를 확인할 수 있습니다.

CSS 강좌 / 상속(inheritance)

CSS 강좌 / 상속(inheritance)

CSS 속성은 상속하는 속성과 상속하지 않는 속성이 있습니다. 상속하는 속성은 자식 요소에 영향을 미칩니다. 상속하지 않는 속성은 자식 요소에 영향을 미치지 않습니다.

CSS 강좌 / 세로 가운데 정렬하는 방법

CSS 강좌 / 세로 가운데 정렬하는 방법

CSS에서 텍스트의 가로 가운데 정렬은 text-align 속성을 이용합니다. 요소의 가로 가운데 정렬은 margin 속성을 이용합니다. 세로 정렬을 가운데로 하려면 어떻게 해야 할까요? 네 가지 방법을 소개합니다.

CSS 강좌 / 표 꾸미기 / 배경색

CSS 강좌 / 표 꾸미기 / 배경색

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

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

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

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

CSS 강좌 / 표 꾸미기 / 테두리

CSS 강좌 / 표 꾸미기 / 테두리

테두리는 border 속성으로 만듭니다. table, th, td 요소에 적용할 수 있습니다. tr 요소에는 적용되지 않습니다.

CSS 강좌 / CSS를 HTML에 적용시키는 방법

CSS 강좌 / CSS를 HTML에 적용시키는 방법

인라인·내부·외부 CSS의 작성 위치를 비교하고, 두 HTML 페이지가 하나의 스타일시트를 공유하도록 구성합니다. 폴더 위치에 따른 경로와 CSS가 적용되지 않을 때의 확인 순서도 설명합니다.

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

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

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

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

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

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

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

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

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