CSS
[CSS] width 100vw일 때 가로(좌우) 스크롤이 생긴다면?
dev_sihyun
2024. 1. 24. 12:34
반응형
100vw 사용 시 가로 스크롤 문제 완벽 해결 가이드
📋 목차
🔍 vw, vh 단위 이해하기
기본 개념
/* Viewport 단위 설명 */
.example {
width: 50vw; /* viewport width의 50% */
height: 50vh; /* viewport height의 50% */
/* 추가 viewport 단위들 */
width: 50vmin; /* viewport의 작은 쪽 기준 50% */
width: 50vmax; /* viewport의 큰 쪽 기준 50% */
}
📊 Viewport 단위 비교표
단위 | 설명 | 계산 기준 | 용도 |
---|---|---|---|
vw |
Viewport Width | 화면 너비의 1% | 가로 반응형 |
vh |
Viewport Height | 화면 높이의 1% | 세로 반응형 |
vmin |
Viewport Minimum | 작은 쪽 기준 1% | 정사각형 요소 |
vmax |
Viewport Maximum | 큰 쪽 기준 1% | 전체 화면 커버 |
🎯 vw/vh의 특징
- ✅ 반응형 디자인에 탁월
- ✅ 전체 화면 레이아웃 구현 시 유용
- ⚠️ 스크롤바 포함 계산 (문제의 원인!)
- ⚠️ 모바일에서 주소창 높이 변화 영향
🚨 문제 상황과 원인 분석
문제가 되는 코드
body {
width: 100vw; /* ← 문제의 원인! */
height: 100vh;
position: relative;
z-index: 10;
/* 커스텀 스크롤바 */
&::-webkit-scrollbar {
background: transparent;
width: 8px; /* ← 이 너비가 핵심! */
}
&::-webkit-scrollbar-thumb {
border-radius: 100px;
background-color: #ccc;
border: 0;
}
&::-webkit-scrollbar-track {
background-color: transparent;
}
}
🔍 문제 발생 원리
화면 전체 너비: 1920px (예시)
├── body width (100vw): 1920px
└── scrollbar width: 8px
─────────────────────────────────
총 필요 너비: 1928px (1920px + 8px)
결과: 화면보다 8px 더 넓어져서 가로 스크롤 발생! 🔄
🖼️ 시각적 문제 확인
<!-- 문제 확인용 HTML -->
<div class="debug-container">
<div class="content">
화면 너비: 100vw
</div>
<div class="scrollbar-indicator">
스크롤바: 8px
</div>
</div>
.debug-container {
width: 100vw;
height: 100vh;
background: linear-gradient(90deg, #ff6b6b 0%, #4ecdc4 100%);
position: relative;
overflow-x: auto; /* 스크롤 문제 확인용 */
}
.scrollbar-indicator {
position: absolute;
right: 0;
top: 0;
width: 8px;
height: 100%;
background: rgba(255, 0, 0, 0.5);
z-index: 1000;
}
💡 해결 방법 비교
방법 1: calc() 사용 (기본 해결책)
body {
width: calc(100vw - 8px); /* 스크롤바 너비만큼 차감 */
height: 100vh;
}
장점:
- ✅ 간단하고 직관적
- ✅ 정확한 계산
단점:
- ❌ 스크롤바 너비를 하드코딩
- ❌ 브라우저/OS별 차이 고려 필요
방법 2: 100% 사용 (권장)
body {
width: 100%; /* vw 대신 % 사용 */
height: 100vh;
box-sizing: border-box; /* padding, border 포함 */
}
장점:
- ✅ 스크롤바 문제 없음
- ✅ 브라우저 호환성 좋음
- ✅ 더 예측 가능한 동작
단점:
- ❌ 부모 요소에 의존적
방법 3: CSS 커스텀 속성 활용
:root {
--scrollbar-width: 8px;
--viewport-width: calc(100vw - var(--scrollbar-width));
}
body {
width: var(--viewport-width);
height: 100vh;
}
/* 스크롤바가 없는 경우 대응 */
@media (hover: none) {
:root {
--scrollbar-width: 0px; /* 모바일에서는 보통 0 */
}
}
방법 4: JavaScript를 이용한 동적 계산
// 실제 스크롤바 너비 계산
function getScrollbarWidth() {
const outer = document.createElement('div');
outer.style.visibility = 'hidden';
outer.style.overflow = 'scroll';
outer.style.msOverflowStyle = 'scrollbar';
document.body.appendChild(outer);
const inner = document.createElement('div');
outer.appendChild(inner);
const scrollbarWidth = outer.offsetWidth - inner.offsetWidth;
outer.parentNode.removeChild(outer);
return scrollbarWidth;
}
// CSS 변수로 설정
document.documentElement.style.setProperty(
'--scrollbar-width',
`${getScrollbarWidth()}px`
);
body {
width: calc(100vw - var(--scrollbar-width));
height: 100vh;
}
🌐 브라우저별 차이점
스크롤바 너비 비교
브라우저/OS | 기본 스크롤바 너비 | 특징 |
---|---|---|
Chrome (Windows) | 17px | 항상 표시 |
Chrome (macOS) | 15px | 스크롤 시만 표시 |
Firefox (Windows) | 17px | 항상 표시 |
Safari (macOS) | 15px | 오버레이 형태 |
Edge | 17px | Windows와 동일 |
모바일 브라우저 | 0px | 오버레이 형태 |
크로스 브라우저 해결책
body {
width: 100%;
max-width: 100vw; /* fallback */
height: 100vh;
overflow-x: hidden; /* 가로 스크롤 강제 숨김 */
box-sizing: border-box;
}
/* 웹킷 브라우저 대응 */
@supports (-webkit-appearance: none) {
body {
width: calc(100vw - 15px); /* macOS Safari */
}
}
/* Firefox 대응 */
@supports (-moz-appearance: none) {
body {
width: calc(100vw - 17px); /* Windows Firefox */
}
}
🛠️ 실무 활용 팁
1. Modern CSS Grid 활용
.full-screen-layout {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 100vh;
width: 100%;
margin: 0;
padding: 0;
}
2. Flexbox로 전체 화면 구성
.app-container {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
}
.main-content {
flex: 1;
width: 100%;
}
3. CSS Reset으로 예방
/* CSS Reset - 스크롤바 문제 예방 */
* {
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow-x: hidden; /* 가로 스크롤 방지 */
}
4. 반응형 스크롤바 처리
// SCSS mixin으로 재사용
@mixin full-viewport($include-scrollbar: false) {
@if $include-scrollbar {
width: 100vw;
} @else {
width: 100%;
max-width: 100vw;
}
height: 100vh;
}
// 사용 예시
.hero-section {
@include full-viewport(false);
background: linear-gradient(45deg, #667eea 0%, #764ba2 100%);
}
🎯 대안 방법
1. Container Queries 활용 (최신)
@supports (container-type: inline-size) {
.container {
container-type: inline-size;
width: 100%;
}
.content {
@container (min-width: 768px) {
width: 100%;
padding: 2rem;
}
}
}
2. CSS-in-JS 라이브러리 활용
// Styled-components 예시
import styled from 'styled-components';
const FullWidthContainer = styled.div`
width: 100%;
max-width: 100vw;
height: 100vh;
box-sizing: border-box;
@media (min-width: 768px) {
width: calc(100vw - ${props => props.scrollbarWidth || '17px'});
}
`;
3. PostCSS 플러그인 활용
// postcss.config.js
module.exports = {
plugins: [
require('postcss-viewport-height-correction'),
// vh 단위 문제 해결
]
};
⚠️ 주의사항 및 고려사항
🚫 피해야 할 실수들
/* ❌ 잘못된 방법들 */
.bad-example {
width: 100vw;
padding: 20px; /* 패딩이 추가되어 더 넓어짐 */
border: 1px solid #000; /* 보더도 추가 너비 */
box-sizing: content-box; /* 기본값, 문제 발생 */
}
/* ❌ 하드코딩된 스크롤바 너비 */
.also-bad {
width: calc(100vw - 17px); /* 모든 브라우저가 17px는 아님 */
}
✅ 올바른 접근법
/* ✅ 권장 방법 */
.good-example {
width: 100%;
max-width: 100vw;
padding: 20px;
border: 1px solid #000;
box-sizing: border-box; /* 중요! */
}
📱 모바일 고려사항
/* 모바일에서 100vh 문제 해결 */
.mobile-safe {
height: 100vh;
height: calc(var(--vh, 1vh) * 100); /* JS로 설정된 실제 높이 */
}
// 모바일 viewport height 보정
function setMobileVH() {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
}
window.addEventListener('resize', setMobileVH);
setMobileVH();
🎉 마무리
100vw 사용 시 가로 스크롤 문제는 스크롤바가 viewport 계산에 포함되지 않기 때문에 발생합니다.
📝 해결책 우선순위
- 🥇
width: 100%
사용 - 가장 안전하고 호환성 좋음 - 🥈
calc(100vw - scrollbar-width)
- 정확한 제어가 필요한 경우 - 🥉 JavaScript 동적 계산 - 완벽한 호환성이 필요한 경우
🔧 실무 체크리스트
-
box-sizing: border-box
설정 확인 - 모바일/데스크톱 테스트 진행
- 다양한 브라우저에서 스크롤바 동작 확인
- CSS Reset/Normalize 적용
- 반응형 디자인 고려
🔗 참고 자료
💡 Pro Tip: 대부분의 경우
width: 100%
가width: 100vw
보다 더 나은 선택입니다. 꼭 필요한 경우가 아니라면 100%를 사용하세요!
반응형