При закрытии модального окна страница прокручивается вверх

Обновлено: 24.04.2024

После скроллинга и закрытия модального окна пользователь попадает на совершенно другое место на странице. Потому что содержимое страницы перемещается вслед за скроллингом.

Но это можно предотвратить с помощью приемов CSS и JavaScript.

Начнем с чего-нибудь простого

Можно помешать перелистыванию станицы при открытом модальном окне, установив высоту модального окна на полную высоту области просмотра и используя overflow-y: hidden при открытом модальном диалоге:

Но если перед открытием модального окна мы уже перешли к содержимому , то получим небольшое горизонтальное смещение.

Чтобы избежать этого, зададим правый отступ элемента body.

Чтобы все работало, модальное окно должно быть меньше, чем высота области просмотра. Иначе на странице появится полоса прокрутки.

Как на счет мобильной версии?

Данное решение отлично работает как на ПК, так и на Android. Но в браузере Safari для iOS не все так гладко. Потому что содержимое страницы все еще прокручивается при открытом модальном диалоге.

В качестве обходного пути можно установить элемент body в position: fixed:

Но осталась еще одна маленькая проблема. Предположим, что кнопка открытия modal находится внизу страницы и мы кликаем ее. Но из-за этого мы возвращаемся обратно в верхнюю часть экрана.

Необходимо обратиться к JavaScript

Мы можем использовать JavaScript, чтобы избежать проблемы с событием касания. Метод stopPropagation некорректно работает при обработке касания в устройствах на iOS. Но зато метод preventDefault действует отлично. Это означает, что нам необходимо добавить обработчик событий к каждому узлу DOM модального окна. Это можно реализовать с помощью jQuery.

Улучшим подход с фиксированным элементом body

Вот с чем мы работали:

Если мы знаем позицию верхней части прокрутки и используем ее в CSS, тогда элемент body не будет прокручиваться обратно к началу экрана. Для реализации можно применить JavaScript:

Но еще осталась одна проблема. На странице изменяется положение скроллинга при открытом диалоге и зафиксированном body. Поэтому нужно восстановить расположение ползунка прокрутки. Чтобы разобраться с проблемой, изменим код JavaScript.

Теперь содержимое body больше не прокручивается при открытом модальном окне, а положение скроллинга сохраняется.

Дайте знать, что вы думаете по этой теме материала в комментариях. За комментарии, лайки, дизлайки, отклики, подписки огромное вам спасибо!

Пожалуйста, опубликуйте ваши мнения по текущей теме статьи. За комментарии, подписки, дизлайки, отклики, лайки огромное вам спасибо!

Я пытался вызвать фрагмент javascript ниже при открытии модального окна, но безуспешно

Обратите внимание, что наш веб-сайт отказался от поддержки IE6, хотя IE7 + должен быть совместимым.



Bootstrap modal автоматически добавляет класс modal-open в тело, когда отображается модальный диалог, и удаляет его, когда диалог скрыт. Поэтому вы можете добавить в свой CSS следующее:

Вы можете утверждать, что приведенный выше код принадлежит базе кода CSS Bootstrap, но это простое решение, позволяющее добавить его на свой сайт.

Обновление от 8 февраля 2013 г.
Теперь это перестало работать в Twitter Bootstrap v. 2.3.0 - они больше не добавляют modal-open класс в тело.

Обходной путь - добавить класс в тело, когда модальное окно будет показано, и удалить его, когда модальное окно закрыто:

Обновление 11 марта 2013 г. Похоже, что modal-open класс вернется в Bootstrap 3.0 явно с целью предотвращения прокрутки:

Reintroduces .modal-open on the body (so we can nuke the scroll there)


@Bagata Cool - modal-open вернется в Bootstrap 3, поэтому при его запуске можно безопасно удалить приведенный выше код.

Вот почему нужно продолжать прокрутку вниз, если выбранный ответ вас не устраивает, есть вероятность, что вы найдете такие драгоценные камни. не ожидал, что ответ с более чем 97 голосами будет похоронен так глубоко под другими менее понравившимися комментариями.

