웹 페이지가 이상하게 보일 때가 있습니다. 버튼이 너무 크거나, 박스가 갑자기 줄을 바꾸고, 글자가 상자 밖으로 삐져나오기도 하죠. 이럴 때 원인을 찾는 핵심은 딱 두 가지입니다. 얼마나 크게 만들었는가와 어떻게 흐르도록 두었는가입니다.
이번 장에서는 CSS에서 자주 쓰는 크기 단위인 px, %, em, rem, vw, vh를 익히고, display와 overflow가 화면에 어떤 영향을 주는지 차근차근 살펴보겠습니다. 여기까지 이해하면 "왜 저 요소가 저렇게 보이지?"라는 질문에 꽤 자신 있게 답할 수 있게 됩니다.
크기를 정하는 단위부터 이해하자
CSS에서 크기는 숫자만 적는 것이 아니라 숫자 + 단위로 적는 경우가 많습니다. 예를 들어 width: 200px;처럼 말이죠. 단위는 기준점이 무엇인지 알려줍니다. 어떤 단위는 고정된 느낌으로 동작하고, 어떤 단위는 부모나 화면 크기에 따라 유연하게 변합니다.1
처음 배우는 단계에서는 이렇게 기억하면 충분합니다.
px: 비교적 고정된 크기%: 부모를 기준으로 한 비율em: 글자 크기를 기준으로 커지는 단위rem: 문서 전체의 기본 글자 크기를 기준으로 한 단위vw,vh: 브라우저 화면 크기를 기준으로 한 단위
이제 하나씩 만나보겠습니다.
px: 가장 직관적인 기본 단위
px는 픽셀 단위입니다. 초보자에게 가장 이해하기 쉬운 단위죠. 100px이면 대체로 "가로 100만큼"이라고 생각하면 됩니다. 그래서 테두리, 작은 아이콘, 정확한 크기가 필요한 버튼 높이 같은 곳에 많이 사용합니다.1
.box {
width: 200px;
height: 100px;
}이 코드는 박스를 가로 200, 세로 100 크기로 만듭니다. 장점은 예측하기 쉽다는 것입니다. 단점은 너무 많이 쓰면 화면 크기가 달라져도 유연하게 반응하지 않는다는 점입니다.
예를 들어 작은 모바일 화면에서도 400px짜리 박스는 꽤 크게 느껴질 수 있습니다. 그래서 px는 좋지만, 언제나 정답은 아닙니다.
%: 부모를 바라보는 단위
%는 부모 요소를 기준으로 계산되는 비율입니다. width: 50%;라고 쓰면, 내 부모 너비의 절반만 차지합니다.12
.container {
width: 400px;
border: 2px solid #333;
}
.child {
width: 50%;
background-color: tomato;
}<div class="container">
<div class="child">나는 부모의 절반 너비</div>
</div>위 코드에서 .child는 400px의 절반인 200px 너비가 됩니다.
여기서 중요한 점이 하나 있습니다. %는 자기 마음대로 커지는 것이 아니라, 항상 부모를 쳐다본다는 점입니다. 그래서 부모가 작아지면 자식도 작아지고, 부모가 커지면 자식도 커집니다. 반응형 화면에서 아주 자주 쓰이는 이유가 바로 이것입니다.
em: 글자 크기를 따라 움직이는 단위
em은 처음엔 조금 헷갈리지만, 익숙해지면 꽤 유용합니다. 핵심은 글자 크기와 연결되어 있다는 것입니다. 보통 부모의 글자 크기를 기준으로 생각하면 이해가 쉽습니다. 예를 들어 부모의 font-size가 16px일 때 2em은 32px처럼 계산됩니다.12
.card {
font-size: 16px;
}
.card-title {
font-size: 2em;
}이 경우 .card-title의 글자 크기는 32px이 됩니다.
em이 좋은 이유는 요소 안에서 비례를 맞추기 쉽기 때문입니다. 예를 들어 버튼 글자가 커지면 안쪽 여백도 함께 커지게 만들 수 있습니다.
.button {
font-size: 1em;
padding: 0.5em 1em;
}글자가 커지면 패딩도 같이 커집니다. 그래서 "이 버튼은 글자와 함께 자연스럽게 커졌으면 좋겠다" 같은 상황에 잘 어울립니다.
다만 중첩되면 계산이 점점 커질 수 있습니다. 부모, 자식, 손자 요소가 모두 em을 쓰면 생각보다 커지는 일이 생길 수 있으니 주의가 필요합니다.2
rem: 전체 기준이 하나로 통일되는 단위
rem은 root em의 줄임말입니다. 여기서 root는 문서의 루트 요소인 html입니다. 즉, rem은 문서 전체의 기본 글자 크기를 기준으로 계산됩니다.12
브라우저 기본값이 보통 16px이라면:
1rem= 16px1.5rem= 24px2rem= 32px
html {
font-size: 16px;
}
h1 {
font-size: 2rem;
}
p {
font-size: 1rem;
}rem의 장점은 예측 가능하다는 점입니다. 어디에 넣든 기준이 같기 때문에, 큰 사이트나 여러 컴포넌트가 있는 화면에서 특히 편합니다. 글자 크기, 여백, 버튼 크기를 일정한 기준으로 맞추고 싶다면 rem이 아주 든든합니다.2
초보자 기준으로는 이렇게 정리하면 좋습니다. 박스 안에서 글자와 함께 비례해서 커졌으면 em, 사이트 전체에서 통일감 있게 크기를 맞추고 싶으면 rem입니다.
vw와 vh: 화면 크기를 기준으로 잡는 단위
vw와 vh는 브라우저 화면, 즉 뷰포트(viewport)를 기준으로 계산됩니다. 1vw는 화면 너비의 1%, 1vh는 화면 높이의 1%입니다.12
.hero {
width: 100vw;
height: 100vh;
}이 코드는 화면 전체를 꽉 채우는 영역을 만들 때 자주 보입니다. 랜딩 페이지의 첫 화면, 큰 배너, 환영 섹션 같은 곳에서 많이 씁니다.
여기서 %와 헷갈리기 쉽습니다.
50%는 부모의 절반이고, 50vw는 화면 너비의 절반입니다. 부모가 작더라도 50vw는 부모가 아니라 화면을 기준으로 움직입니다.1
그래서 작은 카드 안의 요소에 50vw를 주면 생각보다 너무 커질 수 있습니다. "부모 기준인가, 화면 기준인가?"를 꼭 따져야 합니다.
어떤 단위를 언제 쓰면 좋을까
단위는 싸우는 관계가 아니라 역할이 다른 도구입니다. 망치와 드라이버처럼요.
초보자에게 추천하는 감각적인 기준은 이렇습니다.
정확한 테두리나 작은 고정 요소는
px부모 너비에 맞춰 유연하게 줄고 늘어나는 것은
%글자 크기와 함께 비례해야 하는 내부 간격은
em전체 사이트 기준으로 통일감 있게 쓰는 글자와 여백은
rem화면 자체를 기준으로 잡는 큰 영역은
vw,vh
처음부터 완벽하게 고를 필요는 없습니다. 중요한 건 "무엇을 기준으로 삼을지"를 의식하는 것입니다.
예제로 보는 단위 차이
아래 예제를 보면 각 단위의 성격이 훨씬 잘 보입니다.
<div class="parent">
<div class="box px-box">200px</div>
<div class="box percent-box">50%</div>
<div class="box rem-box">10rem</div>
<div class="box vw-box">50vw</div>
</div>html {
font-size: 16px;
}
.parent {
width: 400px;
border: 2px solid #333;
padding: 16px;
}
.box {
margin-bottom: 12px;
background: #dbeafe;
border: 1px solid #60a5fa;
}
.px-box {
width: 200px;
}
.percent-box {
width: 50%;
}
.rem-box {
width: 10rem;
}
.vw-box {
width: 50vw;
}이 예제에서:
200px는 항상 비슷한 크기입니다.50%는 부모 400px의 절반 정도로 계산됩니다.10rem은 루트 글자 크기 기준이라 160px입니다.50vw는 부모가 아니라 화면 너비 기준이므로, 경우에 따라 부모보다 더 넓어질 수도 있습니다.
이 차이를 직접 개발자 도구에서 바꿔 보면 단위 감각이 정말 빨리 생깁니다.
display: 요소가 줄을 어떻게 차지할까
이제 크기를 정했다면, 다음 질문이 생깁니다. "그 요소는 줄을 어떻게 쓰는가?" 바로 여기서 display가 등장합니다.
display는 요소가 화면에서 어떤 방식으로 배치되는지 정합니다. 초보자 단계에서는 네 가지만 확실히 알아도 레이아웃 이해도가 크게 올라갑니다.34
blockinlineinline-blocknone
block: 한 줄을 시원하게 차지하는 요소
block 요소는 새 줄에서 시작하고, 보통 가로로 가능한 공간을 넓게 차지합니다.34
대표적으로 div, p, h1 같은 요소가 기본적으로 block 성질을 가집니다.
<div class="block-box">첫 번째 박스</div>
<div class="block-box">두 번째 박스</div>.block-box {
display: block;
background: #fde68a;
margin-bottom: 10px;
padding: 12px;
}결과는 위아래로 차곡차곡 쌓입니다. 박스 하나가 한 줄을 쓰고, 다음 박스는 다음 줄로 내려갑니다.
레이아웃 관점에서 block은 "문단", "구역", "섹션"처럼 생각하면 쉽습니다. 화면을 위에서 아래로 쌓아 올리는 기본 단위입니다.
inline: 글자처럼 흐르는 요소
inline 요소는 글자처럼 한 줄 안에서 흐릅니다. 새 줄에서 시작하지 않고, 내용만큼만 자리를 차지합니다.34
대표적으로 span, a, strong 같은 요소가 inline입니다.
<p>
오늘의 할인 상품은
<span class="highlight">딸기 케이크</span>
입니다.
</p>.highlight {
display: inline;
background: #fecaca;
}이 경우 span은 문장 속 일부처럼 자연스럽게 들어갑니다.
중요한 특징이 하나 있습니다. inline 요소는 보통 width와 height를 줘도 기대한 대로 잘 적용되지 않습니다.3 그래서 "왜 span에 width를 줬는데 안 커지지?" 같은 일이 자주 생깁니다. 이유는 그 요소가 inline이기 때문입니다.
inline-block: 옆으로 놓이지만 크기 조절도 가능
inline-block은 이름 그대로 inline과 block의 장점을 섞은 형태입니다. 옆으로 나란히 놓일 수 있으면서, width와 height도 줄 수 있습니다.34
<div class="badge">HTML</div>
<div class="badge">CSS</div>
<div class="badge">JavaScript</div>.badge {
display: inline-block;
width: 120px;
padding: 10px;
margin-right: 8px;
background: #bfdbfe;
text-align: center;
}이렇게 하면 요소들이 한 줄에 나란히 놓이면서도, 각자 박스처럼 크기를 가질 수 있습니다.
버튼 묶음, 태그, 뱃지, 간단한 가로 메뉴를 만들 때 유용합니다. 요즘은 복잡한 배치에 Flexbox를 더 많이 쓰지만, inline-block은 여전히 기본 동작을 이해하는 데 매우 중요합니다.
none: 화면에서도, 자리에서도 사라진다
display: none;은 요소를 아예 없는 것처럼 처리합니다. 화면에 보이지 않을 뿐 아니라, 차지하던 자리도 사라집니다.34
.notice {
display: none;
}이때 자주 비교되는 것이 visibility: hidden;인데, 그건 보이지만 않게 할 뿐 자리는 남겨 둡니다. 반면 display: none;은 자리까지 사라집니다. 초보자가 이 둘을 헷갈리기 쉬우니 꼭 구분해 두세요.
예를 들어 메뉴를 잠시 숨기거나, 조건에 따라 특정 안내문을 안 보이게 할 때 display: none;을 많이 사용합니다.
block, inline, inline-block 차이를 한 번에 보기
아래 예제는 세 가지를 한눈에 비교하기 좋습니다.
<div class="demo-wrap">
<span class="d-block">block</span>
<span class="d-inline">inline</span>
<span class="d-inline-block">inline-block</span>
</div>.demo-wrap span {
background: #ddd6fe;
border: 1px solid #8b5cf6;
margin: 8px;
padding: 8px;
}
.d-block {
display: block;
width: 200px;
}
.d-inline {
display: inline;
width: 200px;
}
.d-inline-block {
display: inline-block;
width: 200px;
}이 예제를 보면:
block은 줄을 바꾸고 너비가 적용됩니다.inline은 줄 안에 머물지만 너비 적용이 기대처럼 되지 않습니다.inline-block은 줄 안에 머물면서 너비도 적용됩니다.
이 세 줄만 제대로 이해해도, 화면이 왜 그렇게 생겼는지 설명하는 힘이 크게 늘어납니다.
overflow: 내용이 넘칠 때 무슨 일이 벌어질까
이제 마지막 퍼즐입니다. 박스 크기를 정했고, 줄의 흐름도 정했습니다. 그런데 내용이 박스보다 많으면 어떻게 될까요? 바로 overflow가 결정합니다.
overflow는 상자보다 내용이 더 클 때, 그 넘친 부분을 어떻게 처리할지 정하는 속성입니다.56
기본값은 visible입니다. 즉, 기본적으로는 내용이 박스 밖으로 보여도 그냥 보여 줍니다.5
overflow: visible
visible은 넘친 내용을 잘라내지 않습니다. 그래서 내용이 상자 밖으로 삐져나올 수 있습니다.5
.box {
width: 200px;
height: 60px;
overflow: visible;
}이 상태에서는 박스 크기보다 긴 글이 박스 아래로 튀어나와 보일 수 있습니다. 초보자 입장에서는 "CSS가 망가졌나?" 싶을 수 있지만, 사실은 기본 동작일 뿐입니다.
overflow: hidden
hidden은 넘친 내용을 잘라냅니다. 밖으로 삐져나온 부분은 보이지 않습니다.5
.box {
width: 200px;
height: 60px;
overflow: hidden;
}카드 썸네일, 둥근 이미지, 특정 영역 안에만 내용을 보여 주고 싶을 때 자주 씁니다. 다만 중요한 텍스트를 숨기면 사용자가 나머지 내용을 볼 방법이 없으므로 조심해야 합니다.
overflow: scroll
scroll은 내용이 넘치든 말든 스크롤바를 항상 보여 주는 방식입니다.5
.box {
width: 200px;
height: 60px;
overflow: scroll;
}이 방식은 사용자가 반드시 스크롤할 수 있다는 장점이 있지만, 실제로는 넘치지 않아도 스크롤바가 보일 수 있어 화면이 다소 답답해 보일 수 있습니다.
overflow: auto
auto는 실무에서 가장 자주 쓰는 쪽에 가깝습니다. 내용이 넘칠 때만 스크롤바를 보여 줍니다.5
.box {
width: 200px;
height: 60px;
overflow: auto;
}내용이 적으면 깔끔하고, 많으면 자동으로 스크롤이 생깁니다. 긴 코드, 채팅 영역, 댓글 목록, 작은 설명 박스 등에 잘 어울립니다.
overflow는 언제 차이가 잘 보일까
overflow는 보통 박스의 크기가 제한되어 있을 때 차이가 분명하게 드러납니다. 예를 들어 높이가 정해져 있지 않으면, 박스가 그냥 늘어나서 내용을 담아 버릴 수도 있습니다. 그래서 overflow를 연습할 때는 width나 height를 함께 지정해 보는 것이 좋습니다.5
다음 예제를 직접 보면 이해가 빠릅니다.
<div class="overflow-demo visible-box">
내용이 길면 박스 밖으로 나옵니다. 내용이 길면 박스 밖으로 나옵니다.
내용이 길면 박스 밖으로 나옵니다.
</div>
<div class="overflow-demo hidden-box">
내용이 길면 박스 밖으로 나옵니다. 내용이 길면 박스 밖으로 나옵니다.
내용이 길면 박스 밖으로 나옵니다.
</div>
<div class="overflow-demo auto-box">
내용이 길면 박스 안에서 스크롤됩니다. 내용이 길면 박스 안에서 스크롤됩니다.
내용이 길면 박스 안에서 스크롤됩니다.
</div>.overflow-demo {
width: 240px;
height: 80px;
border: 2px solid #334155;
margin-bottom: 16px;
padding: 8px;
}
.visible-box {
overflow: visible;
}
.hidden-box {
overflow: hidden;
}
.auto-box {
overflow: auto;
}실행해 보면 세 박스가 완전히 다르게 느껴질 것입니다. 같은 내용인데도 처리 방식에 따라 인상이 달라집니다. 이것이 바로 레이아웃 디버깅에서 overflow가 중요한 이유입니다.
가로와 세로를 따로 제어할 수도 있다
때로는 세로 스크롤만 허용하고, 가로로는 넘치지 않게 막고 싶을 때가 있습니다. 그럴 때는 overflow-x, overflow-y를 사용합니다.5
.chat-box {
width: 300px;
height: 180px;
overflow-y: auto;
overflow-x: hidden;
}이 코드는 채팅창처럼 세로로만 내용이 길어지는 영역에 잘 맞습니다. 위아래로는 스크롤할 수 있지만, 옆으로 미끄러지는 일은 막을 수 있습니다.
실전 예제 1: 반응형 카드 만들기
이제 앞에서 배운 것을 한 번 섞어 봅시다.
<div class="card">
<h3>오늘의 추천</h3>
<p>
CSS는 생각보다 재밌습니다. 단위를 이해하면 레이아웃이 갑자기 말이 되기 시작합니다.
</p>
<a href="#" class="card-button">자세히 보기</a>
</div>.card {
width: 80%;
max-width: 30rem;
padding: 1.5rem;
margin: 2rem auto;
border: 1px solid #cbd5e1;
border-radius: 1rem;
}
.card h3 {
font-size: 1.5rem;
margin-bottom: 0.75rem;
}
.card p {
font-size: 1rem;
line-height: 1.6;
}
.card-button {
display: inline-block;
margin-top: 1rem;
padding: 0.75em 1.2em;
background: #2563eb;
color: white;
text-decoration: none;
border-radius: 0.5rem;
}여기서 눈여겨볼 점은 이렇습니다.
카드 너비는
%와rem을 섞어 유연성과 최대 크기를 함께 잡았습니다.제목과 본문 크기는
rem으로 통일감을 줬습니다.버튼은
inline-block이라 줄 안에 놓일 수 있으면서 패딩과 크기 조절도 자연스럽습니다.버튼 패딩은
em이라 글자 크기와 함께 비례합니다.
이런 조합이 실무에서 매우 자주 등장합니다.
실전 예제 2: 잘리지 않는 박스와 잘리는 박스
<div class="profile visible-profile">
<img src="https://via.placeholder.com/300x180" alt="예시 이미지">
</div>
<div class="profile hidden-profile">
<img src="https://via.placeholder.com/300x180" alt="예시 이미지">
</div>.profile {
width: 220px;
height: 120px;
border-radius: 16px;
border: 2px solid #94a3b8;
margin-bottom: 16px;
}
.profile img {
width: 300px;
}
.visible-profile {
overflow: visible;
}
.hidden-profile {
overflow: hidden;
}첫 번째 박스는 이미지가 튀어나와 보일 것이고, 두 번째 박스는 둥근 테두리 안에서 깔끔하게 잘립니다. 카드 썸네일이나 프로필 배너를 만들 때 왜 overflow: hidden;이 자주 등장하는지 이 예제로 감이 옵니다.
초보자가 자주 헷갈리는 포인트
처음 CSS를 배울 때 특히 자주 나오는 오해를 정리해 봅시다.
width: 50%를 줬는데 생각보다 작거나 크다면, 부모 크기를 먼저 확인해야 합니다. %는 부모 기준입니다.
span에 width를 줬는데 안 먹는다면, 그 요소가 inline일 가능성이 큽니다. inline-block이나 block으로 바꿔 보세요.
overflow: auto를 줬는데 스크롤이 안 보인다면, 박스가 실제로 넘치지 않았거나 높이 제한이 없을 수 있습니다.
em을 여러 단계 중첩해서 썼더니 글자가 너무 커졌다면, 부모의 글자 크기가 계속 누적되었을 수 있습니다. 이럴 때는 rem이 더 예측 가능합니다.2
50vw가 부모 박스를 뚫고 나간다면, 그건 이상한 게 아니라 정상입니다. vw는 부모가 아니라 화면 기준입니다.1
오늘 배운 내용을 한 장으로 정리하면
CSS에서 크기는 숫자만의 문제가 아니라 무엇을 기준으로 계산하느냐의 문제입니다. px는 비교적 고정적이고, %는 부모를, em과 rem은 글자 크기를, vw와 vh는 화면 크기를 바라봅니다.
또한 요소는 단지 크기만 가지는 것이 아니라, display에 따라 줄을 차지하는 방식이 달라집니다. block은 줄을 바꾸고, inline은 글자처럼 흐르며, inline-block은 옆으로 놓이면서도 박스처럼 다룰 수 있고, none은 자리째 사라집니다.
마지막으로 내용이 박스보다 커졌을 때는 overflow가 등장합니다. 보여 줄지, 숨길지, 스크롤할지 정하는 것이죠. 이 세 가지 축, 즉 크기, 흐름, 넘침 처리를 이해하면 화면을 훨씬 잘 읽게 됩니다.
다음 장에서는 이 흐름 위에서 요소를 조금 더 적극적으로 배치하는 방법, 즉 position, z-index, 그리고 기본적인 배치 사고를 다뤄 보겠습니다. 이제 요소는 단순히 쌓이는 상자가 아니라, 원하는 자리에 놓을 수 있는 조각이 됩니다.
참고
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.