clamp()가 하는 일
clamp(MIN, PREFERRED, MAX)는 값 세 개를 받아서, 가운데 값이 나머지 둘 사이에 있는 한 그 값을 돌려줘요. 고전적인 용도는 미디어 쿼리 없이 화면과 함께 커지다가 적당한 한계에서 멈추는 제목이에요.
선호값은 1rem + 3vw, 즉 16px에 너비의 3%를 더한 값이에요. 너비 800px 미리보기에서는 16 + 24 = 40px이고, 24px(1.5rem)과 48px(3rem) 사이라서 제목은 40px이에요. 320px 휴대폰에서는 선호값이 25.6px이에요. 1067px을 넘으면 48px을 넘어서 48px에서 멈춰요. 창 크기를 바꿔서 숫자가 바뀌는 걸 보세요. 여기서 vw는 미리보기 프레임 너비의 퍼센트예요.
창 크기를 바꾸지 않고 보기
vw는 뷰포트를 따르는데, 글을 읽는 동안 뷰포트를 바꾸기는 쉽지 않아요. 컨테이너 쿼리 단위는 대신 컨테이너를 따라요. cqi는 컨테이너 너비의 1%예요. 슬라이더를 끌어서 상자를 바꿔 보면 같은 종류의 clamp()가 반응해요.
시작 쪽으로 밀면 제목이 20px(MIN)에서 멈춰요. 끝 쪽으로 밀면 40px(MAX)에서 멈춰요. 그 사이에서는 0.5rem + 6cqi를 따라요. vw 버전과 같은 원리이고, 자만 더 작아요.
세 인수
font-size: clamp(1rem, 0.8rem + 1vw, 1.5rem);
/* MIN PREFERRED MAX */
| 인수 | 역할 | 보통 쓰는 단위 |
|---|---|---|
| MIN | 값이 가질 수 있는 가장 작은 크기 | rem |
| PREFERRED | 화면에 따라 바뀌는 값 | rem + vw (또는 cqi) |
| MAX | 값이 가질 수 있는 가장 큰 크기 | rem |
각 인수 안에서는 calc()를 쓰지 않아도 계산이 돼요. 1rem + 2vw는 그대로 괜찮아요. +와 -는 양쪽에 공백이 필요하고, 없으면 선언 전체가 잘못된 값이 돼요.
MIN이 MAX보다 크면 MIN이 이겨요. clamp(3rem, 5vw, 2rem)은 항상 3rem이에요.
가운데 값 계산하기
320px 화면에서 16px, 1280px 화면에서 24px로 글자를 키우려면 이렇게 해요.
- 기울기: (24 − 16) ÷ (1280 − 320) = 8 ÷ 960 = 0.00833, 즉 0.833vw예요(vw는 100px당이에요).
- 시작점: 16px − 0.00833 × 320px = 13.33px, 즉 0.833rem이에요.
- 둘레에 한계를 넣어요.
font-size: clamp(1rem, 0.833rem + 0.833vw, 1.5rem);
너비 320px에서는 13.33 + 2.67 = 16px, 1280px에서는 13.33 + 10.67 = 24px이 되고, 그 범위 밖에서는 한계에 머물러요. 온라인 "clamp 계산기"가 바로 이 계산을 해 줘요.
min()과 max()
clamp()는 더 간단한 함수 두 개의 조합이에요.
min(a, b)는 작은 값을 돌려줘서 상한을 정해요.max(a, b)는 큰 값을 돌려줘서 하한을 정해요.clamp(MIN, VAL, MAX)는max(MIN, min(VAL, MAX))와 같아요.
처음에는 이름이 거꾸로 느껴져요. "최대 600px"이라고 하려면 min()을 써요.
넓은 미리보기에서 첫 번째 카드는 420px에서 멈춰요. 260px 부모 안에서는 100%가 더 작은 값이라서 두 번째 카드는 260px이에요. max(12px, 3%)는 첫 번째 카드에 부모 너비의 3%(body 기준, 800px 미리보기에서 약 23.5px)를 주고, 두 번째 카드에는 260px의 3%(7.8px)가 하한보다 작아서 12px을 줘요.
width: min(100%, 420px)는 옛 방식인 width: 100%; max-width: 420px; 두 줄을 선언 하나로 대신해요.
글자 크기 너머: 간격과 너비
clamp()는 길이를 받는 모든 속성에서 동작해요. 가운데 값에 퍼센트를 쓰면 컴포넌트가 뷰포트 대신 부모를 기준으로 유동적이 돼요.
300px 부모에서 카드는 너비 240px(80%)에 padding 15px(300px의 5%)이에요. 760px 부모에서는 80%가 608px이라서 카드가 최댓값 520px에서 멈추고, 760px의 5%는 38px이라서 padding은 32px에서 멈춰요.
접근성: 가운데 값에 rem을 남겨 두세요
font-size: 5vw처럼 vw로만 만든 글자 크기는 독자가 브라우저 설정에서 기본 글자 크기를 키워도 커지지 않고, 브라우저 확대에도 커지지 않아요. 확대하면 CSS 픽셀 기준으로 뷰포트가 좁아지기 때문이에요. rem 부분(1rem + 2vw)과 rem 한계를 더하면 텍스트가 독자의 설정과 연결된 채로 유지돼요. rem과 vw는 단위 페이지에서 자세히 설명해요.
자주 하는 실수
- 최솟값에
min()쓰기.min()은 작은 값을 고르니 상한이에요. "최소 12px"에는max(12px, ...)를 쓰세요. +나-둘레에 공백 없음.clamp(1rem, 1rem+2vw, 3rem)은 잘못된 값이라 속성이 이전 값으로 돌아가요.- 가운데에
vw만 쓰기. 그러면 텍스트가 독자의 글자 크기 설정을 무시해요.rem항을 더하세요. - MIN이 MAX보다 큼. 결과가 항상 MIN이 되는데, 의도한 경우는 드물어요.
- 글자 크기 한계를
px로 쓰기. 더 큰 글자가 필요한 독자에게도 텍스트를 제한해요.rem을 쓰세요.
자주 묻는 질문
CSS에서 clamp()는 무엇을 하나요?
clamp(MIN, PREFERRED, MAX)는 선호값이 두 한계 사이에 있는 동안 그 값을 쓰고, 벗어나면 가까운 한계를 써요. font-size: clamp(1rem, 4vw, 2rem)은 뷰포트 너비의 4%를 따르지만 1rem보다 작거나 2rem보다 커지지 않아요.
clamp로 반응형 글자 크기는 어떻게 만드나요?
가운데에 뷰포트 기준 값을, 양쪽에 고정 한계를 넣고, 가운데 값에 rem을 섞어서 텍스트가 독자의 글자 크기 설정을 계속 따르게 하세요. font-size: clamp(1.5rem, 1rem + 2vw, 3rem);
clamp()에서 최솟값이 최댓값보다 크면 어떻게 되나요?
최솟값이 이겨요. clamp()는 최댓값 다음에 최솟값을 적용하기 때문에 clamp(3rem, 5vw, 2rem)은 항상 3rem이 돼요.
CSS에서 min()과 max()는 무엇이 다른가요?
min()은 가장 작은 값을 돌려줘서 상한 역할을 해요. width: min(100%, 600px)는 600px보다 넓어지지 않아요. max()는 가장 큰 값을 돌려줘서 하한 역할을 해요. font-size: max(1rem, 2vw)는 1rem보다 작아지지 않아요.
clamp()는 모든 브라우저에서 지원되나요?
네, clamp(), min(), max()는 Chrome, Edge, Firefox, Safari의 모든 최신 버전에서 동작하고, 길이, 숫자, 퍼센트, 각도를 받는 모든 속성에 쓸 수 있어요.