웹 개발의 끊임없이 진화하는 세계에서 유연하고 응답 가능하며 접근성 있는 디자인을 만드는 것은 중요합니다. 개발자의 CSS 도구상에서 가장 강력한 도구 중 하나는 상대적 단위의 사용입니다. 이러한 단위를 사용하면 디자인을 보다 유연하고 응답 가능하게 만들 수 있습니다. 이 글에서는 상대적 단위의 세계에 깊이 파고들어 효과적인 사용 방법과 현대 웹 개발에서 왜 중요한지 살펴볼 것입니다.
왜 중요한가요?
구체적인 내용에 대해 파헤치기 전에 현대 웹 개발에서 상대적 단위가 왜 중요한지에 대해 알아봅시다:
- 응답성: 상대적 단위는 응답형 디자인의 핵심이며 요소가 다양한 기기 크기에 맞게 유동적으로 확장되도록 합니다.
- 접근성: 글꼴 크기에 상대적 단위를 사용하면 사용자가 브라우저의 기본 글꼴 크기를 조정할 때 텍스트가 가독성 있게 유지됩니다.
- 유지보수성: 상대적 단위를 사용하면 전역 레이아웃 변경 시 수십 개의 하드코딩된 픽셀 값을 업데이트하는 대신 몇 가지 값만 업데이트하면 됩니다.
- 일관성: 상대적 단위를 사용하면 전반적인 비율이 변해도 요소 간 비율적 관계를 유지할 수 있습니다.
함께 다양한 상대 단위 유형을 탐색해 봅시다.
Ems 및 Rems
가장 일반적으로 사용되는 상대 단위는 em 및 rem입니다. 둘 다 글꼴 크기를 기준으로 하지만 중요한 면에서 다르게 작동합니다.
Ems 이해하기
em은 사용된 요소의 글꼴 크기에 대한 상대적인 단위입니다. 자세한 예시를 보여드리겠습니다:
.parent {
font-size: 16px;
}
.child {
font-size: 1.5em; /* 24px (16px * 1.5) */
padding: 1em; /* 24px */
border-radius: 0.25em; /* 6px */
}
이 예시에서 모든 자식 요소의 속성은 해당 자체 글꼴 크기에 상대적입니다. 이렇게 함으로써 글꼴 크기가 변하는 경우 모든 속성이 크기에 맞게 조정되는 확장 가능한 구성 요소가 생성됩니다.
일반적으로 em은 글꼴 크기를 설정하는 데 사용되지만 위 예시에서 보았듯이 그 잠재력은 그 이상으로 확장됩니다. em을 사용하여 요소의 많은 속성을 정의한 다음 글꼴 크기를 하나 변경함으로써 전체 요소를 쉽게 확대 또는 축소할 수 있습니다. 이러한 유연성으로 인해 em은 글꼴 뿐만 아니라 다양한 속성에 매우 유용하게 사용됩니다.
잠재적인 함정
Ems를 중첩 요소의 글꼴 크기를 정의하는 데 사용할 때 복잡해질 수 있습니다. 예시를 살펴보겠습니다:
<section>
<ul>
<li>First level item</li>
<ul>
<li>Second level item</li>
<ul>
<li>Third level item</li>
<ul>
<li>Fourth level item</li>
</ul>
</ul>
</ul>
</ul>
</section>
이제 em을 사용한 CSS를 적용해보겠습니다:
section {
font-size: 16px;
}
ul {
font-size: 0.9em;
}
이렇게 하면 다음과 같은 결과가 나타납니다:

