Как исправить скачок вверх страницы при открытии бургер-меню?
Здравствуйте.
У верхней шапки сайта задал position: fixed.
При открытии меню в любом месте на сайте, происходит скрол ("за кадром") наверх страницы.
При закрытии бургер-меню, страница скролится вниз до позиции на момент открытия меню.
Использую готовую сборку GULP с ютуба.
Бургер меню реализовано вот так:
import { disableScroll } from '../functions/disable-scroll'; import { enableScroll } from '../functions/enable-scroll'; (function(){ const burger = document?.querySelector('[data-burger]'); const menu = document?.querySelector('[data-menu]'); const menuItems = document?.querySelectorAll('[data-menu-item]'); const overlay = document?.querySelector('[data-menu-overlay]'); burger?.addEventListener('click', (e) => { burger?.classList.toggle('burger--active'); menu?.classList.toggle('menu--active'); if (menu?.classList.contains('menu--active')) { burger?.setAttribute('aria-expanded', 'true'); burger?.setAttribute('aria-label', 'Закрыть меню'); disableScroll(); } else { burger?.setAttribute('aria-expanded', 'false'); burger?.setAttribute('aria-label', 'Открыть меню'); enableScroll(); } }); overlay?.addEventListener('click', () => { burger?.setAttribute('aria-expanded', 'false'); burger?.setAttribute('aria-label', 'Открыть меню'); burger.classList.remove('burger--active'); menu.classList.remove('menu--active'); enableScroll(); }); menuItems?.forEach(el => { el.addEventListener('click', () => { burger?.setAttribute('aria-expanded', 'false'); burger?.setAttribute('aria-label', 'Открыть меню'); burger.classList.remove('burger--active'); menu.classList.remove('menu--active'); enableScroll(); }); }); })(); |
import { disableScroll } from '../functions/disable-scroll'; import { enableScroll } from '../functions/enable-scroll'; (function(){ const burger = document?.querySelector('[data-burger]'); const menu = document?.querySelector('[data-menu]'); const menuItems = document?.querySelectorAll('[data-menu-item]'); const overlay = document?.querySelector('[data-menu-overlay]'); burger?.addEventListener('click', (e) => { burger?.classList.toggle('burger--active'); menu?.classList.toggle('menu--active'); if (menu?.classList.contains('menu--active')) { burger?.setAttribute('aria-expanded', 'true'); burger?.setAttribute('aria-label', 'Закрыть меню'); disableScroll(); } else { burger?.setAttribute('aria-expanded', 'false'); burger?.setAttribute('aria-label', 'Открыть меню'); enableScroll(); } }); overlay?.addEventListener('click', () => { burger?.setAttribute('aria-expanded', 'false'); burger?.setAttribute('aria-label', 'Открыть меню'); burger.classList.remove('burger--active'); menu.classList.remove('menu--active'); enableScroll(); }); menuItems?.forEach(el => { el.addEventListener('click', () => { burger?.setAttribute('aria-expanded', 'false'); burger?.setAttribute('aria-label', 'Открыть меню'); burger.classList.remove('burger--active'); menu.classList.remove('menu--active'); enableScroll(); }); }); })();
Отключение скрола:
import vars from '../_vars'; export const disableScroll = () => { const fixBlocks = document?.querySelectorAll('.fixed-block'); const pagePosition = window.scrollY; const paddingOffset = `${(window.innerWidth - vars.bodyEl.offsetWidth)}px`; vars.htmlEl.style.scrollBehavior = 'none'; fixBlocks.forEach(el => { el.style.paddingRight = paddingOffset; }); vars.bodyEl.style.paddingRight = paddingOffset; vars.bodyEl.classList.add('dis-scroll'); vars.bodyEl.dataset.position = pagePosition; vars.bodyEl.style.top = `-${pagePosition}px`; } |
import vars from '../_vars'; export const disableScroll = () => { const fixBlocks = document?.querySelectorAll('.fixed-block'); const pagePosition = window.scrollY; const paddingOffset = `${(window.innerWidth - vars.bodyEl.offsetWidth)}px`; vars.htmlEl.style.scrollBehavior = 'none'; fixBlocks.forEach(el => { el.style.paddingRight = paddingOffset; }); vars.bodyEl.style.paddingRight = paddingOffset; vars.bodyEl.classList.add('dis-scroll'); vars.bodyEl.dataset.position = pagePosition; vars.bodyEl.style.top = `-${pagePosition}px`; }
Включение скрола:
import vars from '../_vars'; export const enableScroll = () => { const fixBlocks = document?.querySelectorAll('.fixed-block'); const body = document.body; const pagePosition = parseInt(vars.bodyEl.dataset.position, 10); fixBlocks.forEach(el => { el.style.paddingRight = '0px'; }); vars.bodyEl.style.paddingRight = '0px'; vars.bodyEl.style.top = 'auto'; vars.bodyEl.classList.remove('dis-scroll'); window.scroll({ top: pagePosition, left: 0 }); vars.bodyEl.removeAttribute('data-position'); vars.htmlEl.style.scrollBehavior = 'smooth'; } |
import vars from '../_vars'; export const enableScroll = () => { const fixBlocks = document?.querySelectorAll('.fixed-block'); const body = document.body; const pagePosition = parseInt(vars.bodyEl.dataset.position, 10); fixBlocks.forEach(el => { el.style.paddingRight = '0px'; }); vars.bodyEl.style.paddingRight = '0px'; vars.bodyEl.style.top = 'auto'; vars.bodyEl.classList.remove('dis-scroll'); window.scroll({ top: pagePosition, left: 0 }); vars.bodyEl.removeAttribute('data-position'); vars.htmlEl.style.scrollBehavior = 'smooth'; }
Опытным путем выяснил, что проблема возникает из-за свойства position: fixed, которое задается для body при отключении скрола, через класс:
.dis-scroll { position: fixed; left: 0; top: 0; overflow: hidden; width: 100%; height: 100vh; overscroll-behavior: none; } |
.dis-scroll { position: fixed; left: 0; top: 0; overflow: hidden; width: 100%; height: 100vh; overscroll-behavior: none; }
Собственно вопрос:
Как исправить данный момент?
Если убрать position: fixed, то ничего не ломается и все ок.
Но оно же там не просто так.
Я узнал что так нужно для исправления какого то бага на ios, но не уверен.
Как исправить понятно, но как исправить правильно?
Дополнительно:
Суть в том, что при открытии бургер меню, желательно остановить ручной скрол страницы (на заденем плане), особенно если у тебя бургер меню не влезает на экран и приходится его скролить. Чтобы предотвратить скролл страницы используют в body overflow: hidden;, но тогда мы имеем микро-скачек на заднем плане, это из-за появления скрола сбоку. Чтобы убрать этот микро-скачек добавляют в body еще position: fixed;.
Возникает проблема: страница прыгает вверх, и тогда, для этого делают на JS функции скрола.
Это не ответ на твой вопрос, я попытался объяснить зачем нужен position: fixed
Или нул чек внутри листенера на сам бургер.
что очень плохо
И почему же это ОЧЕНЬ плохо? Тем более там половина чейннгов тупо ненужны от слова совсем.
Нашел в чем проблема.
Во включении скрола.
Нашел ответ в комментариях к этому видео:
https://www.youtube.com/watch?v=TmVu9j7l0kI&ab_cha...
Дело в строчке
vars.htmlEl.style.scrollBehavior = 'smooth';
В видео есть объяснение почему так сделано.
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
Для исправления скачка вверх страницы при открытии бургер-меню, можно использовать следующий подход:
1. Используйте JavaScript для добавления класса к body при открытии бургер-меню, который будет предотвращать скролл страницы вверх. Например:
document.querySelector('.burger-menu').addEventListener('click', function() { document.body.classList.toggle('no-scroll'); });
2. Добавьте стили для класса 'no-scroll', чтобы запретить скролл страницы:
.no-scroll { overflow: hidden; }
3. Убедитесь, что ваш бургер-меню не занимает место в документе при его скрытии. Для этого можно использовать свойство position: fixed или absolute для меню.
4. Проверьте, что у вас нет других событий или скриптов, которые могут вызывать скачок страницы при открытии бургер-меню.
Эти шаги помогут вам избежать скачка страницы при открытии бургер-меню и обеспечить более плавный пользовательский опыт.