проблема в том, что для предотвращения прокрутки документа вверх при открытии модального окна вам нужно было добавить body.modal-open . В настоящий момент ваше решение работает, но с обратной стороной - документ прокручивается вверх после открытия модального окна.

Принятый ответ не работает на мобильных устройствах (по крайней мере, iOS 7 с Safari 7), и я не хочу, чтобы MOAR JavaScript работал на моем сайте, когда будет работать CSS.

Этот CSS предотвратит прокрутку фоновой страницы под модальным окном:

Тем не менее, у него также есть небольшой побочный эффект, связанный с прокруткой вверх. position:absolute решает эту проблему, но вновь вводит возможность прокрутки на мобильном устройстве.

Я также добавляю это, чтобы нижележащая страница не прыгала влево / вправо при отображении / скрытии модальных окон.


Спасибо! Мобильные телефоны (по крайней мере, собственный браузер iOS и Android) вызывали у меня головную боль и не работали бы без них position: fixed .

Спасибо, что также включили код для предотвращения перехода страницы влево / вправо при отображении / скрытии модальных окон. Это было чрезвычайно полезно, и я убедился, что это решает проблему, с которой я столкнулся в Safari на iPhone 5c под управлением iOS 9.2.1.

Хотя я считаю, что это подойдет только для самых элементарных нужд, это было полезное исправление. Спасибо.

Вот как я сделал это, чтобы сохранить позицию прокрутки с помощью jquery: js const currPageScrollPos = $(window).scrollTop() $("body").removeClass("show_overlay") $(window).delay(5).scrollTop(currPageScrollPos)

Просто скройте переполнение тела, и оно не будет прокручиваться. Когда вы скрываете модальное окно, верните его к автоматическому.

Вы можете попробовать установить размер тела в соответствии с размером окна с помощью overflow: hidden, когда модальное окно открыто

при этом экран будет перемещаться каждый раз при открытии модального окна, что неудобно, мне просто нужно отключить фоновую прокрутку

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

Дело не в том, чтобы остановить прокрутку модального окна, а в том, чтобы остановить прокрутку тела в фоновом режиме

это окно, которое прокручивается, если тело переполняет его. Например, полосы прокрутки не являются частью документа.

Вам нужно выйти за рамки ответа @ charlietfl и учитывать полосы прокрутки, иначе вы можете увидеть перекомпоновку документа.

Открытие модального окна:

  1. Запишите body ширину
  2. Установить body переполнение на hidden

Явно установите ширину тела, которая была на шаге 1.

Закрытие модального окна:

Установить body ширину на auto

Я получал "дергающийся" экран из-за отсутствия лучшего термина, и ключевым моментом здесь для меня было соблюдение настроек ширины. Благодаря тонну.

О боже, какая чудесная идея. @jpap, вы помогли мне решить проблему перекомпоновки документов, которая долго меня беспокоила.

Предупреждение: Опция ниже не имеет отношения к Bootstrap v3.0.x, поскольку прокрутка в этих версиях была явно ограничена самим модальным окном. Если вы отключите события колеса, вы можете случайно запретить некоторым пользователям просматривать контент в модальных окнах, высота которых превышает высоту области просмотра.

Еще один вариант: события колеса

Прокрутки событие не отменяемое. Однако можно отменить события колеса мыши и колеса мыши. Большое предостережение заключается в том, что не все устаревшие браузеры поддерживают их, Mozilla только недавно добавила поддержку последнего в Gecko 17.0. Я не знаю полного распространения, но IE6 + и Chrome их поддерживают.

Вот как их использовать:

JSFiddle

@AxeEffect теперь должен работать. Единственная проблема заключалась в том, что внешние ссылки на библиотеку Bootstrap изменились. Спасибо за внимание.

@TowerJimmy, вам, вероятно, нужно отменить события касания или перетаскивания для этого (если это вообще возможно)

