데스크탑에서 딱 맞던 글자가 폰에서는 답답하게 크고, 폰에 맞추면 데스크탑에서 초라하게 작습니다. 글자 크기를 화면에 따라 흐르게 만드는 방법을 봅니다. 아래 예제는 그대로 확인할 수 있습니다.

59.1 미디어쿼리로 단계 바꾸기

가장 기본은 화면 폭 구간마다 크기를 갈아 끼우는 것입니다. 손이 많이 가지만 동작은 확실합니다.


h1 { font-size: 1.75rem; }
@media (min-width: 768px) {
h1 { font-size: 2.25rem; }
}
@media (min-width: 1200px) {
h1 { font-size: 3rem; }
}


구간을 넘을 때마다 크기가 툭 바뀝니다. 확실하지만 경계에서 계단처럼 끊기고, 관리할 중단점이 늘어나는 것이 흠입니다.

59.2 clamp로 매끄럽게 흐르기

구간을 나누는 대신 크기가 화면 폭을 따라 연속으로 흐르게 할 수 있습니다. clamp 한 줄이 미디어쿼리 여러 개를 대신합니다.


h1 {
font-size: clamp(1.75rem, 1rem + 3vw, 3rem);
}


최소 1.75rem, 최대 3rem 사이에서 화면 폭에 따라 부드럽게 커집니다. 경계에서 튀지 않고 미끄러지듯 변하니 중단점을 셀 필요가 없습니다.

59.3 가운데 값 뜯어보기

clamp의 가운데 식이 흐름을 정합니다. 고정분과 화면 비례분을 더해 기울기를 만듭니다.


/* 1rem + 3vw 의 의미 */
/* 360px 화면: 1rem + 약 0.67rem = 약 1.67rem -> 하한 1.75 */
/* 768px 화면: 1rem + 약 1.44rem = 약 2.44rem */
/* 1280px 화면: 1rem + 2.4rem = 3.4rem -> 상한 3 */
h1 { font-size: clamp(1.75rem, 1rem + 3vw, 3rem); }


고정분 1rem이 바닥을 받치고 3vw가 화면에 비례해 더해집니다. rem을 섞어 두면 사용자가 글자를 키웠을 때도 함께 커져 접근성이 지켜집니다.

59.4 vw만 쓰면 안 되는 이유

크기를 순수 vw로만 주면 아주 좁은 화면에서 글자가 읽기 어려울 만큼 작아집니다. 하한이 없기 때문입니다.


/* 나쁜 예: 하한 없음 */
h1 { font-size: 5vw; }
/* 좋은 예: clamp로 바닥 받침 */
h1 { font-size: clamp(1.5rem, 5vw, 3rem); }


5vw는 320px 화면에서 16px까지 쪼그라들어 제목 같지 않습니다. clamp로 최소값을 걸면 아무리 좁아도 그 아래로는 안 내려갑니다.

59.5 스케일 전체를 유동으로

제목 하나만이 아니라 스케일 전체를 흐르게 할 수 있습니다. 각 단계를 clamp 변수로 정의합니다.


:root {
--step-0: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
--step-1: clamp(1.25rem, 1.1rem + 0.75vw, 1.5rem);
--step-2: clamp(1.5rem, 1.3rem + 1vw, 2rem);
--step-3: clamp(1.875rem, 1.5rem + 1.8vw, 2.75rem);
}
h2 { font-size: var(--step-3); }
p { font-size: var(--step-0); }


본문은 살짝만, 제목은 크게 흐르도록 단계마다 기울기를 다르게 줬습니다. 화면이 넓어질수록 제목과 본문의 크기 차가 자연스럽게 벌어집니다.

59.6 행간도 함께 조절

글자가 커지면 줄 간격 감각도 달라집니다. 좁은 화면에서 넉넉하던 행간을 넓은 화면에서 살짝 줄이면 균형이 맞습니다.


h1 {
font-size: clamp(1.75rem, 1rem + 3vw, 3rem);
line-height: clamp(1.15, 1.3 - 0.3vw, 1.3);
}