각 레벨에서 무슨 일이 일어나는지 살펴보겠습니다:
- 첫 번째 수준 - 글꼴 크기: 0.9em의 16px = 14.4px
- 두 번째 수준 - 글꼴 크기: 0.9em의 14.4px = 12.96px
- 세 번째 수준 - 글꼴 크기: 0.9em의 12.96px = 11.66px
- 네 번째 수준 - 글꼴 크기: 0.9em의 11.66px = 10.50px
각 중첩 레벨마다 글꼴 크기가 점점 작아지는 것을 확인할 수 있습니다. 이 중첩 효과는 깊게 중첩된 구조에서 텍스트가 읽기 어렵게 되는 결과를 초래할 수 있습니다. 이는 디자인 요구 사항에 따라 특징이자 잠재적인 함정입니다.
렘: 루트 에름
em과 관련된 중첩 문제를 피하기 위해 rem 단위가 있습니다. 이것들은 항상 루트 요소인 html
요소의 글꼴 크기(보통 16px)에 대해 상대적입니다.
다음 예시들을 위해 현재 루트 요소의 글꼴 크기가 16px인 것으로 가정해봅시다:
.deeply-nested-element {
font-size: 1.5rem; /* 중첩 여부에 관계없이 항상 24px로 유지됩니다. */
padding: 1rem; /* 항상 16px로 유지됩니다. */
margin: 0.5rem; /* 항상 8px로 유지됩니다. */
}
Rem은 문서 전반에 걸쳐 일관성을 제공하여 글꼴 크기 및 다른 많은 속성에 이상적입니다!
실용적인 예시
em과 rem을 조합하여 멋지게 확장되는 접근성 있는 버튼 구성요소를 만들어봅시다:
.button {
font-size: 1rem; /* 16px (또는 사용자가 설정한 선호 크기) */
padding: .5em 1em; /* 8px 16px, em을 사용하여 현재 요소의 폰트 크기와 함께 확장 */
border-radius: .25em; /* 4px */
transition: font-size .3s ease, padding .3s ease, border-radius .3s ease;
}
@media (prefers-reduced-motion: no-preference) {
.button:hover {
font-size: 1.1rem; /* 호버 시 17.6px로 증가합니다 */
}
}
이 예제에서는 사용자가 HTML 문서의 글꼴 크기를 변경하는 경우 버튼의 패딩(padding)과 테두리 반경(border-radius)이 비례적으로 조정됩니다 :)
Viewport-Relative Units
Ems와 rems가 매우 유용하지만 때로는 뷰포트(화면) 크기에 상대적인 단위가 필요합니다. 바로 뷰포트 상대적 단위(viewport-relative units)입니다:
- vw: 뷰포트 너비의 1%
- vh: 뷰포트 높이의 1%
- vmin: 더 작은 차원(너비 또는 높이)의 1%
- vmax: 더 큰 차원(너비 또는 높이)의 1%
이러한 단위는 전체화면 레이아웃을 만들거나 뷰포트 크기에 비례하여 극적으로 확대되어야 하는 요소들을 만드는 데 특히 유용합니다.
.hero-section {
height: 100vh;
width: 100vw;
/* ... */
}
.hero-section-image {
width: 50vmin;
height: 50vmin;
object-fit: cover;
/* ... */
}
이 코드는 뷰포트 크기를 기준으로 크기가 조정되는 콘텐츠를 가진 전체 높이의 히어로 섹션을 만들며, 이미지는 항상 정사각형이 되고 더 작은 뷰포트 차원의 절반을 차지하도록합니다.
이 유닛들은 훌륭하지만 데스크톱 브라우저를 기준으로 설계되어 있어서 사용자가 창 크기를 수동으로 조절하지 않는 한 뷰포트 크기가 일정합니다. 모바일에서는 이야기가 좀 달라집니다.
모바일 뷰포트의 동적 성격
많은 모바일 브라우저들은 사용자 상호작용에 따라 브라우저의 UI 요소인 주소 표시줄이나 네비게이션 버튼과 같은 요소들이 나타나거나 사라지는 사용자 경험 기능을 구현합니다. 일반적인 작동 방식은 다음과 같습니다:
- 사용자가 페이지를 처음로드할 때, 이러한 UI 요소들이 보이며 뷰포트 높이가 감소합니다.
- 사용자가 페이지를 아래로 스크롤할 때 이들 요소는 종종 보이지 않게 되며 뷰포트 높이가 효과적으로 증가합니다.
- 사용자가 다시 위로 스크롤하거나 화면 상단 부근을 탭하면, 다시 보이게 되며 뷰포트 높이가 다시 감소합니다.
이 동적 동작은 뷰포트 크기가 변동적으로 변하므로 vh(오버레이, 사이드바 등에 사용되는 뷰포트 상대 단위)와 같은 뷰포트 상대 단위를 사용할 때 레이아웃 문제가 발생할 수 있습니다.
동적 뷰포트 단위 입력
이러한 문제를 해결하기 위해 새로운 뷰포트 단위가 소개되었습니다:
- svh (작은 뷰포트 높이): 모바일 브라우저 UI 요소가 표시될 때 뷰포트 높이를 나타냅니다.
- lvh (큰 뷰포트 높이): 모바일 브라우저 UI 요소가 숨겨질 때 뷰포트 높이를 나타냅니다.
- dvh (동적 뷰포트 높이): 브라우저 UI 요소가 나타나거나 사라질 때 svh와 lvh 사이를 동적으로 조절합니다.
아래 예시를 고려해 보세요:
.side-menu {
height: 100dvh;
}
이 요소는 현재 모바일 브라우저 UI 요소의 상태에 따라 높이가 동적으로 조정되어 사용자 경험이 일관성 있게 유지됩니다 👍.
인라인 / 블록 논리 속성
완전성을 확보하기 위해, 추가로 언급해야 할 단위 유형 세트가 있습니다: 인라인 및 블록입니다. 이를 "논리 속성"이라고 합니다. 이들은 너비와 높이와 유사하게 작동하지만 몽골어와 같은 수직으로 쓰인 언어에 적합하도록 설계된 논리적인 속성입니다. 이들은 vi, vb, svi, svb, lvi, lvb, dvi, dvb입니다.
브라우저 지원 및 대체 방법
동적 뷰포트 단위에 대한 지원은 글을 작성할 당시 93.21%입니다. 그러나 더 오래된 브라우저를 대상으로 한다면 대체 방법을 제공하는 것이 좋습니다.
.modal {
height: 100vh; /* vh를 지원하지 않는 브라우저를 위한 대체값 */
height: 100dvh; /* 이를 지원하는 브라우저에서 사용됨 */
}
단위 결합
calc 함수 사용
calc() 함수는 반응형 디자인에 있어서 게임 체인저입니다. 이 함수를 사용하면 다양한 단위로 기본 수학 연산을 수행할 수 있어 유연한 레이아웃을 만드는 것이 쉬워집니다. 다음은 알아야 할 내용입니다.
- 덧셈(+), 뺄셈(-), 곱셈(*), 나눗셈(/)을 지원합니다
- 연산자 주변에 항상 공백을 추가해주세요
예시:
p {
font-size: calc(0.5em + 1svw);
}
이 예시에서는 폰트 크기가 뷰포트 너비에 따라 조절되지만 0.5rem보다 작아지지는 않습니다.
clamp 함수 사용하기
clamp() 함수는 이 개념을 더 나아가서 최소값과 최대값을 설정할 수 있는 선호값을 지정할 수 있게 해줍니다. clamp() 함수는 세 가지 인수를 취합니다:
- 최소값
- 선호값 (식일 수 있습니다)
- 최대값
다음 예시를 살펴보세요:
h1 {
font-size: clamp(1em, 5vw, 6em);
}
이렇게 하면 뷰포트 너비에 맞게 크기가 조절되지만 1em보다 작거나 6em보다 크지는 않습니다.
다른 유용한 함수 사용하기
- min(): 여러 값 중 가장 작은 값을 선택합니다 예시: width: min(200px, 20svw);
- 예시: width: min(200px, 20svw);
- max(): 여러 값 중 가장 큰 값을 선택합니다 예시: min-height: max(200px, 20svw);
- 예시: min-height: max(200px, 20svw);
모두 마무리
CSS에서 상대 단위를 마스터하면 유연하고 접근성 있는 디자인을 만들 수 있어요. em, rem, 뷰포트 단위의 미묘한 차이를 이해하고 효과적으로 결합하는 방법을 알면 화면 크기와 사용자 선호에 맞게 레이아웃을 원활하게 조절할 수 있어요.
dvh와 같은 동적 뷰포트 단위의 등장은 모바일 브라우저의 독특한 도전에 웹 디자인을 맞추는 중요한 진전이에요. 이러한 단위를 사용하면 모바일 뷰포트의 동적 특성을 처리하는 반응형 레이아웃을 만들 수 있어요.
하지만 목표는 픽셀을 완전히 없애는 것이 아니라, 분별력 있게 사용하는 것이에요. 픽셀과 같은 절대 단위는 여전히 그 자리에 있어요, 특히 테두리나 픽셀 완벽한 제어가 필요할 때에요. 중요한 것은 상대적인 단위를 유연성을 위해 언제 사용해야 하고, 정밀도를 위해 언제 절대 단위를 사용해야 하는지를 아는 것이에요.
다음 프로젝트나 다음 UI를 구축할 때 가능한 경우 상대적 단위를 사용해 보세요. 스타일시트가 더 간결해지고 레이아웃이 유연해지며 전체적인 디자인이 다양한 기기와 사용자 설정에 걸쳐 더 견고해질 것입니다.
다음에 또 만나요! 즐거운 코딩 되세요!