폰트 크기 단위 px, rem, em 차이 완벽 정리 (반응형 웹 필수)

1주 전 폰트 크기 단위 px, rem, em 차이 완벽 정리

CSS로 웹 폰트 스타일을 잡다 보면 px, rem, em 중 무엇을 써야 할지 고민되는 순간이 온다. “그냥 익숙한 px로 폰트 크기를 다 때려 박으면 안 되나?” 싶겠지만, 그랬다간 모바일 화면에서 레이아웃이 다 깨지는 대참사가 일어난다.

오늘은 헷갈리는 CSS 폰트 단위의 명확한 차이를 짚고, 특히 많은 개발자가 오해하는 em의 작동 원리(왜 패딩은 부모를 안 볼까?)를 파헤친다. 마지막엔 현업 국룰 세팅법까지 정리했으니 끝까지 보면 이득이다.

CSS 폰트 단위별 특징 요약

핵심은 ‘무엇을 기준으로 크기가 변하는가’이다. 이 기준점만 이해하면 혼란이 정리가 된다.

  • px (Pixels): 절대 단위
    • 부모 요소나 브라우저 설정에 영향받지 않는 고정된 값이다.
    • 직관적이지만, 사용자가 브라우저 글꼴 설정을 변경해도 크기가 변하지 않아 웹 접근성 측면에서 불리하다. 테두리(border)처럼 고정된 두께가 필요할 때만 제한적으로 사용한다.
  • rem (Root EM): 최상위 기준
    • HTML 문서의 최상위 요소인 <html> 태그의 폰트 사이즈를 기준으로 한다.
    • 구조가 아무리 복잡해도 오직 ‘루트’ 하나만 바라보기 때문에 일관성 관리에 가장 유리하다.
  • em (EM): 부모 기준
    • 해당 요소를 감싸고 있는 직계 부모(Parent)의 폰트 사이즈를 기준으로 한다.
    • 중첩될 경우 크기가 기하급수적으로 커지는 부작용이 있어 폰트 크기 지정용으로는 적합하지 않다.

표로 정리하면,

단위기준 (Reference)특징추천 용도
px절대값 (화면)고정됨, 직관적테두리 두께, 그림자 등 고정된 값
rem<html> (Root)일관성 있음, 접근성 우수폰트 사이즈, 전체 레이아웃
em부모 요소중첩 시 계산 복잡함컴포넌트 내부 여백(padding 등)

em은 왜 padding에서 부모 폰트를 안 볼까?

많은 초보자가 “em은 부모 크기를 따라간다”고만 외운다. 그런데 막상 padding: 2em을 주면 부모 폰트가 아니라 자기 자신의 폰트 크기를 따라가서 혼란에 빠진다.

이유는 간단하다. 브라우저가 스타일을 계산하는 ‘순서(Time Line)’ 때문이다.

em의 진짜 정의: “현재 나의 폰트 사이즈”

원래 em은 무조건 **내 폰트 사이즈(Current Font Size)**를 의미한다. 부모가 아니다. 그런데 왜 font-size를 쓸 때만 부모를 볼까?

1단계: font-size 계산

브라우저가 내 font-size를 정하려고 할 때, 아직 내 크기가 정해지지 않았는 경우에만, 어쩔 수 없이 부모의 폰트 사이즈를 빌려와서 계산한다. 이게 우리가 “부모를 본다”고 느끼는 이유이다.

“너 폰트 크기 2em으로 한다고? em네 폰트 크기잖아. 근데 네 폰트 크기가 아직 없는데? 뭘 곱하라는 거야?”
👉 예외 발생! 아직 내 크기가 정해지지 않았을 때만, 어쩔 수 없이 부모의 폰트 사이즈를 빌려와서 계산한다.

2단계: padding, margin 계산

폰트 크기 계산이 끝났다. (예: 16px -> 32px로 확정) 이제 패딩을 계산할 차례다.

“너 패딩 1em 준다고? OK, 아까 네 폰트 32px로 정해졌지? 그럼 패딩은 32px!”

표로 정리하면,

속성em의 기준이유
font-size부모 폰트 크기아직 내 크기가 없어서 임시로 빌려옴
padding/margin나의 폰트 크기이미 내 크기가 정해졌으므로 내 껄 씀

