Skip to content
블로그로 돌아가기
튜토리얼

px vs rem vs em: CSS 단위 완벽 비교 가이드

px vs rem vs em 비교: 각 CSS 단위의 의미, 접근성을 위해 rem을 쓰는 시점, em 중첩 함정, 속성별 결정표까지 온라인 가이드로 정리합니다.

12분 소요

px vs rem vs em: CSS 단위 완벽 비교 가이드

결론부터 말하면, 거의 모든 크기 지정에는 rem을 쓰세요. 글꼴 크기, 안쪽 여백, 바깥쪽 여백, 간격, 모서리 둥글기, 중단점이 다 여기 해당합니다. rem이 독자의 브라우저 글꼴 크기 설정에 맞춰 함께 확대되기 때문입니다. 1px 테두리나 정밀한 그림자 오프셋처럼 절대 확대되면 안 되는 소수의 값에는 px를 쓰세요. 버튼 텍스트에 맞춰 안쪽 여백이 함께 커져야 하는 경우처럼, 값이 요소 자신의 글꼴 크기를 따라 커져야 하는 드문 국소적 상황에는 em을 씁니다.

이 규칙이면 결정의 90%는 끝납니다. 문제는 나머지 10%에 숨어 있습니다. 누구나 처음 접하면 놀라는 em 복합 계산, 확대 시 레이아웃을 깨뜨리는 미디어 쿼리 버그, px가 오히려 더 접근성 높은 선택인 경우입니다. 아래에서 셋을 모두 다루고, 실행 가능한 CSS 예시와 함께 스타일을 작성하는 동안 옆에 띄워 둘 속성별 치트시트도 정리했습니다.

px, rem, em이 실제로 무엇을 의미하는가

세 단위는 기준점이 서로 다릅니다. 차이는 거기서 갈립니다.

px는 절대 단위입니다. 1px은 CSS 픽셀 하나이며, 주변에 무엇이 있든 그 크기를 유지합니다. border: 1px solid는 그냥 1픽셀입니다. 다만 “절대적”이라는 말은 사용자의 환경 설정도 무시한다는 뜻이기도 한데, 왜 그게 중요한지는 뒤에서 더 다룹니다.

rem루트 요소의 글꼴 크기를 기준으로 합니다. 루트는 <html>이며, 브라우저는 기본값으로 그 글꼴 크기를 16px로 설정합니다. 따라서 표준 설정에서는 페이지 어디에서든, 중첩 깊이와 무관하게 1rem16px과 같습니다. 이 일관성이 rem의 장점입니다. 기준값이 하나뿐이라 계산이 어긋날 일이 없습니다.

em현재 요소의 글꼴 크기를 기준으로 합니다(font-size가 아닌 속성의 경우 부모 요소 기준). 그 기준점이 요소를 중첩할수록 달라지기 때문에, em 값은 맥락에 따라 변합니다. 같은 1.5em이라도 어떤 곳에서는 24px로, 다른 곳에서는 30px로 계산될 수 있습니다.

외워 둘 기준값은 16px = 1rem입니다. 다른 건 다 잊어도 이것만은 머릿속에 새겨 두세요. 특정 값을 변환해야 할 때는 px → rem 변환기가 선택한 기준값에 맞춰 나눗셈을 처리해 줍니다.

px vs rem vs em 한눈에 보기

단위기준사용자 글꼴 크기에 맞춰 확대되는가?일반적 용도중첩 시 동작
px없음(절대)아니요테두리, 그림자 오프셋, 헤어라인항상 같은 크기
rem루트 <html> 글꼴 크기글꼴 크기, 간격, 중단점항상 같은 크기
em현재 요소의 글꼴 크기컴포넌트에 묶인 국소적 값복합됨, 어긋날 수 있음

대부분의 논쟁을 가르는 두 열은 “사용자 글꼴 크기에 맞춰 확대되는가”와 “중첩 시 동작”입니다. rem은 둘 다에서 앞섭니다. 독자의 환경 설정을 따르면서도 예측 가능하게 유지됩니다. em은 첫 번째 이점은 공유하지만 두 번째는 포기합니다.

