Как сделать несколько модальных окон на одной странице

Обновлено: 24.04.2024

Модальное окно html + css, несколько вариантов модальных окон, открытие, закрытие модального окна, открытие модального окна по ссылке, открытие модального окна по кнопке! В общем попытаемся разобраться в скрипте модального окна!

Самое простое модальное окно

Что такое "Модальное окно"

Определение, что такое "Модальное окно"!? "Модальное окно" - это всплывающий элемент, который покрывает все пространство монитора и делает невозможным другие действия на сайте до того, пока вы не закроете это окно!

Алгоритм создания модального окна:

На самом деле, если разобраться, то нам всего то понадобится несколько кнопок и пара div, чтобы это все работало!

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

Самое простое модельное окно html + css

Чтобы забрендировать данный скрипт, поскольку я его написал самолично, то он будет называться ->"DW modal window"

Что потребуется для создания модального окна!?

Основной блок модального окна, который по умолчанию будет скрыт (display: none;), как вы наверное уже догадались вниже идущем коде четыре элемента

1). затемнение(zatemnenie),
2). само окно(window)
3). закрытие окна(close_window)
4). Содержание модального окна

И далее нам потребуются стили для нашего модального окна, не буду расписывать каждую строчку -> соберем весь код модального окна вместе:

Скрипт модального окна в сборе -> html + css

Мы недавно ввели новые фишки такие как. : для данного пункта у нас, кроме кода. который расположен ниже

Пример модального окна на отдельной странице

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

Вёрстка таких окон сначала кажется простой задачей. Модальные окна можно сделать даже без помощи 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

В этой статье мы разберемся как создавать модальные окна с помощью javascript.

Модальные окна которые мы сделаем буду универсальны. Для создания модальных окон в дальнейшем вам не нужно будет дописывать что-то в .js файле.

Весь код для копирования в конце статьи.

Вот что получилось в итоге ( это скрин, не кликать :)):

Кнопки открытия окна

План работы скрипта:

  1. Зарегистрировать событие клика на элементы с классом js-open-modal
  2. При клике на кнопку, ищем модальное окно с таким же атрибутом data-modal, добавляем класс .active подложке и этому модальному окну
  3. При клике на крестик удаляем класс у родительского модального окна и подложки

Пишем JavaScript

В начале, повесим на document событие DOMContentLoaded. Это событие сработает когда страница будет загружена.

Затем запишем массив кнопок в переменную используя метод querySelector. Здесь же определим еще 2 переменные: элемент подложки и массив кнопок-крестиков.

Заметьте, modalButtons и CloseButtons мы получаем через querySelectorAll, который возвращает массив, мы сделали это потому что нужно обрабатывать клики по всем кнопка, а вот overlay мы получаем через querySelector, он возвращает один элемент.

В html добавим кнопкам классы .js-open-modal. Мы специально будем использовать новый класс с приставкой js, чтобы не путать стили и интерактивность. Все кто будет работать с кодом увидит, что у класса есть приставка js, значит этот класс используется для интерактивности и его лучше не трогать.

После этого нужно повесить событие клика на каждую кнопку. Для этого мы переберем полученный массив кнопок и повесим обработчик на каждый элемент. Перебирать массив мы будем с помощью forEach:

В переменной item у нас будет храниться текущий элемент цикла. Повесим обработчик на него:

event или e — объект текущего события. В этом объекте хранятся различные методы и данные. При вызове любого события указание аргумента у функции будет ссылаться на этот объект. Зачем нам нужен этот объект? Об этом чуть ниже.

Что нам нужно сделать теперь?

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

Для этого в объекте события есть метод, который предотвращает стандартное действие элемента.

С предотвращением вопрос решили.

У каждой кнопки есть атрибут data-modal, в нем хранится значение, которое находится у модального окна в таком же атрибуте. Наши действия:

  1. Получить значение атрибута текущей кнопки
  2. Найти модальное окно с помощью этого значения

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

В итоге получается такой селектор — ‘.modal=[data-modal="значение переменной"]’ , который и находит наше модальное окно.

Давайте добавим нашему окну и подложке класс active.

Напишем стили для классов .active:

Весь javascript код который получился:

Кнопки должны открывать то модальное окно, к которому привязаны. Проверяем:

Осталось написать закрытие окон по клику на крестик. С перебором элементов и созданием события вы уже знакомы.

При клике на крестик нам нужно у этого же элемента найти родителя или деда с классом .modal и удалить у него класс .active.

Готовой функции для перебора родителей элемента нет. Есть метод который позволяет получить родителя, но это ненадежно, так как разметка может поменяться и наш код сломается.

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

Его нужно подключить в отдельном файле или в этом же файле до нашего кода.

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

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

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

Элемент в консоли

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

Теперь вы можете создавать много много модальных окон не изменяя свой js код.

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

Если у тебя есть замечания, пожелания, предложения — можешь так же написать их в комментариях. Я рад новым мнениям и критике.

Дополнение

По просьбе читателя добавляю код для закрытия модального окна по кнопке ESC и при клике на темный фон.

Закрытие окна при клике на ESC:

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

У событий связанных с клавишами, есть свойство keycode, которое хранит код нажатой клавиши. У ESC этот код — 27.

Нам остается проверять при каждом нажатии код клавиши с кодом ESC и если есть совпадение — удаляем класс у активного окна и фона.

Скрытие при нажатии

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

Ладно, подглядывай уже 🙂

Создаем событие клика на overlay, эта переменная создана в самом начале. Потом в функции удаляем у активного модального окна активный класс и делаем тоже самое у фона, на который кликнули, за это отвечает переменная this, если переводить — этот.

То есть при клике на фон, мы говорим: «Удали активный класс у окна и у фона, на который кликнули»

У меня есть страница, на которой должны открываться разные модальные окна при нажатии соответствующей ссылки на странице. У меня есть структура и javascript для работы с ОДНОМ окном, но я не могу заставить его работать более чем с одним. Я думаю, мне нужно перебрать каждый модальный блок . но не могу понять синтаксис.

Вы должны сделать модальные окна уникальными, чтобы иметь возможность выбирать их позже. Один из способов сделать это - через id .

Вам нужно определить, какая кнопка какое окно должно открываться. Одно из возможных решений - через data-attributes

А потом - событие:

Опять же - это одно из возможных решений.


Успех! Это работает сейчас, после многих часов моей возни с возможностями. Спасибо!! (Я не могу проголосовать, очевидно - слишком ново. Как только смогу, я проголосую за этот ответ.) Еще раз спасибо!

Я рада, что смогла помочь. Не беспокойтесь о голосовании, просто отметьте ответ как завершенный, чтобы другие пользователи не занимались им. :)

pgk, я надеюсь, что вы еще немного поможете мне с этим проектом. Как я могу заставить модальные окна закрываться по щелчку за пределами самих модальных окон. Закрытие по нажатию кнопки закрытия работает, но я хочу, чтобы они закрывались, если пользователь щелкает в любом месте окна. Есть ли у вас какие-либо предложения?

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

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

Создайте модальное диалоговое окно.

Класс всех модальных окон останется таким же, как и class="modal" при наличии множества модальных "id" окон, которые вы хотите отобразить на одном экране, используйте свойство, поскольку модальные окна Bootstrap написаны на Javascript, а JS полностью основан на идентификаторе.

Вам необходимо определить, какая кнопка будет нацелена на какое модальное окно, используя data-target атрибут тега . Если вы используете тег для запуска модального окна, используйте href атрибут. Пример :

ИЛИ при использовании тега тогда;

Для получения дополнительной информации вы можете проверить следующую страницу Bootstrap Modals.

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

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

Модальное наложение сзади

Я попытался изменить z-index оф .modal-backdrop , но это превратилось в беспорядок.

В некоторых случаях у меня есть более двух модальных окон на одной странице.

Увидев множество исправлений для этого, и ни одно из них не было именно тем, что мне было нужно, я придумал еще более короткое решение, вдохновленное @YermoLamers и @Ketwaroo.

Исправление фонового z-индекса В
этом решении используется, setTimeout потому что .modal-backdrop он не создается при show.bs.modal срабатывании события .

  • Это работает для всех .modal созданных на странице (даже динамических модальных)
  • Фон мгновенно накладывается на предыдущее модальное окно.

Пример jsfiddle

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

Версии
Это решение протестировано с загрузкой 3.1.0 - 3.3.5

@ A1rPun у меня не работает .. когда я закрываю второй модальный .. тело становится прокручиваемым .. я использовал весь ваш код .. :(

Не работал в моей среде с последними версиями BS. Пришлось сделать: $ ('. Modal-backdrop'). Last (). Not ('. Modal-stack'). Css ('z-index', zIndex - 1) .addClass ('modal-stack') ;

Мне пришлось внести незначительные изменения (добавленные .not(this) во вторую строку), чтобы заставить его работать с помощью начальной загрузки datepicker var zIndex = 1040 + (10 * $('.modal:visible').not(this).length);

Вы можете довольно легко добиться того же эффекта, подключив обработчики событий shown.bs.modal и hidden.bs.modal и настроив там z-index.

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

Исходный код скрипта:

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

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

Объединив ответ A1rPun с предложением StriplingWarrior, я придумал следующее:

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

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

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

Z-индекс видимого фона обновляется как для событий, так show.bs.modal и для hidden.bs.modal событий:

Хорошее решение. Я ожидаю, что фон станет темнее, когда у вас будет несколько модальных окон, но я понимаю, почему вам это не нужно. @AndyBurton Не могли бы вы сообщить мне, чего не хватает в моем решении?

@ A1rPun при открытии и закрытии 2-го модального окна полосы прокрутки, которые позволяли прокручивать в 1-м модальном окне, были удалены. IIRC это выглядело из-за того, что класс в теле был удален при закрытии 2-го модального окна.

Простое решение для Bootstrap 4.5


При решении Stacking modals прокручивается главная страница, когда одна из них закрыта, я обнаружил, что более новые версии Bootstrap (по крайней мере, начиная с версии 3.0.3) не требуют какого-либо дополнительного кода для стекирования модальных окон.

Вы можете добавить более одного модального окна (конечно, с другим идентификатором) на свою страницу. Единственная проблема, обнаруженная при открытии более чем одного модального окна, будет заключаться в том, что закрытие одного удаляет modal-open класс для селектора тела.

Вы можете использовать следующий код Javascript, чтобы повторно добавить modal-open :

В случае, если вам не нужен эффект фона для сложенного модального окна, вы можете установить его data-backdrop="false" .

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