Как исправить скачок вверх страницы при открытии бургер-меню?

Ссылка скопирована
20 февраля 2026 1 ответ

Здравствуйте.

У верхней шапки сайта задал 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

  • Константин, стало немного понятней, спасибо.
  • у вас очень много проверок на undefined, старайтесь в 1 месте проверять
  • lil_koi, и это проблема? Проблема тут как раз в том, что автор не понимает когда надо, а когда ненадо проверять. У него подряд идут 3 обращения к бургеру и нулл чек только на двух из них.
    Или нул чек внутри листенера на сам бургер.
  • WbICHA, я в JS пока не силен. Это готовое решение от автора сборки.
  • Hypnos696, проблема как раз в том, что это НЕготовое решение.
  • WbICHA, я к тому, что он в каждой строчке делает проверку, что очень плохо. Это не ришит проблему, но сделает код чище. Ответ уже дали
  • lil_koi,

    что очень плохо

    И почему же это ОЧЕНЬ плохо? Тем более там половина чейннгов тупо ненужны от слова совсем.

  • Нашел в чем проблема.

    Во включении скрола.
    Нашел ответ в комментариях к этому видео:
    https://www.youtube.com/watch?v=TmVu9j7l0kI&ab_cha...

    Дело в строчке
    vars.htmlEl.style.scrollBehavior = 'smooth';

    В видео есть объяснение почему так сделано.

    Нужно решить такую задачу?

    Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

    Заказать помощь
    Лучший ответ
    1
    Ирина WP Ответ

    Для исправления скачка вверх страницы при открытии бургер-меню, можно использовать следующий подход:

    1. Используйте JavaScript для добавления класса к body при открытии бургер-меню, который будет предотвращать скролл страницы вверх. Например:

    document.querySelector('.burger-menu').addEventListener('click', function() {
      document.body.classList.toggle('no-scroll');
    });

    document.querySelector('.burger-menu').addEventListener('click', function() { document.body.classList.toggle('no-scroll'); });

    2. Добавьте стили для класса 'no-scroll', чтобы запретить скролл страницы:

    .no-scroll {
      overflow: hidden;
    }

    .no-scroll { overflow: hidden; }

    3. Убедитесь, что ваш бургер-меню не занимает место в документе при его скрытии. Для этого можно использовать свойство position: fixed или absolute для меню.

    4. Проверьте, что у вас нет других событий или скриптов, которые могут вызывать скачок страницы при открытии бургер-меню.

    Эти шаги помогут вам избежать скачка страницы при открытии бургер-меню и обеспечить более плавный пользовательский опыт.

    Другие ответы (0)

    Пока нет других ответов. Будьте первым, кто поможет автору.

    Ответить на вопрос

    комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Вам также может быть интересно