Прощай, обрезанный футер: Укрощаем вьюпорт с помощью dvh, lvh и svh
Признайся, сколько раз ты проклинал мобильный Safari? Ты верстаешь идеальный полноэкранный лендинг, ставишь секции height: 100vh, открываешь на iPhone и… твоя главная кнопка «Купить» стыдливо прячется под динамической панелью браузера. Пользователь пытается скроллить, панель то уменьшается, то увеличивается, контент прыгает, а ты сидишь и думаешь: «Ну почему 100% высоты экрана — это не 100% того, что я вижу?».
Это классическая боль, которая годами преследовала фронтенд-разработчиков. Проблема в том, что классическая единица vh (viewport height) в мобильных браузерах статична. Она рассчитывается один раз при загрузке страницы, исходя из максимально возможной высоты экрана, и плевать хотела на то, открыты сейчас табы или адресная строка. Но в 2026 году пора забыть об этом кошмаре.
Как мы страдали раньше: Эпоха костылей и JavaScript-хаков
До появления современных единиц измерения у нас было два пути, и оба вели в никуда. Первый — смириться. Второй — городить огород из JavaScript. Мы писали скрипты, которые высчитывали window.innerHeight, делили его на 100 и прокидывали это значение в CSS-переменную --vh. Выглядело это примерно так:
let vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
// И не забудь навесить обработчик на resize, чтобы всё не поехало!
window.addEventListener('resize', () => {
let vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
});
В CSS мы использовали это через height: calc(var(--vh, 1vh) * 100). Это работало, но вызывало микро-лаги при ресайзе и заставляло браузер лишний раз пересчитывать лейаут. Точно так же, как мы когда-то мучились с сетками до появления гридов (кстати, если хочешь копнуть глубже, почитай про скрытые возможности CSS Grid Layout), проблема с высотой вьюпорта требовала нативного и элегантного решения.
Как делать правильно в 2026 году
Спецификация CSS Values and Units Module Level 4 подарила нам три новые суперсилы, которые теперь поддерживаются всеми актуальными браузерами. Теперь нам не нужны скрипты, чтобы понять, сколько места на экране осталось на самом деле.
- svh (Small Viewport Height): Минимально возможная высота вьюпорта, когда все интерфейсы браузера (адресная строка, табы) максимально развернуты. Это твой «безопасный» вариант.
- lvh (Large Viewport Height): Максимальная высота, когда интерфейсы браузера скрыты. По сути, это старый добрый
vh, каким он задумывался изначально. - dvh (Dynamic Viewport Height): Самая умная единица. Она динамически меняется прямо в процессе скролла, подстраиваясь под текущее состояние интерфейса браузера.
Именно dvh — это тот самый «золотой стандарт» для создания Hero-секций. Он гарантирует, что твой контент всегда будет занимать ровно столько места, сколько видит пользователь в данный момент. Это так же важно для современного UI, как и грамотная адаптивная типографика с помощью функции clamp(): вы просто один раз задаете правила, а браузер берет всю рутину на себя.
Готовый сниппет кода
Вот как должен выглядеть современный полноэкранный блок, который не «сломается» в мобильном Safari и при этом будет иметь фоллбек для старых систем:
.hero-section {
/* Фоллбек для старых браузеров (Internet Explorer, мы тебя помним) */
height: 100vh;
/* Современный стандарт: динамическая высота */
height: 100dvh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, #6e8efb, #a777e3);
color: white;
padding: 2rem;
box-sizing: border-box;
}
.hero-title {
font-size: clamp(2rem, 5vw, 4rem);
text-align: center;
}
Частая ошибка новичков
Главный подвох dvh — это его избыточное использование. Помни, что dvh заставляет браузер пересчитывать размеры элементов при каждом изменении состояния интерфейса (когда пользователь начинает скроллить и адресная строка уезжает вверх). Если ты привяжешь к dvh размер шрифта или сложные параметры внутренних отступов у сотен элементов на странице, ты можешь получить неприятные «дергания» контента.
Совет от Senior-разработчика: Используй dvh только для контейнеров верхнего уровня (Hero-блоки, модальные окна, боковые меню). Для всего остального внутри этих контейнеров лучше использовать проценты или обычные относительные единицы. И всегда прописывай 100vh первой строкой как фоллбек — CSS просто проигнорирует dvh, если браузер его не понимает, и твой макет не развалится.
🔥 Больше фишек, готовых сниппетов и передовых подходов к CSS мы публикуем в нашем Telegram-канале. Подписывайтесь, чтобы не пропустить!