각 단위는 어떻게 계산되는가

계산은 평범한 산수입니다. 사람들이 헷갈리는 부분은 어떤 숫자로 나누거나 곱하느냐입니다.

rem은 루트 글꼴 크기를 사용합니다.

rem = px ÷ root-font-size

기본 16px 루트에서는 24px ÷ 16 = 1.5rem입니다. 되돌리려면 곱하면 됩니다. 1.5rem × 16 = 24px. 페이지의 모든 rem이 같은 16(또는 루트로 설정한 값)을 쓰기 때문에 rem은 예측 가능합니다.

em은 현재 요소 자신의 글꼴 크기를 사용합니다.

em = px ÷ current-element-font-size

어떤 요소의 font-size20px이면, 그 요소에서 1em20px, 0.5em10px, 1.5em 안쪽 여백은 30px입니다. 요소의 글꼴 크기를 바꾸면 거기 붙은 모든 em 값이 함께 바뀝니다. 이 국소적 결합이 em의 핵심이면서 동시에 함정입니다.

em 복합 함정

다른 자료들이 대충 넘어가는 지점이 여기입니다. 글꼴 크기에 모두 em을 쓰는 요소들을 중첩하면 값이 트리를 따라 내려가며 곱해집니다. 각 단계가 부모의 계산된 글꼴 크기를 상속받고, 그 위에 자신의 em 배율을 적용하기 때문입니다.

.menu      { font-size: 1.2em; } /* 부모가 16px → 19.2px */
.menu .item { font-size: 1.2em; } /* 부모가 19.2px → 23.04px */
.menu .item .sub { font-size: 1.2em; } /* 부모가 23.04px → 27.648px */

각 단계가 “부모의 120%“라니 무해해 보입니다. 하지만 부모가 이미 커진 상태이기 때문에, 세 번째 단계는 원래의 16px 기준으로 1.2 × 1.2 × 1.2 = 1.728em, 즉 규칙만 따로 떼어 읽었을 때 짐작할 법한 19.2px이 아니라 약 27.6px이 됩니다. 컴포넌트 안의 목록 안에 또 목록을 중첩하면, 텍스트가 추적하기 어려운 방식으로 부풀어 오릅니다.

rem은 이 문제를 통째로 비껴갑니다. 1.2rem은 문서 맨 위에 있든 12단계 깊이에 있든 19.2px입니다. 부모가 아니라 항상 루트를 기준으로 측정하기 때문입니다. 어떤 값이 예상치 못한 크기로 계산되면 가장 먼저 그것이 em(부모 기준, 복합됨)인지 rem(루트 기준, 안정적)인지부터 확인하세요. rem 값을 디버깅하면서 픽셀 크기를 빠르게 확인하고 싶다면 rem → px 변환기로 바로 계산할 수 있습니다.

rem을 언제 사용하는가

기본적으로 rem을 선택하세요. 글꼴 크기, 안쪽 여백, 바깥쪽 여백, 간격, 모서리 둥글기, 미디어 쿼리 중단점 등 독자가 텍스트 크기를 조정할 때 함께 확대되어야 하는 모든 것에 적합한 단위입니다.

마지막 구절이 곧 접근성 논거인데, 이건 가정이 아닙니다. WebAIM의 스크린 리더 및 저시력 사용자 설문을 보면 상당수 사용자가 브라우저나 OS의 기본 글꼴 크기를 조정하고, 그중 많은 이가 표준 16px보다 훨씬 크게 설정합니다. rem으로 크기를 지정한 레이아웃은 그 변경을 따릅니다. 기본값을 20px로 올리면 rem 기반 값이 모두 비례해서 커집니다. px로 크기를 지정한 레이아웃은 이를 무시합니다. 독자가 아무리 크게 봐야 해도 텍스트는 하드코딩된 크기에 고정된 채 머뭅니다.