Не удалось заставить его работать в Chrome, просто изменив CSS, потому что я не хотел, чтобы страница прокручивалась обратно вверх. Это сработало нормально:

Была проблема с переходом на вершину с сайдингом из угловатых материалов. Это был единственный ответ, который, похоже, работает во всех случаях (рабочий стол / мобильный + разрешить прокрутку в модальном / боковом меню + оставить фиксированное положение прокрутки тела без прыжков).

Попробуй это:

у меня это сработало. (поддерживает IE8)


Это работает, но также заставляет вас переходить наверх при открытии модального окна при использовании position: fixed .

Добавление класса is-modal-open или изменение стиля тега body с помощью javascript - это нормально, и он будет работать должным образом. Но проблема, с которой мы столкнемся, - это когда тело становится переполненным: скрытым, оно перескакивает наверх (scrollTop станет 0). Позже это станет проблемой для удобства использования.

В качестве решения этой проблемы вместо изменения тега body overflow: hidden измените его на теге html.

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

По состоянию на ноябрь 2017 г. в Chrome появилось новое свойство css.

который решает эту проблему, хотя на момент написания имеет ограниченную кроссбраузерную поддержку.

см. ссылки ниже для получения полной информации и поддержки браузера

For Bootstrap, you might try this (working on Firefox , Chrome and Microsoft Edge ) :

Надеюсь это поможет.


Я не уверен насчет этого кода, но попробовать стоит.

Как я уже сказал, я не уверен на 100%, но все равно попробуйте.

@xorinzor вы указали в разделе комментариев ответа charlietfl, что это работает. Но вы сказали: это не предотвращает прокрутку тела при открытом модальном окне.

правда, но на данный момент это единственное решение, которое частично работает, и меня устраивает. Причина, по которой я пометил его ответ как ответ, состоит в том, что он раньше давал ответ.

@xorinzor правда, я думал, что ответил раньше него / нее, может быть какой-то странный глюк. это нормально, хотя

Ознакомьтесь с этим jsFiddle, чтобы увидеть, как он используется.

Это не так уж и давно, но у меня ничего из этого не работает, даже скрипка. Я все еще могу прокручивать окно, что мне не хватает?

@smhmic примерно через 20 раз открытия и закрытия ширина зеленого div становится равной open modal ширине кнопок. Chrome на 8

Чтобы страница не перескакивала вверх, а также предотвращала сдвиг содержимого вправо, добавьте класс к классу, body когда модальное окно запущено, и установите следующие правила CSS:

Это position:static и то, height:auto что объединяется, чтобы остановить скачок содержимого вправо. overflow-y:hidden; Останавливает страницу от того , прокручивать за модальным.

Многие предлагают "переполнение: скрыто" на теле, что не сработает (по крайней мере, в моем случае), поскольку заставит веб-сайт прокрутиться вверх.

Это решение, которое работает для меня (как на мобильных телефонах, так и на компьютерах) с использованием jQuery:

Это заставит прокрутку модального окна работать и предотвратит одновременную прокрутку веб-сайта.

Вы можете использовать следующую логику, я ее протестировал, и она работает (даже в IE)

следующий фрагмент (с использованием jquery) отключит прокрутку окна:

Теперь, когда вы удаляете модальное окно, не забудьте удалить класс noscroll в теге html:

Разве overflow нельзя установить на hidden ? +1 хотя, как это сработало для меня (используя hidden ).

В моей ситуации веб-страница изначально имеет полосу прокрутки. Всякий раз, когда я нажимаю модальное окно, полоса прокрутки не исчезает, а заголовок немного сдвигается вправо.

Затем я попытался добавить .modal-open (что рекомендовало большинство). Это действительно устранило проблемы: полоса прокрутки появляется после того, как я открываю модальное окно. Однако появляется еще один побочный эффект: «фон под заголовком немного сместится влево вместе с еще одной длинной полосой позади модального окна».

Длинная полоса за модальным окном

К счастью, после добавления все исправлено идеально. Фон заголовка и тела не сдвинулся, а в модальном окне все еще сохраняется полоса прокрутки.

