Фиксированное нижнее меню на мобильных: Полное решение
Узнайте, как исправить скачки фиксированного нижнего меню на мобильных устройствах. Откройте решения CSS и JavaScript Chrome, Edge и Safari, чтобы обеспечить работу.
Проблема с фиксированным нижним навбаром на мобильных устройствах
У меня возникает постоянная проблема с фиксированным нижним навбаром на мобильных устройствах (Chrome, Edge). Навбар работает корректно при первом загрузке страницы, когда видны верхняя и нижняя адресные панели браузера. Однако при прокрутке вниз, когда браузер скрывает эти панели, навбар временно прилипает к нижней панели браузера, а затем перемещается вверх в позицию, где была нижняя панель браузера до этого.
Проблема не проявляется постоянно, а перезагрузка страницы не решает её. Единственный обходной путь — открыть новую вкладку, загрузить любой сайт, а затем вернуться к исходному сайту.
Технические детали
Я воспроизвел эту проблему в простом проекте Webflow со следующим кодом:
CSS
body {
color: #333;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
font-size: 14px;
line-height: 20px;
}
.content {
height: 2000px;
}
.mobile-bottom-bar {
background-color: red;
height: 100px;
position: fixed;
inset: auto 0% 0%;
}
.body {
background-color: #c3b090;
}
HTML
<body class="body">
<div class="content">
<div class="mobile-bottom-bar"></div>
</div>
<script src="https://d3e54v103j8qbb.cloudfront.net/js/jquery-3.5.1.min.dc5e7f18c8.js?site=66e6aae80c3090deccf29113" type="text/javascript" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="js/webflow.js" type="text/javascript"></script>
</body>
Демонстрация и видео
Я создал демонстрацию этого поведения:
- Видео демонстрация: https://www.youtube.com/shorts/P8qGtCBIvcg
- Live demo: https://test-6e1b82-be73db351802bdf0ab92cfa344a.webflow.io/
Вопрос
Кто-нибудь сталкивался с этой проблемой фиксированных нижних навбаров на мобильных устройствах? Что может вызывать такое поведение и как это исправить? Я пробовал различные решения на CSS и JavaScript, но безуспешно.
Проблема фиксированного нижнего навбара на мобильных устройствах, с которой вы сталкиваетесь, является хорошо задокументированной и связана с динамическими изменениями высоты окна просмотра и поведением браузера во время прокрутки. Это происходит, когда мобильные браузеры автоматически скрывают адресную строку во время прокрутки, что приводит к изменению высоты окна просмотра и влияет на элементы с фиксированным позиционированием.
Содержание
- Понимание причины
- Решения с единицами viewport
- Обходные решения с позиционированием CSS
- Решения на JavaScript
- Фиксированные решения для конкретных браузеров
- Лучшие практики для фиксированных нижних навбаров
- Тестирование и проверка
Понимание причины
Проблема возникает из того, как мобильные браузеры обрабатывают единицы viewport, когда их адресные строки автоматически скрываются во время прокрутки. Как объясняет CSS‑Tricks, видимая область динамически меняется при прокрутке, что может сбивать с толку элементы с фиксированным позиционированием.
Согласно обсуждениям на Stack Overflow, это поведение проявляется именно тогда, когда:
- Страница загружается с видимой адресной строкой браузера
- Прокрутка заставляет браузер скрыть адресную строку
- Высота окна просмотра меняется, влияя на расчёты фиксированного позиционирования
- Фиксированные элементы временно «приклеиваются» к chrome браузера во время этого перехода
Решения с единицами viewport
Самое эффективное решение — использовать динамические единицы viewport (dvh) вместо стандартных единиц (vh). Как отмечено в одном ответе на Stack Overflow:
:root {
height: 100dvh;
}
body {
height: 100%;
margin: 0;
padding: 0;
}
.mobile-bottom-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100px;
background-color: red;
}
Единица 100dvh динамически корректируется под текущую высоту окна просмотра, включая момент скрытия/показа адресной строки во время прокрутки. Это предотвращает скачки позиционирования, которые вы наблюдаете.
Обходные решения с позиционированием CSS
Альтернативный подход к позиционированию
Из обсуждений сообщества TeamTreehouse ещё одно решение — избегать конфликтующих значений позиционирования:
.mobile-bottom-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100px;
background-color: red;
/* Избегайте установки top:0 при использовании bottom:0 */
top: auto !important;
}
Z‑index и контекст наложения
Согласно блогу Steve Fenton, добавление пустого фиксированного элемента может помочь вызвать правильное поведение браузера:
/* Добавьте это, чтобы вызвать поведение браузера */
.viewport-trigger {
position: fixed;
top: 0;
left: 0;
width: 1px;
height: 1px;
z-index: -1;
}
.mobile-bottom-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100px;
background-color: red;
z-index: 1000;
}
Решения на JavaScript
Обработка события прокрутки
Более динамический подход включает JavaScript для обработки событий прокрутки и корректировки позиционирования:
document.addEventListener('DOMContentLoaded', function() {
const navbar = document.querySelector('.mobile-bottom-bar');
let lastScrollTop = 0;
window.addEventListener('scroll', function() {
let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
// Применять исправление только на мобильных устройствах
if (window.innerWidth <= 768) {
// Принудительно вызвать рефлоу для пересчёта
navbar.style.display = 'none';
void navbar.offsetHeight; // Принудительный рефлоу
navbar.style.display = 'block';
}
lastScrollTop = scrollTop;
});
});
Динамическая корректировка высоты
Исходя из исследований, вы также можете динамически корректировать позицию навбара в зависимости от изменений окна просмотра:
// Обработка изменений высоты окна просмотра
const resizeObserver = new ResizeObserver(entries => {
for (let entry of entries) {
if (entry.target === document.documentElement) {
const navbar = document.querySelector('.mobile-bottom-bar');
if (navbar) {
// Принудительно перенастроить позицию
navbar.style.bottom = '0px';
}
}
}
});
resizeObserver.observe(document.documentElement);
Фиксированные решения для конкретных браузеров
Специфические решения для Chrome и Edge
Как отмечено в обсуждениях сообщества ServiceNow, некоторые CSS‑исправления работают только для Chrome и Edge:
/* Специфические исправления для Chrome/Edge */
@supports (-webkit-touch-callout: none) {
.mobile-bottom-bar {
position: fixed;
bottom: env(safe-area-inset-bottom, 0);
left: 0;
right: 0;
height: 100px;
background-color: red;
}
}
Учитывая iOS Safari
Для iOS Safari, как упомянуто в обсуждениях на Reddit, убедитесь, что вы используете правильные метатеги viewport:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
Лучшие практики для фиксированных нижних навбаров
Полный пример решения
Комбинируя несколько подходов для надёжного решения:
/* Сброс и базовые стили */
:root {
height: 100dvh;
}
body {
height: 100%;
margin: 0;
padding: 0;
background-color: #c3b090;
}
/* Область контента с правильным отступом */
.content {
min-height: 100vh;
padding-bottom: 100px; /* Предотвращает скрытие контента под навбаром */
}
/* Фиксированный нижний навбар с несколькими исправлениями */
.mobile-bottom-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100px;
background-color: red;
z-index: 1000;
transform: translateZ(0); /* Принудительная аппаратная активация */
will-change: transform;
/* Для устройств с вырезами/округлёнными углами */
padding-bottom: env(safe-area-inset-bottom, 0);
}
/* Добавляем триггер окна просмотра для совместимости браузеров */
.viewport-trigger {
position: fixed;
top: 0;
left: 0;
width: 1px;
height: 1px;
z-index: -1;
}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>Демонстрация фиксированного нижнего навбара</title>
<style>
/* Добавьте CSS из вышеуказанного примера */
</style>
</head>
<body>
<div class="viewport-trigger"></div>
<div class="content">
<div class="mobile-bottom-bar"></div>
<!-- Ваш контент здесь -->
</div>
<script>
// Добавьте JavaScript из вышеуказанного примера
</script>
</body>
</html>
Тестирование и проверка
Чтобы убедиться, что ваше решение работает на разных устройствах и браузерах:
- Тестируйте на нескольких устройствах: Android Chrome, iOS Safari, Edge Mobile
- Тестируйте различные сценарии:
- Загрузка страницы с видимой адресной строкой
- Поведение при прокрутке
- Перезагрузка страницы
- Переключение вкладок
- Используйте инструменты разработчика браузера: имитируйте различные устройства и следите за изменениями макета
- Мониторьте производительность: убедитесь, что исправления не вызывают проблем с производительностью
Ключевой вывод — поведение мобильных браузеров с фиксированными элементами во время изменений высоты окна просмотра сложное и часто требует комбинации CSS‑ и JavaScript‑решений. Подход с динамическими единицами viewport (dvh) в сочетании с правильным позиционированием и триггерами окна просмотра должен решить нестабильное поведение, которое вы наблюдаете.