:root {
  font-size: 16px; /* 1rem = 16px */
}

h1   { font-size: 2rem;     } /* 32px, 사용자 환경 설정에 맞춰 확대됨 */
p    { font-size: 1rem;     } /* 16px */
.card { padding: 1.5rem;    } /* 24px */
.card { border-radius: 0.5rem; } /* 8px */

모든 값이 같은 루트에 묶여 있어서, 루트 글꼴 크기 하나만 바꾸면 인터페이스 전체가 비례해서 다시 조정됩니다. 디자인 시스템을 일관되게 유지하는 방법이기도 합니다. 간격과 타이포그래피가 따로 어긋나지 않고 함께 움직입니다.

62.5% 기법

rem 계산을 한결 쉽게 만드는 인기 있는 지름길이 있습니다. 루트 글꼴 크기를 62.5%로 설정하면 62.5% × 16px = 10px이 됩니다.

html {
  font-size: 62.5%; /* 이제 1rem = 10px */
}

body {
  font-size: 1.6rem; /* 읽기 좋은 16px 본문 텍스트로 복원 */
}

h1 { font-size: 2.4rem; } /* 24px */
p  { font-size: 1.6rem; } /* 16px */

10px 루트에서는 암산이 “픽셀 값을 10으로 나눈다”로 단순해집니다. 24px → 2.4rem, 12px → 1.2rem 식이죠. 한 가지 신경 쓸 점은 body { font-size: 1.6rem }으로 읽기 좋은 본문 크기를 복원하는 것입니다. 순수한 10px 기준으로는 기본 텍스트가 너무 작아지니까요. 10px 대신 62.5%를 백분율로 쓰면 상대성이 유지되므로, 브라우저 기본값을 키운 독자도 여전히 비례 확대를 누립니다. 이 기준을 채택한다면 변환기의 루트 글꼴 크기를 10으로 설정해 스타일시트와 맞추세요.

em을 언제 사용하는가

값이 루트가 아니라 요소 자신의 글꼴 크기에 맞춰 확대되기를 원할 때 em을 사용하세요. 대표적인 사례는 버튼입니다.

.btn {
  font-size: 1rem;      /* 루트 기준으로 크기 지정 */
  padding: 0.75em 1.5em; /* 안쪽 여백이 버튼 텍스트를 따라감 */
}

.btn--large {
  font-size: 1.25rem;   /* 한 번의 변경으로 전부 크기 조정 */
}

안쪽 여백이 em으로 지정돼 있어서, .btn--large 변형은 텍스트 안쪽 여백을 선언 하나로 함께 키웁니다. 버튼은 어떤 크기에서도 비례를 유지합니다. 텍스트 줄에 맞춰 따라가도록 em으로 크기를 지정한 아이콘이나, 글꼴에 맞춰 커져야 하는 자간에도 같은 논리가 적용됩니다.

실무에서는 전역 골격에 rem, 국소적 비례에 em을 쓰는 전략이 잘 통합니다. 글꼴 크기는 루트와 사용자 환경 설정에 응답하도록 rem으로 지정하고, 그 요소를 따라가야 하는 소수의 값만 em으로 지정하세요. 다만 깊게 중첩되는 곳에는 em을 쓰지 마세요. 앞서 본 복합 함정이 다시 슬그머니 돌아옵니다.

px를 언제 사용하는가

어떤 값들은 정말로 확대되면 안 되고, 그런 값에는 px가 맞습니다. 1px 헤어라인 테두리, 정밀한 box-shadow 오프셋, 2px 포커스 링이 그렇습니다. 이들은 콘텐츠가 아니라 렌더링 세부 사항입니다. 사용자가 텍스트를 키웠을 때 1.25px로 “확대”되는 테두리는 얻을 게 없고 오히려 흐릿한 선으로 렌더링될 수 있습니다. px는 그 선을 선명하게 유지합니다.

