요약
- 회사 프로젝트의 너비 기준이 변경되면서 (1920 → 1280), 이에 따른 레이아웃 조정중
clamp()를 사용했으나 적용에 실패했다. - 이 실패를 기회삼아, 지금 블로그에는
clamp()를 적용했다.
들어가며
- 회사 프로젝트 전체적인 레이아웃이 변경되면서 (1920 → 1280) 텍스트에 대한 반응형까지 요청받게 됐다.
- 이에 따른 텍스트의 정의도 더 디테일해지게 됐다.
- 반응형에 맞게 미디어쿼리로 적용하려다
clamp()를 얼핏 들었던 게 기억났고, UI측면에서 훨씬 좋다고 느껴지는clamp()를 사용하고 적용하려 했으나 실패했다. - 이 실패를 기회삼아 지금 블로그에는
clamp()를 적용했고, 적용하면서 제대로 된 개념 정리+이해가 필요함을 느꼈다.
Fluid Typography(유연한 타이포그래피)

이를 구현하는 데 있어, 핵심은 바로 clamp() 함수이다.
clamp(최소값, 선호값, 최대값)
선호값과 선호값으로 허용할 수 있는 범위인 최소 허용값과 최대 허용값을 지정해서 비교한 하나의 값만을 나타내는 비교 함수형 표기법조금 풀어 말하자면, 글꼴 크기에 clamp()를 사용하면 뷰포트 크기에 따라 커지지만 최소 글꼴 크기 이하로 내려가지 않으며, 최대 글꼴 크기를 초과하지 않는 글꼴 크기를 설정할 수 있다.
** clamp(MIN, VAL, MAX) 는 사실 max(MIN, min(VAL, MAX)) 의 결과이다.
최소값(Minimum)
- 화면이 극도로 좁아져도 폰트가 읽기 어려운 수준으로 작아지지 않게 보호하는 안전장치.
선호값(Fluid / Preferred)
- 1vw + 0.5rem과 같이 뷰포트 단위(VW)와 고정 단위(REM)를 혼합(Mixed Units)하여 설정하는 것이 핵심
여기서 0.5rem과 같은 고정 값은 '베이스라인 시프트(Baseline Shift)' 역할을 한다. 단순히 vw만 쓴다면 특정 구간에서의 변화가 일어나지 않고, 너무 늦게 변화된다.

- gif에서 보듯, 왼쪽처럼 선호값이 2vw로 고정돼있다면 앞서 말한 베이스라인이 없으니, 일정 구간동안 계속 최소값으로만 동작하여 원하는 유동적인 타이포그래피(Fluid Typography)가 되지 않는다.
최대값(Maximum)
- 울트라 와이드 모니터에서 폰트가 의도치 않게 거대해지는 것을 방지하여 디자인의 의도를 보존하게 한다.
예시
- 예시는 빠른 이해를 돕기위해 선호값에 rem을 포함하지 않았다.
- 또한 최소, 최대값도 rem으로 작성하지 않았다.
기존
text-md: {
fontSize: "20px",
fontWeight: 700,
},기존에는 이렇게 폰트사이즈를 px로 정의했다면,
clamp 사용 시
text-md: {
fontSize: "clamp(14px, 1.2vw, 20px)",
fontWeight: 700,
},위와같이 사용할 수 있다. 이는 무슨 의미일까?
- 최소로 줄어들 수 있는 사이즈는 14px
- 최대로 늘어날 수 있는 사이즈는 20px
- 그 사이 1.2vw로 조절
한다는 의미다.
이를 조금 더 풀어 설명하자면,
참고. ‘1vw’란?
1vw는 고정된 픽셀(px) 값이 아니라, 현재 보고 있는 화면(viewport) 너비의 1%에 해당하는 상대적인 값.
따라서 화면 너비가 몇 픽셀인지에 따라 1vw의 픽셀 값은 달라진다.
Pixel (px) = (1vw 값 × 현재 뷰포트 너비) / 100
- 화면 너비가 1000px인 경우: 1vw = (1 × 1000) / 100 = 10px
- 화면 너비가 1920px인 경우: 1vw = (1 × 1920) / 100 = 19.2px
더 파고들기
1. 최소, 최대값은 어떻게 정할까?
사실 자기가 원하는대로 할 수 있는 것이다. 나는 text-base의 사이즈가 최소 12px이고 최대 20px이었으면 좋겠어. 아니 나는 최소 16px이고 최대 24px이었으면 좋겠어 ! 그에 맞춰 구할수도 있지만 그래도 많이 쓰는, 추천되는 기준은 있다.
최소값이 16px이라고 했을때 최대값은 어떻게 지정할까?
여기서 Modular Scale이라는 개념이 있다.
The Modular Scale
A modular scale is a sequence of numbers with a consistent ratio between them.
숫자들 사이에 일정한 비율을 가진 일련의 숫자들.
Common ratios:
일반적인 비율
- 1.125 (Major Second) — subtle, conservative
- 1.25 (Major Third) — balanced, versatile
- 1.333 (Perfect Fourth) — clear hierarchy
- 1.5 (Perfect Fifth) — dramatic, editorial
- 1.618 (Golden Ratio) — mathematical harmony
실제 유명 디자인 시스템들은 기본 스케일 비율을 1.25로 많이 가져간다고 한다.
그렇기에 16px * 1.25 = 20px이며, 최소값은 16px, 최대값은 20px이라고 정하고 시작하면 된다.
그렇다면 선호값은 어떻게 설정할까?
2. 선호값 정하기
고려해야할 건 2가지다.
- 본인의 프로젝트 스타일 (기준점 정하기)
- 너비가 최소 375px에서 최대 1024px까지라면, 이를 고려하는 선호값이 결정된다.
- 텍스트 기준 -양 끝값(Minimum & Maximum) 정하기
- 앞서 최소, 최대값 정하기에서 기본 base 값을 최소 16px에서 20px이라고 정하였다.
- 너비를 함께 고려하여, 선호값을 구해보자.
이 선호값은 일차 방정식을 통해 구할 수 있다. (갑자기?)