Фиксированное изображение

Надеюсь, это поможет тем, кто все еще сталкивается с этой проблемой. Удачи!


Бывало у вас такое? Открываете модальное окно, прокручиваете, а после закрытия оказываетесь на странице в позиции, отличающейся от той, с которой его открывали.

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

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

При открытии модального окна можно просто устанавливать элемент body по высоте равным области видимости (viewport) и скрывать вертикальную прокрутку:

Решение имеет право на существование, но если перед открытием модального окна мы прокрутим элемент body , получим небольшую перерисовку содержимого. Ширина области видимости расширяется приблизительно на 15px, что соответствует ширине полосы прокрутки.

Давайте немного отрегулируем правый padding для body , чтобы избежать этого.

Обратите внимание – чтобы это сработало, модальное окно должно быть по высоте меньше области видимости. Иначе полоса прокрутки будет нужна.

Это решение отлично работает как на десктопах, так и на мобильных Android-устройствах. Однако, Safari для iOS требует немного больше внимания, поскольку body всё ещё может прокручиваться, когда модальное окно открыто.

Как альтернатива, мы можем задать для body фиксированное позиционирование.

Работает. Теперь body не будет реагировать на свайпы по экрану. Тем не менее, небольшая проблема всё же остаётся. Если кнопка, открывающая модальное окно, находится внизу страницы и чтобы её увидеть, нужно прокручивать страницу, при нажатии на эту кнопку и открытии модального окна, будет происходить автоматическая прокрутка страницы вверх, что может дезориентировать так же, как и фоновая прокрутка body , от которой мы пытаемся избавиться.

Можем использовать JavaScript, чтобы избежать всплытия события прикосновения к экрану. Все мы знаем, что при открытии модального окна, у него должен быть фоновый слой. К сожалению, в iOS метод stopPropagation() с событиями прикосновения работает немного неуклюже. Но у preventDefault() таких проблем нет. Это значит, что мы должны добавить обработчики событий к каждому DOM-элементу внутри модального окна, а не только к слою подложки или самому модальному окну. Хорошая новость в том, что много JavaScript-библиотек могут делать это, включая старый добрый jQuery.

Ах да, и ещё кое-что. Что если нам нужна прокрутка внутри модального окна? Нам всё ещё нужно вызвать реакцию на событие свайпа, но при достижении верха или низа модального окна, нам всё ещё нужно предотвращать всплытие. Кажется очень сложным (?? так что мы ещё не полностью выкарабкались).

Вот с чем мы работали:

С помощью JavaScript можно вычислить положение прокрутки страницы, и добавлять это значение в CSS. Благодаря этому body не будет прокручиваться обратно в начальную позицию.

Данное решение работает, но после закрытия окна всё ещё происходит небольшой сдвиг. А именно, похоже, когда модальное окно открыто и для body задано фиксированное позиционирование, страница уже теряет положение прокрутки. Следовательно, нам нужно восстановить положение. Давайте изменим JavaScript, чтобы учитывать этот момент.

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

Вёрстка таких окон сначала кажется простой задачей. Модальные окна можно сделать даже без помощи JS только лишь с помощью CSS, но на практике они оказываются неудобными, и из-за маленьких недочетов модальные окна раздражают посетителей сайта.

В итоге было задумано сделать собственное простое решение.


Вообще говоря, есть несколько готовых скриптов, JavaScript библиотек, реализующих функционал модальных окон, например:

  • Arctic Modal,
  • jquery-modal,
  • iziModal,
  • Micromodal.js,
  • tingle.js,
  • Bootstrap Modal (из библиотеки Bootstrap) и др.

(в статье не рассматриваем решения на базе Frontend-фреймворков)

Несколькими из них я пользовался сам, но почти у всех находил какие-то недостатки. Некоторые из них требуют подключения библиотеки jQuery, которая есть не на всех проектах. Для разработки своего решения, нужно сначала определиться с требованиями.