.divider { border-bottom: 1px solid; }     /* 1px로 유지되어야 함 */
.card    { box-shadow: 0 2px 4px rgba(0,0,0,0.1); } /* 고정 오프셋 */
.input:focus { outline: 2px solid; }       /* 선명한 포커스 링 */

의외의 미묘함: px가 더 접근성 높을 때

대부분의 “무조건 rem” 식 조언이 건너뛰는, 직관에 반하는 부분이 여기 있습니다. 접근성 있는 선택은 “어디에나 rem”이 아니라 “확대돼야 할 것은 확대하고, 그러지 말아야 할 것은 고정한다”입니다.

1px 테두리는 고정된 세부 사항입니다. 사용자가 텍스트를 키울 때 함께 커지도록 rem으로 강제해 봐야 가독성에 도움이 되지 않고 헤어라인만 흐려집니다. 이런 속성에는 px가 더 접근성 높은 선택입니다. 제자리에 머물러야 하니까요.

사람들이 실제로 저지르는 실수는 그 반대입니다. 글꼴 크기나 중단점처럼 응답해야 할 것에 px를 쓰는 것이죠. 그게 px가 접근성을 해치는 지점입니다. 결국 핵심은 단위가 아니라 속성입니다. 그 값이 독자가 상호작용하는 콘텐츠인지(확대 → rem), 아니면 고정된 렌더링 세부 사항인지(고정 → px)를 따져 보면 단위는 그 답을 따라옵니다.

미디어 쿼리 함정

이 문제는 실제로 레이아웃을 깨뜨리는데도 경고하는 가이드가 거의 없습니다. px로 작성한 미디어 쿼리 중단점은 기대만큼 브라우저의 글꼴 크기 확대에 응답하지 않습니다.

사이드바가 접히는 width: 600px 중단점을 떠올려 보세요. 시력이 약한 사용자가 편하게 읽으려고 브라우저 기본값을 24px로 설정합니다. 이제 콘텐츠에 가로 공간이 더 필요하고, 커진 텍스트는 더 일찍 줄바꿈하려 합니다. 하지만 px 중단점은 텍스트가 커진 걸 알지 못한 채 여전히 정확히 뷰포트 600px에서 전환되므로, 레이아웃이 엉뚱한 시점에 바뀌고 콘텐츠가 비좁아지거나 겹칩니다.

두 접근법을 비교해 보세요.

/* px 중단점 — 사용자의 글꼴 크기 환경 설정을 무시함 */
@media (min-width: 600px) {
  .sidebar { display: block; }
}

/* em/rem 중단점 — 사용자의 글꼴 크기에 응답함 */
@media (min-width: 37.5em) {
  .sidebar { display: block; }
}

37.5em은 기본 16px에서 600px입니다(600 ÷ 16 = 37.5). 차이는 동작에 있습니다. 사용자가 기본 글꼴 크기를 두 배로 키우면 em 중단점도 사실상 두 배가 되므로, 콘텐츠가 더 넓은 공간을 필요로 하는 바로 그 시점에 레이아웃이 전환됩니다. px 중단점은 그대로 멈춰 있습니다.

알아 둘 만한 특이점이 하나 있습니다. 미디어 쿼리 조건 안에서는 emrem이 둘 다 html 재정의가 아니라 브라우저 기본 글꼴 크기를 기준으로 계산되므로, 여기서는 동일하게 동작합니다. 어느 쪽을 쓰든 버그가 사라지고, 버그를 일으키는 건 px입니다.

속성별 결정표

확신이 서지 않을 때는 이 표를 보면 됩니다. 매번 논리를 다시 따지지 않고 판단하는 가장 빠른 방법입니다.

속성권장 단위이유
font-sizerem사용자의 글꼴 크기 환경 설정에 맞춰 확대됨
padding / marginrem간격이 텍스트와 함께 확대됨
borderpx헤어라인은 선명하고 고정되어야 함
box-shadow 오프셋px콘텐츠가 아닌 정밀한 렌더링 세부 사항
border-radiusrem모서리 둥글기를 확대에 비례하게 유지
미디어 쿼리em / rem중단점은 글꼴 크기 확대에 응답해야 함
width / max-widthrem(텍스트는 종종 ch)확대 가능한 레이아웃 너비, ch는 줄 길이 제한
line-height단위 없음단위 없는 배율은 올바르게 상속됨

