CSS 상대 단위 - em과 rem
반응형 웹디자인이 대두되면서 점점 많은 웹사이트들이 em
과 rem
라고 불리는 CSS 단위를 이용해서 스타일링이 되고 있습니다.
이번 포스팅에서는 em
과 rem
단위가 실제로 브라우저에서 어떻게 동작하는지 정확히 알고 좀 더 적재적소에 사용하는 방법에 대해서 알아보도록 하겠습니다.
상대 단위란?
상대(relative) 단위란 고정되지 않고 어떤 기준에 따라서 유동적으로 바뀔 수 있는 길이를 나타내는 단위입니다. 본 포스팅에서 다룰 em
과 rem
을 포함해 %
, vw
, vh
등이 대표적인 CSS의 상대 단위입니다.
반면 절대(absolute) 단위는 어떤 상황에서든 항상 고정된 길이를 나타내는 단위입니다. 대표적으로 예전부터 현재까지 많이 사용되는 px
와 pt
를 들 수 있고, cm
나 in
와 같은 실생활에서 많이 사용되는 단위들도 이 절대 단위에 범주에 속합니다.
쉽게 말해, 실생활에서 1cm
가 항상 1cm
인 것처럼, 1px
는 항상 1px
(=0.02645833cm)이지만, 1em
이나 1rem
은 항상 고정된 길이를 나타나지 않고 대신 브라우저가 어떤 기준에 따라 계산을 하여 px
로 변환을 해줍니다. 따라서 그 기준이 무엇인지를 파악하는 것이 em
과 rem
을 정확히 이해하는데 핵심이 됩니다.
em과 rem의 공통점
뭐 적어도 px
나 pt
와 같은 절대 단위를 쓰는 것 보다는 나을테니라는 생각으로 많은 분들이 em
과 rem
을 혼용해서 사용하시는 것 같습니다.
사실 브라우저에서 이 두 단위가 같은 길이로 계산될 때가 상당히 많고, 둘 중에 뭐를 쓰든 큰 차이가 나지 않아서 그럴 수도 있을 것입니다.
em
과 rem
은 둘 다 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-size
를 20px
로 늘릴 경우, 상대 단위도 다음과 같이 비례해서 증가되게 됩니다.
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-size
를 10px
로 줄일 경우, 상대 단위도 다음과 같이 비례해서 감소되게 됩니다.
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의 차이점
em
과 rem
단위의 기준은 font-size
속성값이라고 했는데, 정확히 어디에 있는 font-size
속성값인지에 따라 차이가 발생합니다.
em
의 경우, 해당 단위가 사용되고 있는 요소의 font-size
속성값이 기준이 됩니다.
반면에 rem
에서 r
은 root
, 즉 최상위 요소를font-size
속성값 의미합니다. HTML에서 최상위 요소는 <html>
입니다.
따라서 rem
경우, html
요소의 font-size
속성값이 기준이 됩니다.
예를 들어, 다음과 같이 html
요소의 font-size
속성값이 16px
이라고 가정해봅시다.
html {
font-size: 16px;
}
그리고 다음과 같이 div
요소가 스타일링 된다면 width
속성의 값은 200px
이 됩니다.
왜냐하면 em
은 해당 요소의 font-size
에 비례해서 커지기 때문에 div
요소의 font-size
인 20px
에 10
을 곱해야 합니다.
div {
font-size: 20px;
width: 10em; /* 200px */
}
하지만 다음과 같이 em
대신에 rem
단위를 이용해서 div
요소가 스타일링 된다면 width
속성값은 160px
이 됩니다.
왜냐하면 rem
은 html
요소의 font-size
가 16px
이기 때문에, 16px
에 10
을 곱해야 합니다.
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-size
가 16px
가 div
요소의 font-size
값이 되고, 결국 width: 10em
값은 16px * 10 = 160px
로 계산됩니다.
div {
width: 10em; /* 160px */
}
하지만 만약에 html
요소와 이 div
사이에 다른 요소들이 층층이 끼어 있으면 어떻게 될까요? (실제 이런 경우가 훨씬 많겠죠?)
예를 들어 header
요소가 이 둘 사이에 있고, 이 header
요소의 font-size
가 30px
이라면, 이 header
요소를 부모로 가지는 div
요소의 font-size
도 상속이 되어 30px
이되서 width
값을 300px
로 만들 것입니다.
이건 그나마 난데, 만약 이 header
요소의 font-size
가 절대 단위가 아닌 상대 단위를 사용하고 있다면 어떨까요?
heaer
의 font-size
를 2rem
이라고 한다면 16px x 2 = 32px
로 계산될 것이고, div
요소의 font-size
도 32px
이되서 최종적으로 width
값이 320px
이 될 것입니다.
이 처럼, em
을 사용할 때는 font-size
가 html
요소부터 시작해 여러 상위 요소들을 거치면서 상속될 수 있기 때문에 실제 어떤 값으로 계산될지 예측하기가 복잡할 때가 있습니다.
그럼 em과 rem 중 어떤 걸?
많은 CSS 가이드들이 em
을 사용해야만 하는 타당한 이유가 없는 경우라면 가급적 rem
을 우선적으로 쓰도록 권고하고 있습니다. (특히 초보자들에게…)
왜냐하면 em
의 경우 위에서 보았듯이 실제 몇 px
로 변환될지에 영향을 주는 변수가 많아지기 때문에, em
을 사용해서 스타일된 요소의 경우 재사용이 어렵고 유지보수가 힘들어지는 경향이 있기 때문입니다.