Что мы ждём от модальных окон? Отвечая на этот вопрос, я основывался на докладе «Знакомьтесь, модальное окно» Анны Селезнёвой, а так-же на относительно старой статье NikoX «arcticModal — jQuery-плагин для модальных окон».

Итак, чтобы нам хотелось видеть?

Дисклеймер: Прежде чем мы рассмотрим подробности, сразу дам ссылку на готовый код получившейся библиотеки (HystModal) на GitHub, а также ссылку на демо+документацию.

Начнём с разметки.

1. Разметка HTML и CSS

1.1. Каркас модальных окон

Как открыть окно быстро? Самое простое решение: разместить всю разметку модального окна сразу в HTML странице. Затем скрывать/показывать это окно при помощи переключения классов CSS.

Набросаем такую разметку HTML (я назвал этот скрипт «hystmodal»):

Сделаем так, чтобы .hystmodal растягивался на всё окно браузера и закрывал собой содержимое страницы. Чтобы этого добиться, установим фиксированное позиционирование в CSS и приравняем свойства top, bottom, left и right к нулю.

В этом коде сделаны ещё две вещи:

  1. Так как мы хотим центрировать окно внутри страницы, превращаем .hystmodal в flex-контейнер с выравниваем его потомков по центру по вертикали и горизонтали.
  2. Окно может быть больше высоты экрана браузера, поэтому мы устанавливаем overflow-y: auto , чтобы при переполнении возникала полоса прокрутки. Также, для сенсорных экранов (в основном для Safari) нам стоит установить свойство -webkit-overflow-scrolling: touch , чтобы сенсорная прокрутка работала именно на этом блоке а не на странице.

Теперь установим стили для самого окна.

Кажется возникли сложности.

Проблема №1. Если высота окна больше высоты окна браузера, то контент окна будет обрезан сверху.


Это возникает из-за свойства justify-content: center . Оно позволяет нам удобно выровнять потомков по основной оси (по вертикали), но если потомок становится больше родителя то часть его становится недоступной даже при прокручиваемом контейнере. Подробнее можно посмотреть на stackoverflow. Решение – установить justify-content: flex-start , а потомку установить margin:auto . Это выровняет его по центру.

Проблема №2. В ie-11 если высота окна больше высоты окна браузера, то фон окна обрезается.

Решение: мы можем установить flex-shrink:0 потомку – тогда обрезки не происходит.

Проблема №3. В браузерах кроме Chrome нет отступа от нижней границы окна (т.е. padding-bottom не сработал).

Сложно сказать баг это браузеров или наоборот соответствует спецификации, но решения два:

  • установить псевдоэлемент ::after после потомка и дать ему высоту вместо padding
  • обернуть элемент в дополнительный блок и дать отступы уже ему.

Воспользуемся вторым методом. Добавим обертку .hystmodal__wrap . Так мы заодно обойдём и проблему №1, а вместо padding у родителя установим margin-top и margin-top у самого .hystmodal__window .

Наш итоговый html:

В код также добавлены некоторые aria и role атрибуты для обеспечения доступности.

Обновленный код CSS для обертки и окна.

1.2 Скрываем окно

Сейчас наше окно всегда видно. Когда говорят о скрытии элементов, первое что приходит на ум это переключать свойство display со значения none до нашего значения flex.

Но этот подход нас не устроит, ведь свойство display не анимируется. Все переходы дочерних элементов, указанные в свойстве transition, работать не будут.

Нам поможет другое свойство visibility:hidden . Оно скроет окно визуально, хотя и зарезервирует под него место. А так как все будущие окна на странице имеют фиксированное
позиционирование – они будут полностью скрыты и не повлияют на остальную страницу. Кроме того, на элементы с visibility:hidden нельзя установить фокус с клавиатуры, а от скрин-ридеров мы уже скрыли окна с помощью атрибута aria-hidden="true" .

Добавим также классы для открытого окна:

1.3 Оформление подложки