line-height 행은 흔한 버그라 따로 짚어 둡니다. 항상 단위 없이 line-height: 1.5로 쓰세요. 단위 없는 값은 각 요소가 자신의 글꼴 크기를 기준으로 계산하는 배율이라, 중첩된 요소도 읽기 좋게 유지됩니다. 반대로 line-height: 1.5em이나 24px로 쓰면 계산된 길이가 상속되고, 그러면 글꼴이 더 큰 자식이 부모의 줄 높이를 그대로 물려받아 텍스트가 겹치기 시작합니다. 단위 없는 값은 이 문제 자체를 피해 갑니다.

px와 rem 사이 변환

16px = 1rem이라는 기준값만 잡으면 계산은 암산으로 충분할 만큼 단순합니다. rem으로 가려면 16으로 나누고, px로 되돌리려면 16을 곱하세요.

pxrem (16px 기준)
8px0.5rem
12px0.75rem
16px1rem
24px1.5rem
32px2rem

62.5% 기법을 쓰면 기준이 10px이 되어 계산이 한층 더 간단해집니다. 10으로 나누거나 곱하면 되니 24px = 2.4rem이죠. 규칙은 하나, 스타일시트가 실제로 설정한 기준값에 맞춰 변환하는 것입니다.

그 밖의 경우, 즉 어중간한 값이나 사용자 지정 루트, Figma 내보내기 일괄 변환 같은 상황에서는 암산을 건너뛰고 px → rem 변환기rem → px 변환기를 쓰세요. 둘 다 루트 글꼴 크기를 원하는 대로 설정할 수 있고 양방향으로 실시간 변환합니다. 이어서 단위가 뒤섞인 스타일시트를 정리한다면 CSS 포매터로 간격과 들여쓰기를 정돈할 수 있습니다.

흔한 실수

단위 때문에 생기는 골칫거리는 대부분 몇 가지 패턴에서 나옵니다.

루트 글꼴 크기를 px로 설정하기. html { font-size: 16px }처럼 쓰면(기본값을 두거나 100%/백분율을 쓰는 대신) 사용자의 브라우저 글꼴 크기 환경 설정을 통째로 재정의해 버립니다. rem 값은 여전히 그것을 기준으로 계산되지만, 독자는 더 이상 페이지 전체를 확대할 수 없습니다. 루트는 기본값으로 두거나 백분율을 쓰세요.

px와 rem을 체계 없이 섞기. 일부 글꼴 크기는 px로, 일부는 rem으로, 간격은 둘 사이에 나뉘어 있으면 사용자가 텍스트를 조정할 때 레이아웃이 고르지 않게 확대됩니다. rem을 기본으로 정하고, 결정표에 있는 의도적 예외에만 px를 남겨 두세요.

전역 간격에 em 쓰기. 널리 중첩되는 컨테이너에 em을 쓰면 복합 함정이 되살아나, 트리 깊숙한 곳의 padding이 아무도 의도하지 않은 값으로 계산됩니다. 전역 간격은 rem으로 유지하고, em은 국소적이고 컴포넌트 범위의 값에만 쓰세요.

line-height에 단위 붙이기. 위에서 다뤘듯 line-height: 24px이나 1.5em은 계산된 길이로 상속되어 글꼴 크기가 다른 요소에서 깨집니다. 항상 단위 없는 배율을 쓰세요.

FAQ

rem이 px보다 나은가요?

대부분의 크기 지정에서는 그렇습니다. rem은 px가 무시하는 사용자의 브라우저 글꼴 크기 환경 설정에 맞춰 확대되므로 px보다 낫습니다. 다만 “낫다”는 것은 속성에 따라 다릅니다. 선명하게 유지되어야 하는 1px 테두리나 그림자 오프셋 같은 고정 세부 사항에는 px가 옳은 선택입니다. 콘텐츠 크기에는 rem을, 렌더링 세부 사항에는 px를 쓰세요.

