반응형 CSS는 화면에 맞춰 옷을 갈아입는 일입니다
같은 웹페이지라도 PC 모니터에서 볼 때와 휴대폰에서 볼 때는 조건이 다릅니다. PC 화면은 넓고 마우스로 클릭합니다. 휴대폰 화면은 좁고 손가락으로 누릅니다. 그래서 PC에서 보기 좋던 3열 상품 카드가 휴대폰에서는 너무 작아지고, 긴 제목은 줄 밖으로 삐져나가며, 이미지가 화면보다 넓어질 수 있습니다.
반응형 웹은 이런 상황에 맞춰 화면을 조정하는 방식입니다. 새 페이지를 따로 만드는 것이 아니라, 같은 HTML을 두고 CSS가 화면 너비에 따라 글자 크기, 이미지 크기, 여백, 배치를 바꿉니다. MDN은 반응형 디자인을 다양한 화면 크기와 기기에서 사이트가 잘 작동하도록 만드는 접근 방식으로 설명합니다.1
비유하면 옷의 사이즈 조절과 비슷합니다. 같은 재킷이라도 끈을 조이면 몸에 맞고, 단추 위치를 바꾸면 움직이기 편해집니다. 반응형 CSS도 같은 내용을 더 좁은 화면에 맞게 다시 정돈합니다.
AI 생성 이미지
고정된 px만 쓰면 화면이 답답해질 수 있습니다
px은 정확한 크기를 정할 때 좋습니다. 예를 들어 테두리 두께를 1px로 주거나, 아이콘 크기를 24px로 맞추는 일에는 잘 어울립니다. 하지만 모든 크기를 px로 고정하면 작은 화면에서 문제가 생길 수 있습니다.
.promo-banner {
width: 1000px;
padding: 40px;
}이 배너는 PC에서는 괜찮아 보일 수 있습니다. 하지만 휴대폰 화면이 390px 정도라면 1000px짜리 배너는 화면 밖으로 삐져나갑니다. 사용자는 좌우로 밀어야 내용을 볼 수 있습니다.
이럴 때 상대 단위를 사용합니다. 상대 단위는 정해진 숫자 하나에 묶이지 않고, 부모 요소나 화면 크기, 기본 글자 크기에 맞춰 유연하게 변합니다.
%, rem, vw를 어디에 쓰면 좋을까요
%는 부모 요소를 기준으로 크기를 정합니다. 부모 상자가 800px이면 width: 50%는 400px이 되고, 부모 상자가 360px이면 180px이 됩니다. 쇼핑몰 배너나 이미지처럼 화면 폭에 맞춰 줄어들어야 하는 요소에 자주 씁니다.
.banner {
width: 100%;
max-width: 960px;
}위 코드는 "가능하면 부모 폭을 꽉 채우되, 너무 넓어져도 960px까지만 커지라"는 뜻입니다. PC에서는 지나치게 넓어지지 않고, 모바일에서는 화면에 맞게 줄어듭니다.
rem은 웹사이트의 기본 글자 크기를 기준으로 합니다. 보통 브라우저 기본 글자 크기 16px을 기준으로 1rem은 약 16px입니다. 버튼 안쪽 여백이나 카드 여백에 rem을 쓰면 전체 글자 크기 흐름과 잘 맞습니다.
.card {
padding: 1.5rem;
border-radius: 1rem;
}vw는 화면 너비를 기준으로 합니다. 1vw는 화면 너비의 1%입니다. 예를 들어 화면이 1000px이면 1vw는 10px이고, 화면이 400px이면 4px입니다. 큰 메인 문구를 화면에 맞춰 자연스럽게 키우거나 줄일 때 쓸 수 있습니다.
다만 글자 크기를 vw만으로 정하면 큰 화면에서 글자가 지나치게 커질 수 있고, 사용자가 글자를 확대해서 볼 때 불편해질 수 있습니다. 그래서 처음에는 제목 전체를 vw 하나로만 정하기보다, rem을 기본으로 두고 vw를 조금 섞는 방식이 안전합니다.
.hero-title {
font-size: calc(1.5rem + 2vw);
}위 코드는 기본 글자 크기에 화면 너비에 따른 크기를 조금 더하는 방식입니다. "모바일에서는 너무 작지 않고, 큰 화면에서는 조금 더 시원하게 보이게" 만들 때 쓸 수 있습니다. 그래도 너무 커 보인다면 미디어 쿼리로 한 번 더 조정하면 됩니다.
모바일에서 제대로 보이려면 viewport 설정도 확인합니다
반응형 CSS를 열심히 작성했는데도 휴대폰에서 PC 화면이 작게 축소되어 보이는 경우가 있습니다. 이때는 CSS 문제가 아니라 HTML의 viewport 설정이 빠졌을 수 있습니다.
보통 HTML 문서의 <head> 안에 다음 코드가 들어갑니다.
<meta name="viewport" content="width=device-width, initial-scale=1.0">이 코드는 모바일 브라우저에게 "화면 폭을 실제 기기 폭에 맞춰서 보여 주세요"라고 알려 줍니다. 예전 모바일 브라우저는 PC용 웹사이트를 작게 축소해서 보여 주는 방식으로 동작하는 경우가 많았습니다. 그래서 viewport 설정이 없으면, 내가 작성한 @media (max-width: 768px) 같은 조건이 휴대폰에서 기대대로 적용되지 않을 수 있습니다. MDN도 반응형 페이지에서는 이 viewport meta 태그를 문서의 <head>에 포함하라고 안내합니다.1
이미 만들어진 블로그, 쇼핑몰 솔루션, 홈페이지 템플릿을 수정하는 경우에는 이 코드가 이미 들어 있을 때가 많습니다. 그래도 모바일 화면이 이상하다면 한 번쯤 확인해 보세요.
이미지는 먼저 넘치지 않게 만듭니다
모바일에서 자주 생기는 문제 중 하나는 이미지가 화면 밖으로 삐져나가는 일입니다. 이미지는 원본 크기가 클 수 있기 때문입니다. 해결책은 간단합니다.
img {
max-width: 100%;
height: auto;
}max-width: 100%는 이미지가 자기 부모보다 더 넓어지지 않게 막습니다. height: auto는 가로 크기가 줄어들 때 세로 크기도 비율에 맞춰 줄어들게 합니다. MDN도 반응형 디자인에서 이미지와 미디어가 컨테이너 밖으로 넘치지 않도록 유연하게 다루는 방식을 중요한 원리로 설명합니다.1
이미지가 찌그러진다면 대개 가로와 세로를 동시에 억지로 고정했기 때문입니다.
.product-image {
width: 100%;
height: 220px;
object-fit: cover;
}이 코드는 상품 카드에서 자주 씁니다. 이미지는 카드 폭에 맞추고, 높이는 220px로 통일합니다. object-fit: cover는 사진 비율을 유지하면서 정해진 영역을 자연스럽게 채웁니다. 사진 일부가 잘릴 수는 있지만, 찌그러지지는 않습니다.
미디어 쿼리는 "이 조건일 때만" 적용하는 CSS입니다
미디어 쿼리는 화면 너비 같은 조건을 확인한 뒤, 조건이 맞을 때만 CSS를 적용하는 문법입니다. 일상적인 말로 바꾸면 이렇게 됩니다.
"화면 너비가 768px 이하라면, 카드 목록을 1열로 바꿔 주세요."
CSS로는 이렇게 씁니다.
@media (max-width: 768px) {
.card-list {
grid-template-columns: 1fr;
}
}@media는 조건문을 시작하는 표시입니다. (max-width: 768px)은 화면 너비가 768px 이하일 때라는 뜻입니다. 그 안에 들어간 CSS는 조건이 맞을 때만 적용됩니다. 미디어 쿼리는 조건이 참일 때 안쪽 CSS 블록이 적용되는 방식으로 동작합니다.2
처음에는 두 가지 표현만 기억해도 충분합니다.
max-width: 이 너비 이하일 때 적용min-width: 이 너비 이상일 때 적용
기존 PC 화면을 먼저 만들고 모바일에서 덮어쓰고 싶다면 max-width가 이해하기 쉽습니다. 반대로 모바일 화면을 기본으로 만들고 넓은 화면에서 확장하고 싶다면 min-width를 씁니다.
PC 3열 카드가 모바일 1열 카드로 바뀌는 패턴
이전 장에서 Grid로 카드 목록을 만드는 방법을 배웠습니다. 이제 그 목록을 모바일에서도 보기 좋게 바꿔 보겠습니다.
먼저 PC 화면에서 상품 카드가 3열로 보이는 상태입니다.
.product-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}repeat(3, 1fr)은 같은 폭의 열을 3개 만든다는 뜻입니다. PC에서는 상품 3개가 한 줄에 나란히 보여서 목록을 빠르게 훑기 좋습니다. 하지만 휴대폰에서는 각 카드가 너무 좁아집니다.
그래서 화면이 좁아지면 1열로 바꿉니다.
@media (max-width: 768px) {
.product-list {
grid-template-columns: 1fr;
gap: 16px;
}
}이제 768px 이하 화면에서는 카드가 한 줄에 하나씩 쌓입니다. 사용자는 글자와 이미지를 더 크게 볼 수 있고, 손가락으로 버튼을 누르기도 편합니다.
카드 안쪽 여백도 모바일에서는 조금 줄일 수 있습니다.
@media (max-width: 768px) {
.product-card {
padding: 1rem;
}
}PC에서는 여백이 넓어야 고급스럽게 보이지만, 모바일에서는 화면 공간이 부족합니다. 여백을 줄이면 내용이 답답하지 않게 들어옵니다.
모바일에서 자주 생기는 문제 해결하기
글자가 화면 밖으로 나갈 때
긴 상품명, 영어 URL, 긴 해시태그는 줄바꿈이 잘 되지 않아 화면을 밀어낼 수 있습니다.
.card-title {
overflow-wrap: break-word;
}overflow-wrap: break-word는 긴 단어가 상자 밖으로 나가려 할 때 적절히 줄을 바꾸게 합니다. 블로그 제목, 후기 카드, 상품명에 유용합니다.
좌우 스크롤이 생길 때
모바일에서 좌우 스크롤이 생기면 대개 어떤 요소가 화면보다 넓다는 뜻입니다. 다음 항목을 먼저 확인하세요.
width: 1000px처럼 큰 고정 폭이 있는가?이미지에
max-width: 100%가 빠졌는가?카드나 배너에 큰
padding을 주고box-sizing을 설정하지 않았는가?Grid 열을 모바일에서 1열로 바꾸지 않았는가?
viewport meta 태그가 빠져 있지 않은가?
전체 요소에 다음 코드를 넣어 두면 크기 계산 실수를 줄일 수 있습니다.
* {
box-sizing: border-box;
}box-sizing: border-box는 요소의 폭 안에 padding과 border까지 포함해서 계산하게 합니다. "폭은 100%인데 padding 때문에 실제 크기가 100%를 넘는 문제"를 줄여 줍니다.
버튼이 너무 작을 때
모바일 버튼은 눈으로만 보는 요소가 아니라 손가락으로 누르는 요소입니다. 글자만 겨우 들어가는 크기보다 여유 있는 클릭 영역이 필요합니다.
.cta-button {
display: inline-block;
padding: 0.9rem 1.2rem;
font-size: 1rem;
}모바일에서 버튼이 여러 개 나란히 있어 답답하다면 세로로 쌓아도 좋습니다.
@media (max-width: 600px) {
.button-group {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
}작은 실습: 블로그 글 목록을 모바일용으로 바꾸기
수정 전 CSS입니다. PC에서는 괜찮지만 모바일에서는 3열이 너무 좁습니다.
.post-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
.post-card {
padding: 24px;
}수정 후 CSS입니다.
.post-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
.post-card {
padding: 24px;
}
@media (max-width: 768px) {
.post-list {
grid-template-columns: 1fr;
gap: 16px;
}
.post-card {
padding: 1rem;
}
}수정 전에는 모바일에서 카드가 한 줄에 3개 들어가 글자와 버튼이 작아집니다. 수정 후에는 카드가 한 줄에 하나씩 배치되어 제목, 설명, 버튼을 읽기 편합니다.
마지막으로 반응형 CSS를 점검할 때는 다음 순서로 보면 좋습니다.
HTML에 viewport meta 태그가 들어 있는가?
화면을 좁혔을 때 좌우 스크롤이 생기지 않는가?
이미지는 카드나 본문 영역 안에 자연스럽게 들어오는가?
카드 목록은 모바일에서 1열로 바뀌는가?
제목과 버튼이 너무 작거나 너무 붙어 있지 않은가?
고정된
px폭 때문에 화면을 밀어내는 요소가 없는가?
반응형 CSS의 핵심은 모든 기기 크기를 외우는 것이 아닙니다. 화면이 좁아질 때 읽기 어려워지는 지점을 찾고, 그 지점에서 CSS를 바꾸는 것입니다. PC에서 예쁜 화면보다 모바일에서 읽히는 화면이 먼저 필요할 때가 많습니다. 그래서 반응형 CSS는 선택이 아니라 기본 습관에 가깝습니다.
참고
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.