В лучшем случае, нам нужен отдельный html-элемент в качестве оверлея. Можно использовать и имеющийся элемент модального окна .hystmodal в качестве оверлея, но тогда анимация на этом элементе (например переход opacity) будет затрагивать и внутренние элементы. В итоге, не получится анимировать разные свойства для окна и оверлея отдельно.

Просто разместим элемент .hystmodal__shadow прямо перед закрывающим . В будущем, сделаем так, чтобы этот элемент создавался автоматически из js при инициализации библиотеки.

1.4 Отключение прокрутки страницы

Когда модальное окна открывается, мы хотим, чтобы страница под ним не прокручивалась.
Самый простой способ этого добиться — повесить overflow:hidden для body или html, когда окно открывается. Однако с этим есть проблема:

Проблема №4. В браузере Safari на iOS страница будет прокручиваться, даже если на тег html или body повешен overflow:hidden .
Решается двумя способами, либо блокированием событий прокрутки (touchmove, touchend или touchsart) из js вида:

Однако при этом блокируется и прокрутка самого модального окна, а также все прокручиваемые блоки внутри окна, если они будут. Требуется дополнительные проверки селекторов из js, что приводит к усложнению кода, поэтому рассмотрим другой вариант.

ps: можно конечно применить библиотеку scroll-lock, в которую заложено это решение, но в статье было решено воспользоваться другим вариантом.

Другое решение – основано частично на CSS. Пусть когда окно открывается, на элемент будет добавляться класс .hystmodal__opened :

Благодаря position:fixed , окно не будет прокручиваться даже в safari, однако здесь тоже не всё гладко:

Проблема №5. При открытии/закрытии окна страница прокручивается в начало.
Действительно, это происходит из-за изменения свойства position, текущая прокрутка окна сбрасывается.

Для решения, нам нужно написать следующий JS (упрощенно):

При открытии:

При закрытии:

Отлично, приступим к JavaScript коду.

2. Код JavaScript

2.2 Каркас библиотеки

Нам нужна совместимость со старыми браузерами включая IE11 поэтому нам нужно выбрать из 2 вариантов кодинга:

  • Разрабатывать на старом стандарте ES5, и использовать только те фичи, которые поддерживают все браузеры.
  • Применить современный синтаксис ES6, но подключить транспайлер Babel, который автоматически преобразует код для всех браузеров и встроит необходимые полифилы.
    Было принято решение использовать второй вариант, с прицелом на будущее.
    Приступим.

Основа нашей библиотеки единственный класс HystModal . Ниже я приведу скелет кода с комментариями, а потом добавим остальной функционал.

Итак, мы описали класс HystModal . Чтобы всё работало, нужно всего лишь подключить наш скрипт и создать экземпляр класса:

Проблема №6: если в браузере есть фиксированный скроллбар (который влияет на ширину страницы), то при открытии/закрытии окна происходит сдвиг контента, когда полоса прокрутки то появляется то пропадает.

Действительно – скроллбар пропадает и контент страницы перераспределяется. Чтобы решить эту проблему, можно добавить отступ справа к тегу html, равный ширине скроллбара когда он пропадает.

Однако ширина скроллбара может быть разной в разных браузерах и операционных системах. Кроме того, скроллбара может не быть на коротких страницах или он может быть плавающим (например, в Chrome на Android). Поэтому ширину нужно вычислять динамически из скрипта.

Дополним метод _bodyScrollControl()

Почему код метода close() упрощён? Дело в том, что просто убирая классы CSS у элементов, мы не можем анимировать закрытие окна.

Проблема №7. При закрытии окна, свойство visibility:hidden применяется сразу и не даёт возможности анимировать закрытие окна.