1rem은 픽셀로 얼마인가요?

1rem은 루트 글꼴 크기를 픽셀로 나타낸 값과 같으며, 거의 모든 브라우저에서 기본값은 16px입니다. 따라서 표준 설정에서 1rem = 16px, 1.5rem = 24px, 2rem = 32px입니다. 스타일시트가 html { font-size }를 재정의하면(예: 62.5% 기법으로 10px로) 1rem은 대신 그 값과 같아집니다.

font-size에는 rem과 em 중 무엇을 써야 하나요?

거의 모든 경우 font-size에는 rem을 쓰세요. rem은 루트를 기준으로 측정하므로, 요소가 아무리 깊게 중첩돼도 예측 가능하게 유지됩니다. em은 부모의 글꼴 크기를 기준으로 측정하는데, 트리를 따라 복합되어 중첩된 텍스트를 예상치 못하게 부풀립니다. em은 단일 컴포넌트에 묶인 국소적 값에만 남겨 두세요.

rem 대신 px를 언제 써야 하나요?

사용자의 글꼴 크기에 맞춰 확대되면 안 되는 값에 px를 쓰세요. 1px 테두리, 정밀한 box-shadow 오프셋, 포커스 링 외곽선, 그 밖의 고정 렌더링 세부 사항입니다. 이들은 콘텐츠가 아니라 선명해야 하는 디자인 세부 사항이라, px로 고정하는 편이 더 접근성 높은 선택입니다. 콘텐츠와 관련된 값에는 여전히 rem을 쓰세요.

px를 쓰면 미디어 쿼리가 왜 깨지나요?

px로 작성한 미디어 쿼리 중단점은 브라우저의 글꼴 크기 확대에 응답하지 않습니다. 사용자가 기본 글꼴을 키우면 콘텐츠에 더 많은 공간이 필요하지만, px 중단점은 여전히 같은 뷰포트 너비에서 전환되므로 레이아웃이 엉뚱한 시점에 바뀝니다. 사용자의 글꼴 크기에 맞춰 확대되는 em이나 rem 중단점을 쓰세요.

62.5% 글꼴 크기 기법이 무엇인가요?

62.5% 기법은 html { font-size: 62.5% }로 설정해 루트 글꼴 크기를 10px(16의 62.5%)로 만드는 것입니다. 10px 기준에서는 rem 계산이 “10으로 나누기”가 됩니다. 24px = 2.4rem, 12px = 1.2rem처럼요. 그런 다음 개발자는 body { font-size: 1.6rem }을 설정해 읽기 좋은 16px 본문 텍스트를 복원합니다.

px, rem, em을 섞어 써도 괜찮나요?

괜찮습니다. 각 단위가 자신에게 맞는 속성을 따른다면 px, rem, em을 섞어 쓰는 게 맞습니다. 타이포그래피와 간격에는 rem, 고정 세부 사항에는 px, 국소적이고 컴포넌트 범위의 값에는 em을 쓰는 식이죠. 문제는 체계 없이 섞을 때, 이를테면 일부 글꼴 크기는 px로 일부는 rem으로 쓸 때 생깁니다. rem을 기본으로 정하고 px와 em은 의도적 예외로 다루세요.

padding과 margin에는 어떤 단위를 써야 하나요?

사용자가 글꼴 크기를 조정할 때 간격이 텍스트와 함께 확대되도록 padding과 margin에는 rem을 쓰세요. 그래야 레이아웃이 비례를 유지하고 접근성도 좋아집니다. 텍스트에 맞춰 안쪽 여백이 커지는 버튼처럼 요소 자신의 글꼴 크기를 따라가야 하는 안쪽 여백에는 em을 남겨 두되, 복합이 일어나는 깊게 중첩된 컨테이너에는 em을 피하세요.

태그: css rem em frontend accessibility responsive-design