그래프 상의 두 점에 따른 기울기인 ‘m’을 구하는 건 최대값에서 최소값을 빼주면 되는데,
따라서 m은 m = (20 - 16) / (1024 - 375) = 0.006163328197 이 나오게 된다. 웹에서는 vw 단위로 표현해야하니, (vw는 뷰포트 너비의 100분의 1 이니까) 100을 곱해준다. 반올림한 기울기는 0.62vw이다.
m의 값을 구했으니 b의 값은 바로 구할 수 있게 된다. 최소든 최대든 아무곳에서나 계산하면 된다.
최소값으로 대입하여 계산하게 되면, 16 = (0.00616 * 375) + b 이고, b = 13.7px이 된다.
이 13.7px을 16px 기준으로 rem 계산하게 되면 13.7 / 16 = 0.8562.. 이므로, b의 rem은 반올림하여 0.86이 됨을 알 수 있다.
정리
- text-base의 기준을 1rem= 16px로 두었을 때 modular scale을 생각하여 대중적인 1.25배를 적용, 최대값은 20px이다.
- 최소 16px(1rem), 최대 20px(1.25rem) 사이에 들어가는 선호값은 나의 프로젝트 너비가 최소 375px에서 최대 1024px이 되는것을 알았고, 이를 일차방정식의 차를 통해 기울기와 y절편 값을 구해낼 수 있다.
- 결론적으로 구하게 된 text-base는 다음과 같이 구해진다.
모바일과 데스크탑에서 비율 다르게 주기
이러한 스케일을 쉽게 설정할 수 있는 www.fluid-type-scale.com 사이트를 보면 모바일과 데스크탑에서의 비율을 다르게 줄 수 있게 돼 있다.

