Мне нужно, чтобы наложение показывалось над первым модалом, а не сзади.
Я попытался изменить z-index
из .modal-backdrop
, но это становится беспорядок.
В некоторых случаях у меня есть более двух модалов на одной странице.
Мне нужно, чтобы наложение показывалось над первым модалом, а не сзади.
Я попытался изменить z-index
из .modal-backdrop
, но это становится беспорядок.
В некоторых случаях у меня есть более двух модалов на одной странице.
Ответы:
Увидев множество исправлений для этого, и ни одно из них не было именно тем, что мне было нужно, я пришел к еще более короткому решению, вдохновленному @YermoLamers & @Ketwaroo.
Фоновое исправление z-index
Это решение использует, setTimeout
потому что .modal-backdrop
не создается при запуске события show.bs.modal
.
$(document).on('show.bs.modal', '.modal', function () {
var zIndex = 1040 + (10 * $('.modal:visible').length);
$(this).css('z-index', zIndex);
setTimeout(function() {
$('.modal-backdrop').not('.modal-stack').css('z-index', zIndex - 1).addClass('modal-stack');
}, 0);
});
.modal
созданного на странице (даже динамические модалы)Если по какой-либо причине вам не нравится жестко запрограммированный z-индекс, вы можете рассчитать самый высокий z-индекс на странице следующим образом:
var zIndex = Math.max.apply(null, Array.prototype.map.call(document.querySelectorAll('*'), function(el) {
return +el.style.zIndex;
})) + 10;
Исправление
полосы прокрутки Если на вашей странице есть модальное окно, которое превышает высоту браузера, вы не можете прокрутить его при закрытии второго модального окна. Чтобы исправить это, добавьте:
$(document).on('hidden.bs.modal', '.modal', function () {
$('.modal:visible').length && $(document.body).addClass('modal-open');
});
Версии
Это решение протестировано с начальной загрузкой 3.1.0 - 3.3.5.
.not(this)
во вторую строку), чтобы заставить его работать с начальной var zIndex = 1040 + (10 * $('.modal:visible').not(this).length);
Я понимаю, что ответ принят, но я настоятельно рекомендую не взламывать загрузчик, чтобы это исправить.
Вы можете довольно легко добиться того же эффекта, подключив обработчики событий show.bs.modal и hidden.bs.modal и настроив там z-index.
Немного больше информации доступно здесь.
Это решение работает автоматически с произвольно глубокими стеками модов.
Исходный код скрипта:
$(document).ready(function() {
$('.modal').on('hidden.bs.modal', function(event) {
$(this).removeClass( 'fv-modal-stack' );
$('body').data( 'fv_open_modals', $('body').data( 'fv_open_modals' ) - 1 );
});
$('.modal').on('shown.bs.modal', function (event) {
// keep track of the number of open modals
if ( typeof( $('body').data( 'fv_open_modals' ) ) == 'undefined' ) {
$('body').data( 'fv_open_modals', 0 );
}
// if the z-index of this modal has been set, ignore.
if ($(this).hasClass('fv-modal-stack')) {
return;
}
$(this).addClass('fv-modal-stack');
$('body').data('fv_open_modals', $('body').data('fv_open_modals' ) + 1 );
$(this).css('z-index', 1040 + (10 * $('body').data('fv_open_modals' )));
$('.modal-backdrop').not('.fv-modal-stack').css('z-index', 1039 + (10 * $('body').data('fv_open_modals')));
$('.modal-backdrop').not('fv-modal-stack').addClass('fv-modal-stack');
});
});
Что-то более короткая версия, основанная на предложении Ермо Ламерса, похоже, это работает хорошо. Даже с такими базовыми анимациями, как постепенное исчезновение и даже сумасшедший поворот газеты Бэтмена. http://jsfiddle.net/ketwaroo/mXy3E/
$('.modal').on('show.bs.modal', function(event) {
var idx = $('.modal:visible').length;
$(this).css('z-index', 1040 + (10 * idx));
});
$('.modal').on('shown.bs.modal', function(event) {
var idx = ($('.modal:visible').length) -1; // raise backdrop after animation.
$('.modal-backdrop').not('.stacked').css('z-index', 1039 + (10 * idx));
$('.modal-backdrop').not('.stacked').addClass('stacked');
});
modal-open
класс на элемент тела: jsfiddle.net/vkyjocyn
Комбинируя ответ A1rPun с предложением StriplingWarrior, я придумал следующее:
$(document).on({
'show.bs.modal': function () {
var zIndex = 1040 + (10 * $('.modal:visible').length);
$(this).css('z-index', zIndex);
setTimeout(function() {
$('.modal-backdrop').not('.modal-stack').css('z-index', zIndex - 1).addClass('modal-stack');
}, 0);
},
'hidden.bs.modal': function() {
if ($('.modal:visible').length > 0) {
// restore the modal-open class to the body element, so that scrolling works
// properly after de-stacking a modal.
setTimeout(function() {
$(document.body).addClass('modal-open');
}, 0);
}
}
}, '.modal');
Работает даже для динамических модалов, добавленных после факта, и устраняет проблему второй полосы прокрутки. Наиболее примечательной вещью, для которой я нашел это полезным, была интеграция форм внутри модалов с проверкой обратной связи из предупреждений Bootbox, поскольку они используют динамические модалы и, таким образом, требуют привязки события к документу, а не к .modal, поскольку это только присоединяет его к существующим модальности.
Я создал плагин Bootstrap, который включает в себя множество идей, размещенных здесь.
Демонстрация по загрузке: http://www.bootply.com/cObcYInvpq
Github: https://github.com/jhaygt/bootstrap-multimodal
Это также решает проблему с последовательными модалами, заставляющими фон становиться темнее и темнее. Это гарантирует, что в любой момент времени виден только один фон:
if(modalIndex > 0)
$('.modal-backdrop').not(':first').addClass('hidden');
Z-индекс видимого фона обновляется как для событий, так show.bs.modal
и для hidden.bs.modal
событий:
$('.modal-backdrop:first').css('z-index', MultiModal.BASE_ZINDEX + (modalIndex * 20));
При решении Stacking modals прокручивает главную страницу, когда она закрыта, я обнаружил, что более новые версии Bootstrap (по крайней мере, начиная с версии 3.0.3) не требуют никакого дополнительного кода для укладки модалов.
Вы можете добавить более одной модальной линии (конечно, с другим идентификатором) на свою страницу. Единственная проблема, обнаруженная при открытии более одного модального режима, заключается в том, что закрытие удаляетmodal-open
класс для селектора тела.
Вы можете использовать следующий код Javascript для повторного добавления modal-open
:
$('.modal').on('hidden.bs.modal', function (e) {
if($('.modal').hasClass('in')) {
$('body').addClass('modal-open');
}
});
Если вам не нужен эффект фона для сложенного модала, вы можете установить data-backdrop="false"
.
Версия 3.1.1. Исправлена ошибка, из-за которой фиксировался модальный фон, перекрывающий полосу прокрутки модала , но вышеприведенное решение, похоже, также работает с более ранними версиями.
Наконец-то решено. Я проверял это во многих отношениях и прекрасно работает.
Вот решение для тех, у кого есть такая же проблема: Измените функцию Modal.prototype.show (в bootstrap.js или modal.js)
ИЗ:
if (transition) {
that.$element[0].offsetWidth // force reflow
}
that.$element
.addClass('in')
.attr('aria-hidden', false)
that.enforceFocus()
TO:
if (transition) {
that.$element[0].offsetWidth // force reflow
}
that.$backdrop
.css("z-index", (1030 + (10 * $(".modal.fade.in").length)))
that.$element
.css("z-index", (1040 + (10 * $(".modal.fade.in").length)))
.addClass('in')
.attr('aria-hidden', false)
that.enforceFocus()
Это самый лучший способ, который я нашел: проверить, сколько модалей открыто, и изменить z-индекс модала и фона на более высокое значение.
Если вы ищете решение Bootstrap 4, есть простое решение с использованием чистого CSS:
.modal.fade {
background: rgba(0,0,0,0.5);
}
Попробуйте добавить следующее в ваш JS при загрузке
$('#myModal2').on('show.bs.modal', function () {
$('#myModal').css('z-index', 1030); })
$('#myModal2').on('hidden.bs.modal', function () {
$('#myModal').css('z-index', 1040); })
Объяснение:
Поиграв с атрибутами (используя инструмент разработки Chrome), я понял, что любое z-index
значение ниже1031
, отодвинет на задний план.
Поэтому, используя модальные дескрипторы событий начальной загрузки, я установил z-index
в 1030
. Если #myModal2
отображается и установите z-index
обратно, 1040
если #myModal2
скрыто.
Каждый раз, когда вы запускаете sys.showModal, функция увеличивает z-index и устанавливает новый модальный режим.
function system() {
this.modalIndex = 2000;
this.showModal = function (selector) {
this.modalIndex++;
$(selector).modal({
backdrop: 'static',
keyboard: true
});
$(selector).modal('show');
$(selector).css('z-index', this.modalIndex );
}
}
var sys = new system();
sys.showModal('#myModal1');
sys.showModal('#myModal2');
Решение этой проблемы для меня состояло в том, чтобы НЕ использовать класс "fade" в моих модальных div-ах.
Нет сценариев решения, используя только CSS, если у вас есть два слоя модалов, установите 2-й модал на более высокий индекс z
.second-modal { z-index: 1070 }
div.modal-backdrop + div.modal-backdrop {
z-index: 1060;
}
Если вы хотите, чтобы конкретный модал отображался поверх другого открытого модала, попробуйте добавить HTML самого верхнего модала после другого модального div
.
Это сработало для меня:
<div id="modal-under" class="modal fade" ... />
<!--
This modal-upper should appear on top of #modal-under when both are open.
Place its HTML after #modal-under. -->
<div id="modal-upper" class="modal fade" ... />
Мое решение для bootstrap 4, работающее с неограниченной глубиной модальных и динамических модальных.
$('.modal').on('show.bs.modal', function () {
var $modal = $(this);
var baseZIndex = 1050;
var modalZIndex = baseZIndex + ($('.modal.show').length * 20);
var backdropZIndex = modalZIndex - 10;
$modal.css('z-index', modalZIndex).css('overflow', 'auto');
$('.modal-backdrop.show:last').css('z-index', backdropZIndex);
});
$('.modal').on('shown.bs.modal', function () {
var baseBackdropZIndex = 1040;
$('.modal-backdrop.show').each(function (i) {
$(this).css('z-index', baseBackdropZIndex + (i * 20));
});
});
$('.modal').on('hide.bs.modal', function () {
var $modal = $(this);
$modal.css('z-index', '');
});
Каждому модалу должен быть присвоен свой идентификатор, а каждая ссылка должна быть ориентирована на другой модальный идентификатор. Так должно быть что-то вроде этого:
<a href="#myModal" data-toggle="modal">
...
<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"></div>
...
<a href="#myModal2" data-toggle="modal">
...
<div id="myModal2" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"></div>
...
РЕДАКТИРОВАТЬ: Bootstrap 3.3.4 решил эту проблему (и другие модальные проблемы), так что если вы можете обновить свои загрузочные CSS и JS, это было бы лучшим решением. Если вы не можете обновить приведенное ниже решение, оно все равно будет работать и, по сути, будет работать так же, как и при начальной загрузке 3.3.4 (пересчитать и применить отступы).
Как отметил Басс Йобсен, в новых версиях Bootstrap решен z-индекс. Для меня все еще были проблемы с открытым модальным классом и правым отступом, но этот сценарий, вдохновленный решением Yermo Lamers, решает эту проблему. Просто поместите его в свой файл JS и наслаждайтесь.
$(document).on('hide.bs.modal', '.modal', function (event) {
var padding_right = 0;
$.each($('.modal'), function(){
if($(this).hasClass('in') && $(this).modal().data('bs.modal').scrollbarWidth > padding_right) {
padding_right = $(this).modal().data('bs.modal').scrollbarWidth
}
});
$('body').data('padding_right', padding_right + 'px');
});
$(document).on('hidden.bs.modal', '.modal', function (event) {
$('body').data('open_modals', $('body').data('open_modals') - 1);
if($('body').data('open_modals') > 0) {
$('body').addClass('modal-open');
$('body').css('padding-right', $('body').data('padding_right'));
}
});
$(document).on('shown.bs.modal', '.modal', function (event) {
if (typeof($('body').data('open_modals')) == 'undefined') {
$('body').data('open_modals', 0);
}
$('body').data('open_modals', $('body').data('open_modals') + 1);
$('body').css('padding-right', (parseInt($('body').css('padding-right')) / $('body').data('open_modals') + 'px'));
});
Проверь это! Это решение решило проблему для меня, несколько простых строк CSS:
.modal:nth-of-type(even) {
z-index: 1042 !important;
}
.modal-backdrop.in:nth-of-type(even) {
z-index: 1041 !important;
}
Вот ссылка на то, где я ее нашел: Bootply Просто убедитесь, что .modual, который должен отображаться сверху, является вторым в HTML-коде, поэтому CSS может найти его как «четный».
работа для открытия / закрытия мультимодальных
jQuery(function()
{
jQuery(document).on('show.bs.modal', '.modal', function()
{
var maxZ = parseInt(jQuery('.modal-backdrop').css('z-index')) || 1040;
jQuery('.modal:visible').each(function()
{
maxZ = Math.max(parseInt(jQuery(this).css('z-index')), maxZ);
});
jQuery('.modal-backdrop').css('z-index', maxZ);
jQuery(this).css("z-index", maxZ + 1);
jQuery('.modal-dialog', this).css("z-index", maxZ + 2);
});
jQuery(document).on('hidden.bs.modal', '.modal', function ()
{
if (jQuery('.modal:visible').length)
{
jQuery(document.body).addClass('modal-open');
var maxZ = 1040;
jQuery('.modal:visible').each(function()
{
maxZ = Math.max(parseInt(jQuery(this).css('z-index')), maxZ);
});
jQuery('.modal-backdrop').css('z-index', maxZ-1);
}
});
});
демонстрация
Для меня эти простые правила scss работали отлично:
.modal.show{
z-index: 1041;
~ .modal.show{
z-index: 1043;
}
}
.modal-backdrop.show {
z-index: 1040;
+ .modal-backdrop.show{
z-index: 1042;
}
}
Если эти правила приводят к тому, что в вашем случае неправильная модальность будет выше, либо измените порядок ваших модальных дивов, либо измените (нечетное) на (четное) в приведенном выше scss.
Вот некоторые CSS с использованием nth-of-type
селекторов, которые, кажется, работают:
.modal:nth-of-type(even) {
z-index: 1042 !important;
}
.modal-backdrop.in:nth-of-type(even) {
z-index: 1041 !important;
}
Bootply: http://bootply.com/86973
У меня был похожий сценарий, и после небольшого исследования я нашел решение. Хотя я не очень хорош в JS, мне все же удалось записать небольшой запрос.
http://jsfiddle.net/Sherbrow/ThLYb/
<div class="ingredient-item" data-toggle="modal" data-target="#myModal">test1 <p>trerefefef</p></div>
<div class="ingredient-item" data-toggle="modal" data-target="#myModal">tst2 <p>Lorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem IpsumLorem Ipsum</p></div>
<div class="ingredient-item" data-toggle="modal" data-target="#myModal">test3 <p>afsasfafafsa</p></div>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
$('.ingredient-item').on('click', function(e){
e.preventDefault();
var content = $(this).find('p').text();
$('.modal-body').html(content);
});
Добавить глобальную переменную в modal.js
var modalBGIndex = 1040; // modal backdrop background
var modalConIndex = 1042; // modal container data
// показать функцию внутри переменной add - Modal.prototype.backdrop
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
modalConIndex = modalConIndex + 2; // add this line inside "Modal.prototype.show"
that.$element
.show()
.scrollTop(0)
that.$element.css('z-index',modalConIndex) // add this line after show modal
if (this.isShown && this.options.backdrop) {
var doAnimate = $.support.transition && animate
modalBGIndex = modalBGIndex + 2; // add this line increase modal background index 2+
this.$backdrop.addClass('in')
this.$backdrop.css('z-index',modalBGIndex) // add this line after backdrop addclass
Другие решения не работали для меня из коробки. Я думаю, возможно, потому что я использую более свежую версию Bootstrap (3.3.2) .... наложение появлялось поверх модального диалога.
Я немного переработал код и прокомментировал часть, которая корректировала модальный фон. Это решило проблему.
var $body = $('body');
var OPEN_MODALS_COUNT = 'fv_open_modals';
var Z_ADJUSTED = 'fv-modal-stack';
var defaultBootstrapModalZindex = 1040;
// keep track of the number of open modals
if ($body.data(OPEN_MODALS_COUNT) === undefined) {
$body.data(OPEN_MODALS_COUNT, 0);
}
$body.on('show.bs.modal', '.modal', function (event)
{
if (!$(this).hasClass(Z_ADJUSTED)) // only if z-index not already set
{
// Increment count & mark as being adjusted
$body.data(OPEN_MODALS_COUNT, $body.data(OPEN_MODALS_COUNT) + 1);
$(this).addClass(Z_ADJUSTED);
// Set Z-Index
$(this).css('z-index', defaultBootstrapModalZindex + (1 * $body.data(OPEN_MODALS_COUNT)));
//// BackDrop z-index (Doesn't seem to be necessary with Bootstrap 3.3.2 ...)
//$('.modal-backdrop').not( '.' + Z_ADJUSTED )
// .css('z-index', 1039 + (10 * $body.data(OPEN_MODALS_COUNT)))
// .addClass(Z_ADJUSTED);
}
});
$body.on('hidden.bs.modal', '.modal', function (event)
{
// Decrement count & remove adjusted class
$body.data(OPEN_MODALS_COUNT, $body.data(OPEN_MODALS_COUNT) - 1);
$(this).removeClass(Z_ADJUSTED);
// Fix issue with scrollbar being shown when any modal is hidden
if($body.data(OPEN_MODALS_COUNT) > 0)
$body.addClass('modal-open');
});
В качестве примечания: если вы хотите использовать это в AngularJs, просто поместите код внутри метода вашего модуля .run ().
К сожалению, у меня нет репутации комментировать, но следует отметить, что принятое решение с жестко закодированной базовой линией z-индекса 1040, похоже, превосходит вычисление zIndex, которое пытается найти максимальное значение zIndex, отображаемое на странице.
Похоже, что некоторые расширения / плагины полагаются на содержимое DOM верхнего уровня, что делает расчет .Max настолько неприлично большим числом, что он не может увеличивать zIndex дальше. Это приводит к модальному режиму, в котором наложение отображается поверх модального некорректно (если вы используете инструменты Firebug / Google Inspector, вы увидите zIndex порядка 2 ^ n - 1)
Мне не удалось выделить причину, по которой различные формы Math.Max для z-Index приводят к этому сценарию, но это может произойти, и оно будет уникальным для нескольких пользователей. (В моих общих тестах на browsertack этот код работал отлично).
Надеюсь, это кому-нибудь поможет.
В моем случае проблема была вызвана расширением браузера, которое включает в себя файлы bootstrap.js, в которых событие show обрабатывается дважды и modal-backdrop
добавляются два div, но при закрытии модального режима удаляется только один из них.
Обнаружил, что добавив точку останова модификации поддерева к элементу body в chrome, и отследил добавление modal-backdrop
div.
$(window).scroll(function(){
if($('.modal.in').length && !$('body').hasClass('modal-open'))
{
$('body').addClass('modal-open');
}
});
Обновление: 22.01.2019, 13.41 Я оптимизировал решение с помощью jhay, который также поддерживает закрытие и открытие одинаковых или разных диалоговых окон, например, при переходе от одной детализации данных к другой вперед или назад.
(function ($, window) {
'use strict';
var MultiModal = function (element) {
this.$element = $(element);
this.modalIndex = 0;
};
MultiModal.BASE_ZINDEX = 1040;
/* Max index number. When reached just collate the zIndexes */
MultiModal.MAX_INDEX = 5;
MultiModal.prototype.show = function (target) {
var that = this;
var $target = $(target);
// Bootstrap triggers the show event at the beginning of the show function and before
// the modal backdrop element has been created. The timeout here allows the modal
// show function to complete, after which the modal backdrop will have been created
// and appended to the DOM.
// we only want one backdrop; hide any extras
setTimeout(function () {
/* Count the number of triggered modal dialogs */
that.modalIndex++;
if (that.modalIndex >= MultiModal.MAX_INDEX) {
/* Collate the zIndexes of every open modal dialog according to its order */
that.collateZIndex();
}
/* Modify the zIndex */
$target.css('z-index', MultiModal.BASE_ZINDEX + (that.modalIndex * 20) + 10);
/* we only want one backdrop; hide any extras */
if (that.modalIndex > 1)
$('.modal-backdrop').not(':first').addClass('hidden');
that.adjustBackdrop();
});
};
MultiModal.prototype.hidden = function (target) {
this.modalIndex--;
this.adjustBackdrop();
if ($('.modal.in').length === 1) {
/* Reset the index to 1 when only one modal dialog is open */
this.modalIndex = 1;
$('.modal.in').css('z-index', MultiModal.BASE_ZINDEX + 10);
var $modalBackdrop = $('.modal-backdrop:first');
$modalBackdrop.removeClass('hidden');
$modalBackdrop.css('z-index', MultiModal.BASE_ZINDEX);
}
};
MultiModal.prototype.adjustBackdrop = function () {
$('.modal-backdrop:first').css('z-index', MultiModal.BASE_ZINDEX + (this.modalIndex * 20));
};
MultiModal.prototype.collateZIndex = function () {
var index = 1;
var $modals = $('.modal.in').toArray();
$modals.sort(function(x, y)
{
return (Number(x.style.zIndex) - Number(y.style.zIndex));
});
for (i = 0; i < $modals.length; i++)
{
$($modals[i]).css('z-index', MultiModal.BASE_ZINDEX + (index * 20) + 10);
index++;
};
this.modalIndex = index;
this.adjustBackdrop();
};
function Plugin(method, target) {
return this.each(function () {
var $this = $(this);
var data = $this.data('multi-modal-plugin');
if (!data)
$this.data('multi-modal-plugin', (data = new MultiModal(this)));
if (method)
data[method](target);
});
}
$.fn.multiModal = Plugin;
$.fn.multiModal.Constructor = MultiModal;
$(document).on('show.bs.modal', function (e) {
$(document).multiModal('show', e.target);
});
$(document).on('hidden.bs.modal', function (e) {
$(document).multiModal('hidden', e.target);
});}(jQuery, window));
Проверьте количество модалов и добавьте значение к фону как z-index
var zIndex = 1500 + ($('.modal').length*2) + 1;
this.popsr.css({'z-index': zIndex});
this.popsr.on('shown.bs.modal', function () {
$(this).next('.modal-backdrop').css('z-index', zIndex - 1);
});
this.popsr.modal('show');