제목이 작을 때는 행간을 조금 벌려 두 줄을 편하게, 커지면 바짝 붙여 한 덩어리로 만듭니다. 크기와 행간이 같이 움직이니 어느 폭에서도 안정적입니다.

59.7 컨테이너 기준으로 흐르기

vw는 화면 전체 폭 기준이라 사이드바 안 좁은 카드에서는 어긋납니다. 컨테이너 크기 기준 단위를 쓰면 요소 폭에 맞춰 흐릅니다.


.card {
container-type: inline-size;
}
.card h3 {
font-size: clamp(1.1rem, 0.9rem + 2cqi, 1.6rem);
}


cqi는 컨테이너 안쪽 폭의 1퍼센트라, 같은 카드를 넓은 자리에 두면 제목이 커지고 좁은 자리에 두면 작아집니다. 화면이 아니라 그 요소가 놓인 공간에 반응하는 셈입니다.

59.8 한 줄 길이도 반응형으로

크기만 흘려도 한 줄이 너무 길어지면 헛일입니다. 본문 폭을 ch로 묶어 어느 화면에서도 읽기 좋은 길이를 지킵니다.


.prose {
max-width: 65ch;
font-size: clamp(1rem, 0.95rem + 0.3vw, 1.125rem);
margin-inline: auto;
padding-inline: 1.25rem;
}


글자는 화면에 따라 흐르되 한 줄은 65자 언저리에 머뭅니다. 넓은 모니터에서도 본문이 끝없이 늘어지지 않고 양옆 여백이 붙습니다.

59.9 여백도 함께 흐르기

글자만 흐르고 여백이 고정이면 좁은 화면에서 답답합니다. 안쪽 여백과 문단 간격도 화면에 맞춰 조절합니다.


.section {
padding: clamp(1.5rem, 1rem + 4vw, 4rem);
}
.prose p {
margin-bottom: clamp(1rem, 0.9rem + 0.5vw, 1.5rem);
}


글자가 커지는 넓은 화면에서는 여백도 함께 넓어져 균형이 유지됩니다. 크기와 간격이 따로 놀지 않으니 어느 폭에서도 정돈된 인상입니다.

59.10 접근성 지키며 흐르기

순수 vw로만 크기를 주면 사용자가 브라우저 글자 확대를 켜도 안 커집니다. rem을 섞어 두면 확대가 살아납니다.


/* 나쁜 예: 확대에 반응 안 함 */
h2 { font-size: 4vw; }
/* 좋은 예: rem 고정분이 확대를 받음 */
h2 { font-size: clamp(1.5rem, 1rem + 2vw, 2.5rem); }


가운데 식의 1rem이 사용자 설정에 따라 함께 커지기 때문에, 화면 폭에도 반응하고 글자 확대에도 반응합니다. 유연함과 접근성을 둘 다 챙기는 지점입니다. 반대로 vw만 쓰면 확대 버튼을 눌러도 글자가 꿈쩍하지 않아, 눈이 불편한 사용자가 손쓸 방법이 사라집니다.


/* 흐름을 완전히 끄고 싶은 예외 요소 */
.fixed-label {
font-size: 0.875rem; /* rem 고정 */
}
/* 대부분의 텍스트는 유동 */
.fluid {
font-size: clamp(1rem, 0.9rem + 0.4vw, 1.2rem);
}


모든 글자를 흐르게 할 필요는 없습니다. 작은 라벨처럼 크기가 변하면 오히려 어색한 요소는 rem으로 고정하고, 본문과 제목만 유동으로 두는 식으로 나눠 쓰면 됩니다.

59.11 정리

반응형 타이포는 미디어쿼리로 단계를 갈아 끼우는 대신 clamp로 크기를 흐르게 하는 쪽이 깔끔합니다. 최소값으로 바닥을 받치고 vw나 cqi로 기울기를 주되, 행간과 한 줄 길이까지 함께 챙기면 됩니다. 화면 폭이라는 손댈 수 없는 변수를 하나 정하고 나면, 나머지는 계산이 대신 맞춰 줍니다.