사이트를 만든 개발자의 말에 따르면, 모바일에서는 1.25의 비율을 주어 모바일에서 보기 좋은 비율로 보여주고 데스크탑에서는 1.333의 비율을 주어 큰 화면에서 더 크게 보여짐을 위한 것이라 한다.
Instead, you may want the min and max font sizes to be independent. In that case, rather than specifying just a min font size and a single type scale, we actually need to have two separate sets of variables: one for the minimum (mobile) and another for the maximum (desktop). So whereas before we had just one base font size, now we’ll need two: an explicit minimum and maximum font size.
선택한 타입 스케일에 따라, 폰트 크기가 기술적으로는 유동적이라고 하더라도 모바일에서 여전히 너무 큰 폰트 크기를 얻게 될 수 있습니다.
대신, 최소 및 최대 폰트 크기를 독립적으로 설정하고 싶을 수 있습니다. 이 경우, 최소 폰트 크기와 단일 타입 스케일만 지정하는 것이 아니라, 실제로 두 개의 별도 변수 세트가 필요합니다. 하나는 최소값(모바일)을 위한 것이고 다른 하나는 최대값(데스크톱)을 위한 것입니다. 따라서 이전에는 하나의 기본 폰트 크기만 있었지만, 이제는 두 개가 필요합니다. 명시적인 최소 폰트 크기와 최대 폰트 크기입니다.
출처: https://www.aleksandrhovhannisyan.com/blog/fluid-type-scale-with-css-clamp/ 중..
개인적으로 공부해보며, 이 부분까진 필요없다 생각했다.
스케일을 만들어주는 사이트를 보면 base사이즈를 기준으로 다음 폰트의 크기도 1.25배, 그다음도 1.25배로 늘어가는데 실제 사용에선 너무 크기 차이가 난다.
이렇게 커지는 게 다르다보니, 이 둘을 약간 혼합하여(?) 사용하려 한다.
내가 사용하는 방법은 바로 스케일 빌더 사이트에서 보여주는 다음 폰트크기에 1.25배를 하는 게 아니라, 각각의 폰트에만 1.25배를 적용해주는 것이다.
사용해보기
내 블로그는 css를 tailwind로 작성하기에, tailwind 기준으로 작성하였다.
1. 기준 정하기
기준은 1rem = 16px (html { font-size: 16px }) 으로 정했다.
이유라한다면 대부분의 웹 브라우저 기본 폰트 크기는 16px이고, 대부분의 기기에서 잘 보이는 표준이기 때문.
2. 기준에 따라 사용하는 폰트 사이즈 clamp로 구현하기
난 text-base 부터 text-4xl까지 사용하기에, 이를 정의했다.
- xs, sm 사이즈도 있지만 이렇게 작은 사이즈일 경우 변경될 때 오히려 어색해질 수 있다고 하기에 제외하였다.
대신 앞서 언급했듯 스케일 빌더 사이트에서 보여주는 다음 폰트크기에 1.25배를 하는 게 아니라, 각각의 폰트에만 1.25배를 적용해주는 것이다.
구현하기
그렇게 구현한 코드는 아래와 같다.
/** globals.css */
@theme {
/* base: 16px~20px 기준, 나머지 비례 스케일 (375px~1024px) */
--text-base: clamp(1rem, 0.856rem + 0.617vw, 1.25rem); /* 16px~20px */
--text-base--line-height: 1.7;
--text-lg: clamp(1.125rem, 0.981rem + 0.617vw, 1.375rem); /* 18px~22px */
--text-lg--line-height: 1.6;
--text-xl: clamp(1.25rem, 1.033rem + 0.925vw, 1.625rem); /* 20px~26px */
--text-xl--line-height: 1.4;
--text-2xl: clamp(1.5rem, 1.283rem + 0.925vw, 1.875rem); /* 24px~30px */
--text-2xl--line-height: 1.3;
--text-3xl: clamp(1.875rem, 1.586rem + 1.234vw, 2.375rem); /* 30px~38px */
--text-3xl--line-height: 1.25;
--text-4xl: clamp(2.25rem, 1.961rem + 1.234vw, 2.75rem); /* 36px~44px */
--text-4xl--line-height: 1.15;
}- line-height의 정의는 본문의 가독성을 위해 base에 1.7을, 나머지는 제목같은 크기라 더 줄였다.
TMI
1. 블로그
너비 기준을 375px ~ 1024px로 정의 후 작성된 코드이지만 실제 내 블로그 글이 작성되는 부분은 최대 700px 정도이다.
내 블로그는 768px 미만(태블릿 너비)에서는 목차 없이 글을 다 보여주고, 이상일때는 목차를 보여주게 해 두었다. 최대 너비는 1024px로 고정해두었고, 웹에서 봤을 때 최대 1024px 고정에 목차를 제외한 컨텐츠 부분은 700px이다.
실제로 블로그의 경우, 1280px 이상의 일반적인 모니터 환경에서 본문 폭을 700 - 800 px 사이로 유지하는 블로그가 가장 많다.
2. WCAG 2.1 권고
에 따르면,
이 지침은 Level AAA(가장 높은 수준의 접근성) 기준에 해당하지만, 블로그처럼 텍스트 읽기가 주 목적인 웹사이트에서는 가독성을 확보하기 위한 최우선 가이드라인으로 인용.
- 띄어쓰기(공백) 포함이다.
2-1. 왜 한글은 40자 기준일까? (CJK 특성)
WCAG에서 영문은 80자, 한글·중국어·일본어(CJK)는 40자로 차이를 둔 이유는 두 가지다.
- 시각적 밀도: 한글은 자음과 모음이 결합된 복잡한 구조로, 단순한 알파벳보다 눈에 들어오는 정보량이 훨씬 많다. 영문 80자가 차지하는 물리적 가로 너비와 한글 40자가 차지하는 너비가 시각적으로 비슷하게 느껴진다.
- 가독 효율: 인지 심리학 연구에 따르면, 한글은 띄어쓰기 단위로 의미를 파악하기 때문에 줄이 너무 길어지면 맥락을 놓치기 쉽다. 40자 내외가 한 번에 들어오는 최적의 범위이다.
이를 고려했을 때, 내 블로그 기준 한 줄에 한글 40자가 차지하는 베이스가 되는 p 태그의 폰트 사이즈는 16px ~ 18px이다. (700px/18px = 38.8888…)
왜 내 글에서는 20px인데 한 줄에 50자가 들어가있을까? 이는 사용하는 폰트에 차이가 있다고 한다.
그리고 브런치나 다른 블로그 봐도 제대로 지키는 곳 많이 못봤다.
3. 회사에서 적용에 실패한 이유
크게 2가지 문제가 있었다.
- 텍스트 기준을 14px로 잡았을 때의 문제.
base를 14px로 설정하여 프로젝트를 진행하기로 변경됐다. 그렇게 기준을 14px로 설정 후 작업하기까지는 좋았다. 그런데, 회사에서 사용하는 CSS 라이브러리 chakra UI가 내부적으로 16px을 기준으로 동작한다. 이를 컴포넌트에 적용하는 것에 대한 문제가 컸다.
- 나머지는 반응형 요소가 아님
padding, margin 같은 요소들이 고정적이라, 텍스트가 커졌을 때 레이아웃이 깨지는 오류가 발생했다. 사실 1번보다 더 큰 문제였다. 수많은 모든 컴포넌트와 페이지에 다시 맞추는 건 시간대비 비효율적인 일이 됐다.
4. 근데 왜 필요한걸까?
사실 개발자가 아닌 일반인의 입장으로 봤을 때, fluid typography가 정말로 적용할만한 가치가 있는가에 대한 근본적인 질문이 들었다. 어느 사용자가 모든 페이지 들어갈때마다 웹 사이트창을 줄이고 늘려가며 확인하는가? 디자인이 매우 중요한 포트폴리오 사이트나, 에이전시 같은곳이 아니라면 정말로 필요할까? 싶은 기술이긴 하다.
5. clamp 선호값에 rem이 필요한 이유 (codepen)
- 선호값에서 gif로 작성한 부분은 클로드를 통해 인터렉티브한 설명으로 보여준 부분이다.
- 이를 다른 사람들도 쉽게 이해할 수 있게 코드펜으로 적용해두었다. 참고하면 더 도움된다.
마치며
정말로 필요한 기술일까?에 대한 의문은 있으나 지금의 블로그에 적용하고, 또 이 개념에 대해 명확히 정리함에 있어 스스로 만족할 수 있는 내용이었다.
당연하게도 내 방법이 정답은 아니다. 다만, clamp라는 개념에 대해 시야를 넓힐 수 있게 된 계기가 됐다.
출처
https://www.youtube.com/watch?v=P2zoO5Fw2Ks - How to Create Fluid Typography with CSS Clamp | Responsive Type Scales for Custom Themes
www.fluid-type-scale.com - Fluid Type Scale Calculator
https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/clamp - MDN-clamp()
https://www.w3.org/WAI/WCAG21/Understanding/visual-presentation.html - WCAG 2.1 Understanding Docs - Understanding SC 1.4.8:Visual Presentation (Level AAA)
https://www.aleksandrhovhannisyan.com/blog/fluid-type-scale-with-css-clamp/
https://www.smashingmagazine.com/2022/01/modern-fluid-typography-css-clamp/