실전 전략: 폰트는 rem, 여백은 em

실무에서는 각 단위의 장점만을 취해 다음과 같이 구분해서 사용하는 것이 국룰이다. 이 원리를 이용해 실무에서는 다음과 같이 단위를 구분해서 쓴다.

전략 1. 폰트 크기(font-size)는 무조건 rem

em을 폰트에 쓰면 상속 지옥(Snowball Effect)에 빠진다. 구조가 깊어질수록 글자가 기하급수적으로 커진다. 머리 쓰기 싫으면 폰트는 그냥 rem 써라.

전략 2. 컴포넌트 여백(padding)은 em

버튼을 예로 들어보자. 큰 버튼을 만들 때 폰트만 키우고 패딩은 그대로 두면 버튼이 뚱뚱해 보인다. 패딩에 em을 쓰면 폰트만 키워도 여백이 알아서 비율대로 늘어난다.

코드로 보는 예시

HTML
<!-- 1. 기본 버튼 -->
<button class="btn">기본 버튼</button>

<!-- 2. 큰 버튼 (클래스 추가) -->
<button class="btn large">왕 버튼</button>
CSS
.btn {
  /* 1. 폰트 크기는 rem으로 고정 (일관성) */
  font-size: 1.6rem; /* 16px 가정 */
  
  /* 2. 패딩은 em 사용 (비율 유지) */
  /* 여기서 1em은 현재 폰트인 16px을 의미함 */
  padding: 1em 2em; 
  /* -> 상하 16px, 좌우 32px */
}

.large {
  /* 3. 큰 버튼은 폰트만 키운다 */
  font-size: 3.2rem; /* 32px */
  
  /* padding을 따로 안 적어도 됨! */
  /* 왜? 폰트가 32px이 됐으니, 1em도 자동으로 32px이 됨 */
  /* -> 상하 32px, 좌우 64px로 자동 뻥튀기 */
}

이렇게 하면 .large 클래스 하나로 버튼의 모든 비례를 완벽하게 키울 수 있다.

고인물 꿀팁: 62.5% 세팅과 단위 없는 행간

마지막으로 개발 생산성을 2배 높여주는 국룰 세팅법이다.

62.5% 트릭 (계산기 갖다 버리기)

브라우저 기본 폰트(16px)를 그대로 쓰면 14px을 만들 때 0.875rem을 쳐야 한다. 계산하다가 날 샌다. html 폰트를 62.5%로 줄여서 기준을 10px로 맞추자.

HTML
html {
  font-size: 62.5%; /* 16px * 0.625 = 10px */
}
body {
  font-size: 1.6rem; /* 실제 본문은 16px로 복구 */
}

이제 십진법으로 편하게 코딩하면 된다.

  • 16px = 1.6rem
  • 24px = 2.4rem

line-height는 단위 없이 숫자만

줄 간격에는 단위를 붙이지 마라. 1.5em처럼 단위를 붙이면 부모의 고정된 픽셀 값이 상속되어, 자식 폰트가 커질 때 글자가 겹친다.

  • line-height: 1.5em; (비추천)
  • line-height: 1.5; (추천: 자식이 자기 폰트 크기에 맞춰 다시 계산함)

요약

오늘 다룬 내용을 한눈에 볼 수 있도록 정리했다. 이 표 하나만 기억해도 반응형 웹 코딩이 훨씬 쉬워진다.

구분추천 전략 / 사용법핵심 이유
폰트 크기rem 사용부모 영향 없이 일관된 크기 유지 (상속 지옥 방지)
여백 (Padding)em 사용글자가 커지면 여백도 비례해서 자동 조절 (비율 유지)
em의 기준font-size: 부모 기준
나머지: 내 크기 기준
내 폰트 크기가 먼저 정해져야 패딩 계산이 가능하므로
초기 세팅html { font-size: 62.5% }1rem = 10px로 계산을 직관적으로 만들기 위해
행간 (Line-height)단위 없이 숫자만 (예: 1.5)자식 요소가 자신의 폰트 크기에 맞춰 재계산하도록 함

이것만 지키면 반응형 웹 CSS 짜다가 스트레스받을 일은 90% 줄어든다. 오늘부터 px는 보내주자

관련 글