Necesito que la superposición se muestre arriba del primer modal, no en la parte posterior.
Traté de cambiar el z-index
de .modal-backdrop
, pero se convierte en un desastre.
En algunos casos tengo más de dos modales en la misma página.
Necesito que la superposición se muestre arriba del primer modal, no en la parte posterior.
Traté de cambiar el z-index
de .modal-backdrop
, pero se convierte en un desastre.
En algunos casos tengo más de dos modales en la misma página.
Respuestas:
Después de ver muchas soluciones para esto, y ninguna de ellas era exactamente lo que necesitaba, se me ocurrió una solución aún más corta inspirada en @YermoLamers y @Ketwaroo.
Corrección del índice z de fondo
Esta solución utiliza un setTimeout
porque .modal-backdrop
no se crea cuando show.bs.modal
se desencadena el evento .
$(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
creado en la página (incluso modales dinámicos)Si por algún motivo no le gusta el índice z codificado, puede calcular el índice z más alto en la página de esta manera:
var zIndex = Math.max.apply(null, Array.prototype.map.call(document.querySelectorAll('*'), function(el) {
return +el.style.zIndex;
})) + 10;
Corrección de la barra de desplazamiento
Si tiene un modal en su página que excede la altura del navegador, entonces no puede desplazarse al cerrar un segundo modal. Para arreglar esto agregue:
$(document).on('hidden.bs.modal', '.modal', function () {
$('.modal:visible').length && $(document.body).addClass('modal-open');
});
Versiones
Esta solución se prueba con bootstrap 3.1.0 - 3.3.5
.not(this)
a la segunda línea) para que funcionara con bootstrap datepicker var zIndex = 1040 + (10 * $('.modal:visible').not(this).length);
Me doy cuenta de que se ha aceptado una respuesta, pero sugiero no hackear bootstrap para solucionar esto.
Puede lograr fácilmente el mismo efecto conectando los controladores de eventos shown.bs.modal y hidden.bs.modal y ajustando el índice z allí.
Aquí hay un ejemplo de trabajo
Un poco más de información está disponible aquí.
Esta solución funciona automáticamente con pilas de moda arbitrariamente profundas.
El código fuente del script:
$(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');
});
});
Algo más corto basado en la sugerencia de Yermo Lamers, esto parece funcionar bien. Incluso con animaciones básicas como fundido de entrada / salida e incluso el loco periódico de Batman gira. 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
clase en el elemento del cuerpo: jsfiddle.net/vkyjocyn
Combinando la respuesta de A1rPun con la sugerencia de StriplingWarrior, se me ocurrió esto:
$(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');
Funciona incluso para modales dinámicos agregados después del hecho, y elimina el problema de la segunda barra de desplazamiento. Lo más notable para lo que me pareció útil fue integrar formularios dentro de modales con comentarios de validación de las alertas de Bootbox, ya que usan modales dinámicos y, por lo tanto, requieren que enlace el evento para documentar en lugar de .modal, ya que eso solo lo adjunta a los existentes modales.
Creé un complemento Bootstrap que incorpora muchas de las ideas publicadas aquí.
Demostración en Bootply: http://www.bootply.com/cObcYInvpq
Github: https://github.com/jhaygt/bootstrap-multimodal
También aborda el problema con modales sucesivos que hacen que el telón de fondo se vuelva más y más oscuro. Esto asegura que solo un fondo sea visible en un momento dado:
if(modalIndex > 0)
$('.modal-backdrop').not(':first').addClass('hidden');
El índice z del fondo visible se actualiza en los eventos show.bs.modal
y hidden.bs.modal
:
$('.modal-backdrop:first').css('z-index', MultiModal.BASE_ZINDEX + (modalIndex * 20));
Al resolver el apilamiento de modales se desplaza por la página principal cuando uno está cerrado, descubrí que las versiones más nuevas de Bootstrap (al menos desde la versión 3.0.3) no requieren ningún código adicional para apilar modales.
Puede agregar más de un modal (por supuesto, tener una ID diferente) a su página. El único problema que se encuentra al abrir más de un modal será que al cerrar uno elimine elmodal-open
clase para el selector de cuerpo.
Puede usar el siguiente código Javascript para volver a agregar el modal-open
:
$('.modal').on('hidden.bs.modal', function (e) {
if($('.modal').hasClass('in')) {
$('body').addClass('modal-open');
}
});
En el caso de que no necesite el efecto de fondo para el modal apilado, puede configurar data-backdrop="false"
.
Versión 3.1.1. arreglado Fijar el fondo modal superpuesto a la barra de desplazamiento del modal , pero la solución anterior también parece funcionar con versiones anteriores.
Finalmente resuelto. Lo probé de muchas maneras y funciona bien.
Aquí está la solución para cualquiera que tenga el mismo problema: Cambie la función Modal.prototype.show (en bootstrap.js o modal.js)
DE:
if (transition) {
that.$element[0].offsetWidth // force reflow
}
that.$element
.addClass('in')
.attr('aria-hidden', false)
that.enforceFocus()
A:
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()
Es la mejor manera que encontré: compruebe cuántos modales se abren y cambie el índice z del modal y el fondo a un valor más alto.
Si está buscando la solución Bootstrap 4, hay una fácil usando CSS puro:
.modal.fade {
background: rgba(0,0,0,0.5);
}
Intente agregar lo siguiente a su JS en bootply
$('#myModal2').on('show.bs.modal', function () {
$('#myModal').css('z-index', 1030); })
$('#myModal2').on('hidden.bs.modal', function () {
$('#myModal').css('z-index', 1040); })
Explicación:
Después de jugar con los atributos (usando la herramienta de desarrollo de Chrome), me di cuenta de que cualquier z-index
valor a continuación 1031
pondrá las cosas detrás del telón de fondo.
Entonces, al usar los controladores de eventos modales de bootstrap, configuro el z-index
a 1030
. Si #myModal2
se muestra y establece la parte z-index
posterior en 1040
si #myModal2
está oculto.
Cada vez que ejecuta la función sys.showModal, incremente el índice z y configúrelo en su nuevo modal.
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');
La solución a esto para mí fue NO usar la clase "fade" en mis divs modales.
Sin soluciones de script, usando solo css dado que tiene dos capas de modales, establezca el segundo modal en un índice z más alto
.second-modal { z-index: 1070 }
div.modal-backdrop + div.modal-backdrop {
z-index: 1060;
}
Si desea que aparezca un modal específico encima de otro modal abierto, intente agregar el HTML del modal superior después del otro modal div
.
Esto funcionó para mí:
<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" ... />
Mi solución para bootstrap 4, trabajando con una profundidad ilimitada de modales y modal dinámico.
$('.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', '');
});
Cada modal debe tener una identificación diferente y cada enlace debe estar dirigido a una identificación modal diferente. Entonces debería ser algo así:
<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>
...
EDITAR: Bootstrap 3.3.4 ha resuelto este problema (y otros problemas modales), por lo que si puede actualizar su CSS y JS de arranque, esa sería la mejor solución. Si no puede actualizar la solución a continuación, seguirá funcionando y esencialmente hace lo mismo que bootstrap 3.3.4 (recalcular y aplicar relleno).
Como Bass Jobsen señaló, las versiones más nuevas de Bootstrap tienen resuelto el índice z. La clase modal-open y el relleno derecho seguían siendo problemas para mí, pero este script inspirado en la solución de Yermo Lamers lo resuelve. Simplemente colóquelo en su archivo JS y disfrute.
$(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'));
});
¡Mira esto! Esta solución resolvió el problema para mí, algunas líneas simples de CSS:
.modal:nth-of-type(even) {
z-index: 1042 !important;
}
.modal-backdrop.in:nth-of-type(even) {
z-index: 1041 !important;
}
Aquí hay un enlace a donde lo encontré: Bootply Solo asegúrese de que el .modual que necesita aparecer en la parte superior sea el segundo en el código HTML, para que CSS pueda encontrarlo como "par".
trabajar para abrir / cerrar multi modales
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);
}
});
});
Manifestación
Para mí, estas simples reglas de scss funcionaron perfectamente:
.modal.show{
z-index: 1041;
~ .modal.show{
z-index: 1043;
}
}
.modal-backdrop.show {
z-index: 1040;
+ .modal-backdrop.show{
z-index: 1042;
}
}
Si estas reglas hacen que el modal incorrecto esté en la parte superior de su caso, cambie el orden de sus divisiones modales o cambie (impar) a (par) en el scss anterior.
Aquí hay algunos CSS que usan nth-of-type
selectores que parecen funcionar:
.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
Tuve un escenario similar, y después de un poco de I + D encontré una solución. Aunque no soy bueno en JS, aun así he logrado escribir una pequeña consulta.
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);
});
Agregar variable global en modal.js
var modalBGIndex = 1040; // modal backdrop background
var modalConIndex = 1042; // modal container data
// show function inside add variable - 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
Las otras soluciones no funcionaron para mí fuera de la caja. Creo que quizás porque estoy usando una versión más reciente de Bootstrap (3.3.2) ... la superposición aparecía en la parte superior del diálogo modal.
Reformé un poco el código y comenté la parte que estaba ajustando el fondo modal. Esto solucionó el problema.
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');
});
Como nota al margen, si desea usar esto en AngularJs, simplemente coloque el código dentro del método .run () de su módulo.
Desafortunadamente, no tengo la reputación de comentar, pero debe tenerse en cuenta que la solución aceptada con la línea de base codificada de un índice z 1040 parece ser superior al cálculo de zIndex que intenta encontrar el zIndex máximo que se representa en la página.
Parece que ciertas extensiones / complementos se basan en contenido DOM de nivel superior, lo que hace que el cálculo de .Max sea un número tan obscenamente grande que no puede aumentar el zIndex más. Esto da como resultado un modal donde la superposición aparece sobre el modal incorrectamente (si usa las herramientas Firebug / Google Inspector, verá un zIndex del orden de 2 ^ n - 1)
No he podido aislar cuál es la razón específica por la cual las diversas formas de Math.Max for z-Index conducen a este escenario, pero puede suceder y parecerá exclusivo para algunos usuarios. (Mis pruebas generales en browserstack tenían este código funcionando perfectamente).
Espero que esto ayude a alguien.
En mi caso, el problema fue causado por una extensión del navegador que incluye los archivos bootstrap.js donde el evento show se manejó dos veces y dos modal-backdrop
se agregaron divs, pero al cerrar el modal solo se elimina uno de ellos.
Descubrí que al agregar un punto de interrupción de modificación de subárbol al elemento del cuerpo en Chrome, y seguí agregando los modal-backdrop
divs.
$(window).scroll(function(){
if($('.modal.in').length && !$('body').hasClass('modal-open'))
{
$('body').addClass('modal-open');
}
});
Actualización: 22.01.2019, 13.41 Optimicé la solución mediante jhay, que también admite cerrar y abrir diálogos iguales o diferentes cuando, por ejemplo, paso de un detalle a otro hacia adelante o hacia atrás.
(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));
Verifique el recuento de modales y agregue el valor al fondo como índice z
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');