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 계산에 포함되지 않기 때문에 발생합니다.

📝 해결책 우선순위

  1. 🥇 width: 100% 사용 - 가장 안전하고 호환성 좋음
  2. 🥈 calc(100vw - scrollbar-width) - 정확한 제어가 필요한 경우
  3. 🥉 JavaScript 동적 계산 - 완벽한 호환성이 필요한 경우

🔧 실무 체크리스트

  • box-sizing: border-box 설정 확인
  • 모바일/데스크톱 테스트 진행
  • 다양한 브라우저에서 스크롤바 동작 확인
  • CSS Reset/Normalize 적용
  • 반응형 디자인 고려

🔗 참고 자료


💡 Pro Tip: 대부분의 경우 width: 100%width: 100vw보다 더 나은 선택입니다. 꼭 필요한 경우가 아니라면 100%를 사용하세요!

반응형