Причина этого известна: свойство visibility:hidden не анимируется. Конечно, можно обойтись без анимации, но, если она нужна, сделаем следующее.

  • Создадим дополнительный CSS-класс .hystmodal—moved почти такой-же как и .hystmodal--active
  • Затем при закрытии сначала добавим этот класс к окну и повесим обработчик события «transitionend» на модальном окне. Затем удалим класс `.hystmodal—active , таким образом вызывая css-переход. Как только переход завершится, сработает обработчик события «transitionend», в котором сделаем всё остальное и удалим сам обработчик события.

Ниже: новая версия методов закрытия окна:

Вы заметили, что мы создали ещё один метод _closeAfterTransition() и перенесли основную логику закрытия туда. Это нужно, чтобы удалить обработчик события transitionend после закрытия окна, ведь в метод removeEventListener необходимо передать именно ту функцию, которую мы привязывали.

Кроме того, если анимация не будет нужна, можно просто вызвать this._closeAfterTransition() не вешая его на событие.

Как мы помним, внутри addEventListener, this будет указывать на селектор где происходит событие, а не на наш экземпляр класса, поэтому в конструкторе нужно добавить ещё одну строчку для жёсткой привязки метода к this.

2.2 Закрытие окна по клику на оверлей

Нам нужно обработать ещё одно событие – закрытие окна по клику на элемент подложки .hystmodal__wrap . Мы можем повесить обработчик клика на документ для делегирования события как при открытии и проверить что событие произошло на .hystmodal__wrap примерно так:

Это будет работать, но есть один малозаметный недостаток.

Проблема №8. Если кнопку мыши нажать внутри окна, а отпустить за его пределами (над подложкой), окно закрывается.

Представьте, что в окне форма. Вы выделяете текст в поле ввода и случайно двигаете мышь чуть дальше, курсор заходит на подложку и вдруг окно закрывается, всё вдруг пропадает из виду. Не хотелось бы, чтобы так было.

Окно закрывается потому что по спецификации, если нажатие и отпускание мыши были на разных элементах, то событие click сработает на самом ближайшем общем для них элементе, а у нас это как раз .hystmodal__wrap .

Мы могли бы решить это изменением html, добавляя ещё один div сразу после .hystmodal__window и размещая его визуально под окном. Но нам бы не хотелось добавлять лишний пустой div ещё сильнее усложняя разметку.

Мы можем разбить наш addEventListener на два отдельных обработчика: для событий mousedown и mouseup и будем проверять чтобы оба события происходили именно на .hystmodal__wrap . Добавим новые обработчики событий в наш метод eventsFeeler()

2.3 Управление фокусом

У нас заготовлено два метода для управления фокусом: focusContol() для переноса фокуса внутрь окна и обратно при его закрытии, а также focusCatcher(event) для блокирования ухода фокуса из окна.

Решения для фокуса были реализованы аналогично js-библиотеке «Micromodal» (Indrashish Ghosh). А именно:

1. В служебный массив сохраним все css селекторы на которых может быть установлен фокус (свойство помещаем в init()):

2. В методе focusContol() находим первый такой селектор в окне и устанавливаем на него фокус, если окно открывается. Если же окно закрывается – то переводим фокус на this.starter :

3. В методе focusCatcher() находим в окне и превращаем в массив коллекцию всех элементов на которых может быть фокус. И проверяем, если фокус должен был выйти на пределы окна, то вместо этого устанавливаем фокус снова на первый или последний элемент (ведь фокус можно переключать как по Tab так и по Shift+Tab в обратную сторону).

Результирующий код метода focusCatcher:

По сути мы реализовали все необходимое для успешного создания модальных окон, осталось ещё несколько дел:

Проблема №9. В IE11 не работают методы Element.closest() и Object.assign() .

Для поддержки Element.closest, воспользуемся полифилами для closest и matches от MDN.

Можно их вставить просто так, но так как у нас проект всё равно собирается webpack, то удобно воспользоваться пакетом element-closest-polyfill который просто вставляет этот код.

Для поддержки Object.assign , можно воспользоваться уже babel-плагином @babel/plugin-transform-object-assign

3. Заключение и ссылки

Повторяя начало статьи, всё изложенное выше, я оформил в маленькую библиотеку hystModal под MIT-лицензией. Вышло 3 кБ кода при загрузке с gzip. Ещё написал для неё подробную документацию на русском и английском языке.

Что вошло ещё в библиотеку hystModal, чего не было в статье:

  • Настройки (вкл/выкл управление фокусом, варианты закрытия, ожидание анимации закрытия)
  • Коллбеки (функции вызывающиеся перед открытием окна и после его закрытия (в них передаётся объект модального окна))
  • Добавлен запрет на какие-либо действия пока анимация закрытия окна не завершится, а также ожидание анимации закрытия текущего окна перед открытием нового (если окно открывается из другого окна).
  • Оформление кнопки-крестика закрытия в CSS
  • Минификация CSS и JS плагинами Webpack.

Если вам будет интересна эта библиотека, буду рад звёздочке в GitHub, или напишите в Issues о найденных багах. (Особенно большие проблемы, наверное, в грамматике английской версии документации, так как мои знания языка пока на начальном уровне. Связаться со мной также можно в Instagram

без рабочего примера найти проблему сложно.

извините, я пытаюсь отредактировать его, но я не могу скопировать и вставить свой код из Dreamweaver, нужно его ввести

извините, я забыл упомянуть, что часть JS заключается в одновременном закрытии двух модальных окон. Без этого мне пришлось бы щелкнуть 2 раза, чтобы оба модальных окна закрылись. Мне нужно проверить эту JS-часть, похоже, что это проблема

Мне нужно как-то поместить все в jsfiddle, я думаю (шаблон был куплен, поэтому я немного потерял, какой код подключается к где). Как вы сказали, без рабочего примера сложно найти проблему.

Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно.

В этой статье мы подробно рассмотрим стек Twitch, который подразделяется на следующий набор технологий:

8 полезных HTML-тегов, которые лучше использовать вместо <div></p>
<p>

Когда я только начинал изучать html, я использовал div для всего, это был один из первых тегов, которые я выучил, и казалось, что он работает в любой.

Представьте, что вы хотите поехать на пляж. Представьте, что вы упорно трудились весь год и заслужили это. Прибыв на место, вы обнаруживаете, что.

Сопровождаемость кода, сама по себе, является пульсирующим эффектом нескольких факторов. Когда часть программного обеспечения читабельна, ясна.

Ответы 1

Похоже, вы используете Bootstrap, в этом случае вы, вероятно, используете jQuery. Я вижу, что вы используете простой javascript для выполнения этой работы, но в этом конкретном случае вам следует рассмотреть возможность закрытия модального окна с помощью jQuery.

Я добавил это, теперь я могу прокручивать страницу, но она остается темной. Думаю есть какой-то слой?

Как насчет того, чтобы вы попробовали ответить вроде (stackoverflow.com/questions/46215070/…). Удаление фона: $(".modal-backdrop").remove();

@JavaThoughts черный слой, о котором вы говорите, называется наложением, если вы отметите классы, которые добавляются в код при открытии модального окна. Для этого черного слоя есть отдельный класс, в котором отображается модальное окно. Вы можете удалить его, если хотите, но это функция по умолчанию для модального окна Boostrap.

@YoannesGeissler, я добавил это, но он все тот же, темный и может прокручиваться, но не может щелкнуть

@Code_Ninja, кажется, я не могу найти код, показанный в Dreamweaver, когда я нажимаю на темный оверлей. Если это класс, то, если я смогу его найти, будет проще (это купленный шаблон, если это имеет значение). Я должен удалить его, если я этого не сделаю, после закрытия модального окна будет темно.

@JavaThoughts, если вы проверите класс .modal-backdrop.in , есть атрибут CSS, который говорит opacity:0.5 , если вы его удалите, цвет станет нормальным.

а если сделать display:none , то модал полностью пропадет.

@Code_Ninja ммм . Я не могу найти .modal-backdrop.in, это какой-то класс исправлений?

@JavaThoughts, да, это общий класс для Bootrap Modal, он добавляется в структуру DOM при открытии модального окна.

@JavaThoughts запустите ваш вывод и проверьте его в инструментах разработчика, вы найдете его

Читайте также: