Единица 100vw на мобильном браузере нередко оказывается шире видимой области: адресная строка и панель инструментов частично перекрывают контент, а блок с шириной 100vw провоцирует горизонтальный скролл. Именно из-за этого поведения в спецификацию CSS Values and Units Level 4 добавили динамические единицы dvw, и отличие vw от dvw стало одним из частых вопросов при адаптивной вёрстке.

Коротко: vw — это 1% от ширины исходного (наибольшего) вьюпорта, а dvw — 1% от динамического вьюпорта, который пересчитывается при появлении и скрытии элементов интерфейса браузера. Ниже разберём, как это работает на практике, где каждая единица уместна и как не сломать макет.

Что такое vw и как работает классическая единица

Единица vw (viewport width) равна одному проценту от ширины области просмотра. При ширине экрана 390 пикселей значение 1vw составит 3,9 пикселя, а 100vw — все 390. На десктопе, где размер окна меняется только вручную, это поведение предсказуемо и проблем не создаёт.

Сложности начинаются на мобильных устройствах. Во многих мобильных браузерах адресная строка и нижняя панель навигации автоматически скрываются при прокрутке страницы вниз и появляются при прокрутке вверх. Классический vw рассчитывается от размера вьюпорта в состоянии, когда интерфейс браузера скрыт, то есть от наибольшего возможного размера. Пока панели видны, реальная видимая область меньше, и элементы, привязанные к 100vw и 100vh, могут выходить за её пределы.

Типичные симптомы, с которыми сталкиваются верстальщики:

  • 📱 горизонтальная полоса прокрутки на мобильном при заданной ширине 100vw;
  • ✂️ нижняя часть полноэкранного блока обрезана панелью браузера;
  • 🔄 дёрганье кнопок и фонов при скролле, если размеры привязаны к вьюпорту;
  • 📏 несовпадение расчётов в JavaScript через window.innerWidth с CSS-единицами.

Что такое dvw и зачем понадобились новые единицы

Буква d в dvw означает dynamic — динамический. Значение 1dvw — это 1% от ширины динамического вьюпорта, то есть той области, которая реально видна пользователю прямо сейчас, с учётом открытых панелей браузера. Когда адресная строка скрывается, значение dvw пересчитывается, и элемент плавно занимает освободившееся пространство.

Помимо dvw, спецификация вводит ещё две пары единиц, и понимать их важно, чтобы осознанно выбирать инструмент:

  • 📐 svw (small viewport width) — 1% от наименьшего вьюпорта, когда все панели браузера развёрнуты;
  • 📏 lvw (large viewport width) — 1% от наибольшего вьюпорта, когда панели скрыты; по сути соответствует классическому vw;
  • 🔄 dvw — промежуточное значение, плавающее между svw и lvw в зависимости от состояния интерфейса.

Те же три варианта существуют и для высоты: svh, lvh, dvh, а также для меньшего и большего из двух измерений — svmin/dvmin/lvmin и svmax/dvmax/lvmax. На десктопных браузерах, где интерфейс не прячется при скролле, все три значения обычно совпадают.

📊 Какие единицы вы используете для полноэкранных блоков?
Только классические vw/vh
Уже перешёл на dvh/dvw
Комбинирую svh и dvh с fallback
Не знал о новых единицах

Сравнительная таблица: vw, svw, lvw, dvw

Соберём ключевые различия в одну таблицу, чтобы было проще выбирать единицу под конкретную задачу.

Единица От чего считается Меняется при скролле Типичное применение
vw Наибольший вьюпорт Нет Десктопные макеты, типографика
svw Наименьший вьюпорт Нет Элементы, которые не должны обрезаться
lvw Наибольший вьюпорт Нет Фоны, допускающие перекрытие панелями
dvw Текущий видимый вьюпорт Да Полноэкранные секции на мобильных

Обратите внимание: классический vw практически эквивалентен lvw, поэтому замена 100vw на 100lvw ничего не исправит — проблему перекрытия решают именно svw или dvw.

Когда какую единицу выбирать

Выбор зависит от того, что важнее в конкретном блоке: гарантированная видимость, стабильность размеров или использование всего доступного места. Универсального ответа нет, но есть рабочая логика подбора.

Используйте svw/svh, если контент обязан оставаться полностью видимым в любом состоянии браузера — например, экран с кнопкой действия или формой. Блок будет чуть меньше максимальной области, зато его нижняя часть никогда не уйдёт под панель навигации.

Берите dvw/dvh для полноэкранных секций, галерей и hero-блоков, где нужно занять всё доступное пространство. Учтите побочный эффект: при скролле размер блока меняется, и контент внутри может заметно перестраиваться. Для «тяжёлых» по компоновке блоков это иногда выглядит хуже, чем статичный svh.

💡

Для hero-секции часто оптимален компромисс: min-height: 100svh — блок гарантированно виден целиком, а при скрытии панелей браузера просто остаётся небольшой запас, который не бросается в глаза.

Классический vw остаётся уместным для задач, не связанных с высотой экрана: отзывчивая типографика через clamp(), отступы, пропорциональные ширине, декоративные элементы. Там перекрытие панелями браузера роли не играет.

Практический пример с fallback

Хотя поддержка динамических единиц в современных браузерах уже широкая, для старых версий стоит оставить запасной вариант. CSS позволяет сделать это элегантно: просто объявите два правила подряд — браузер, не знающий dvh, проигнорирует вторую строку и применит первую.

.hero {

height: 100vh; / fallback для старых браузеров /

height: 100dvh; / динамическая высота /

}

Тот же приём работает и для ширины. Важен порядок: сначала старая единица, затем новая, иначе переопределение не сработает.

☑️ Проверка вёрстки с dvw/dvh

Выполнено: 0 / 5
⚠️ Внимание: эмулятор устройств в DevTools не всегда воспроизводит автоматическое скрытие панелей мобильного браузера. Поведение dvw и dvh обязательно проверяйте на реальном смартфоне или в браузере с имитацией динамической панели инструментов — иначе разницу с vw вы просто не увидите.

Подводные камни и ограничения

Первая ловушка — перерисовка при скролле. Каждое изменение динамического вьюпорта заставляет браузер пересчитывать размеры всех элементов, привязанных к dvw/dvh. На страницах со сложной раскладкой это может сказываться на плавности, поэтому не стоит развешивать динамические единицы на десятки элементов без необходимости.

Вторая — несовпадение с JavaScript. Значения window.innerWidth и window.innerHeight ведут себя по-разному в зависимости от браузера и не всегда синхронны с тем, что отдаёт dvh в конкретный момент. Если логика критична, сверяйте оба источника на целевых устройствах, а не полагайтесь на предположения.

⚠️ Внимание: сочетание width: 100vw с вертикальным скроллбаром на десктопе — классическая причина горизонтальной прокрутки, потому что ширина скроллбара входит в vw. Замена на dvw эту проблему не решает: вместо этого используйте width: 100% для блочных контейнеров.
Почему 100vh на iOS долго был болью верстальщиков

В мобильном Safari значение 100vh исторически рассчитывалось от высоты вьюпорта без учёта нижней панели, из-за чего нижняя часть полноэкранных блоков оказывалась скрыта. Верстальщики годами обходили это скриптами с вычислением innerHeight и CSS-переменными. Появление svh и dvh дало нативное решение без JavaScript, и современные версии Safari эти единицы поддерживают.

Поддержка браузерами

Единицы svw, lvw и dvw поддерживаются актуальными версиями основных браузеров — Chrome, Safari, Firefox и Edge. Точные версии, с которых началась поддержка, различаются между движками, поэтому перед использованием в проекте с жёсткими требованиями к совместимости сверьтесь с актуальными таблицами поддержки, например на caniuse.com, по запросу «viewport unit variants».

Если аудитория проекта включает заметную долю устаревших браузеров, обязателен fallback через двойное объявление, как в примере выше. Это дешёвая страховка, не требующая ни скриптов, ни полифилов.

💡

Главное отличие vw от dvw: vw считается от наибольшего вьюпорта и не меняется при скролле, а dvw пересчитывается под реально видимую область с учётом панелей мобильного браузера.

Частые вопросы

Чем dvw отличается от svw?

svw всегда равен наименьшему вьюпорту (панели браузера развёрнуты) и не меняется при скролле. dvw плавает между наименьшим и наибольшим значением в зависимости от текущего состояния интерфейса браузера.

Нужно ли заменять все vw на dvw в существующем проекте?

Нет. Массовая замена оправдана только там, где есть реальная проблема: обрезанные полноэкранные блоки, прыгающая вёрстка на мобильных. Для типографики, отступов и декоративных элементов классический vw работает корректно.

Почему 100dvh всё равно обрезается на моём телефоне?

Возможные причины: браузер не поддерживает динамические единицы (проверьте версию), срабатывает fallback-строка из-за опечатки, либо обрезку создаёт не панель браузера, а что-то другое — например, overflow у родителя или фиксированный элемент поверх. Проверяйте на реальном устройстве, а не только в эмуляторе.

Есть ли динамические аналоги для vmin и vmax?

Да, спецификация включает dvmin/dvmax, а также svmin/svmax и lvmin/lvmax. Они работают по тому же принципу, но от меньшего или большего из двух измерений вьюпорта.

Влияет ли dvw на производительность страницы?

Каждое изменение динамического вьюпорта вызывает пересчёт размеров привязанных элементов. Для одного-двух полноэкранных блоков это незаметно, но если привязать к dvw/dvh множество элементов со сложной раскладкой, перерисовка при скролле может сказаться на плавности. Используйте динамические единицы точечно.