Logo

CSS 상대 단위 - em과 rem

반응형 웹디자인이 대두되면서 점점 많은 웹사이트들이 emrem라고 불리는 CSS 단위를 이용해서 스타일링이 되고 있습니다. 이번 포스팅에서는 emrem 단위가 실제로 브라우저에서 어떻게 동작하는지 정확히 알고 좀 더 적재적소에 사용하는 방법에 대해서 알아보도록 하겠습니다.

상대 단위란?

상대(relative) 단위란 고정되지 않고 어떤 기준에 따라서 유동적으로 바뀔 수 있는 길이를 나타내는 단위입니다. 본 포스팅에서 다룰 emrem을 포함해 %, vw, vh 등이 대표적인 CSS의 상대 단위입니다.

반면 절대(absolute) 단위는 어떤 상황에서든 항상 고정된 길이를 나타내는 단위입니다. 대표적으로 예전부터 현재까지 많이 사용되는 pxpt를 들 수 있고, cmin와 같은 실생활에서 많이 사용되는 단위들도 이 절대 단위에 범주에 속합니다.

쉽게 말해, 실생활에서 1cm가 항상 1cm인 것처럼, 1px는 항상 1px(=0.02645833cm)이지만, 1em이나 1rem은 항상 고정된 길이를 나타나지 않고 대신 브라우저가 어떤 기준에 따라 계산을 하여 px로 변환을 해줍니다. 따라서 그 기준이 무엇인지를 파악하는 것이 emrem을 정확히 이해하는데 핵심이 됩니다.

em과 rem의 공통점

뭐 적어도 pxpt와 같은 절대 단위를 쓰는 것 보다는 나을테니라는 생각으로 많은 분들이 emrem을 혼용해서 사용하시는 것 같습니다. 사실 브라우저에서 이 두 단위가 같은 길이로 계산될 때가 상당히 많고, 둘 중에 뭐를 쓰든 큰 차이가 나지 않아서 그럴 수도 있을 것입니다.

emrem은 둘 다 CCS의 font-size 속성값에 비례해서 결정되는 상대 단위입니다. 예를 들어, font-size: 16px인 경우, 상대 단위는 브라우저에 의해서 다음과 같이 계산됩니다.

  • 0.5em = 16 px x 0.5 = 8px
  • 1em = 16 px x 1 = 16px
  • 2em = 16 px x 2 = 32px
  • 3em = 16 px x 3 = 48px

여기서 font-size20px로 늘릴 경우, 상대 단위도 다음과 같이 비례해서 증가되게 됩니다.

  • 0.5em = 20 px x 0.5 = 10px
  • 1em = 20 px x 1 = 20px
  • 2em = 20 px x 2 = 40px
  • 3em = 20 px x 3 = 60px

반대로 font-size10px로 줄일 경우, 상대 단위도 다음과 같이 비례해서 감소되게 됩니다.

  • 0.5em = 10 px x 0.5 = 5px
  • 1em = 10 px x 1 = 10px
  • 2em = 10 px x 2 = 20px
  • 3em = 10 px x 3 = 30px

위와 font-size 값에 증감에 비례해서 유동적으로 길이가 결정되고 싶은 속성에 em이나 rem 단위를 사용해서 길이 지정을 해줄 수 있습니다.

em과 rem의 차이점

emrem 단위의 기준은 font-size 속성값이라고 했는데, 정확히 어디에 있는 font-size 속성값인지에 따라 차이가 발생합니다. em의 경우, 해당 단위가 사용되고 있는 요소의 font-size 속성값이 기준이 됩니다. 반면에 rem에서 rroot, 즉 최상위 요소를font-size 속성값 의미합니다. HTML에서 최상위 요소는 <html> 입니다. 따라서 rem 경우, html 요소의 font-size 속성값이 기준이 됩니다.

예를 들어, 다음과 같이 html 요소의 font-size 속성값이 16px이라고 가정해봅시다.

html {
  font-size: 16px;
}

그리고 다음과 같이 div 요소가 스타일링 된다면 width 속성의 값은 200px이 됩니다. 왜냐하면 em은 해당 요소의 font-size에 비례해서 커지기 때문에 div 요소의 font-size20px10을 곱해야 합니다.

div {
  font-size: 20px;
  width: 10em; /* 200px */
}

하지만 다음과 같이 em 대신에 rem 단위를 이용해서 div 요소가 스타일링 된다면 width 속성값은 160px이 됩니다. 왜냐하면 remhtml 요소의 font-size16px이기 때문에, 16px10을 곱해야 합니다.

div {
  font-size: 20px;
  width: 10rem; /* 160px */
}

다시 말해, rem 단위를 사용하면 해당 요소의 font-size 속성값은 전혀 중요하지 않게 됩니다.

font-size 상속괴 em 단위 계산

자 그럼 여기서 퀴즈! div 요소에서 font-size 속성을 제거하면 어떻게 될까요?

rem의 경우 원래부터 해당 요소의 font-size를 무시하기 때문에 달라질 게 없습니다.

div {
  width: 10rem; /* 160px */
}

하지만 em을 사용할 경우, 약간의 상상력이 필요합니다. 왜냐하면 없는 font-size 속성값을 고려해야 하기 떄문입니다. 어떤 요소에 font-size 속성이 정의되지 않은 경우 부모의 font-size 값을 그대로 상속받게 됩니다. 따라서, 아까 html 요소의 font-size16pxdiv 요소의 font-size 값이 되고, 결국 width: 10em 값은 16px * 10 = 160px로 계산됩니다.

div {
  width: 10em; /* 160px */
}

하지만 만약에 html 요소와 이 div 사이에 다른 요소들이 층층이 끼어 있으면 어떻게 될까요? (실제 이런 경우가 훨씬 많겠죠?) 예를 들어 header 요소가 이 둘 사이에 있고, 이 header 요소의 font-size30px이라면, 이 header 요소를 부모로 가지는 div 요소의 font-size도 상속이 되어 30px이되서 width 값을 300px로 만들 것입니다. 이건 그나마 난데, 만약 이 header 요소의 font-size가 절대 단위가 아닌 상대 단위를 사용하고 있다면 어떨까요? heaerfont-size2rem이라고 한다면 16px x 2 = 32px로 계산될 것이고, div 요소의 font-size32px이되서 최종적으로 width 값이 320px이 될 것입니다.

이 처럼, em을 사용할 때는 font-sizehtml 요소부터 시작해 여러 상위 요소들을 거치면서 상속될 수 있기 때문에 실제 어떤 값으로 계산될지 예측하기가 복잡할 때가 있습니다.

그럼 em과 rem 중 어떤 걸?

많은 CSS 가이드들이 em을 사용해야만 하는 타당한 이유가 없는 경우라면 가급적 rem을 우선적으로 쓰도록 권고하고 있습니다. (특히 초보자들에게…) 왜냐하면 em의 경우 위에서 보았듯이 실제 몇 px로 변환될지에 영향을 주는 변수가 많아지기 때문에, em을 사용해서 스타일된 요소의 경우 재사용이 어렵고 유지보수가 힘들어지는 경향이 있기 때문입니다.