For bootstrap 4, to expand on @helloroy's answer I used the following;-
var modal_lv = 0 ;
$('body').on('shown.bs.modal', function(e) {
if ( modal_lv > 0 )
{
$('.modal-backdrop:last').css('zIndex',1050+modal_lv) ;
$(e.target).css('zIndex',1051+modal_lv) ;
}
modal_lv++ ;
}).on('hidden.bs.modal', function() {
if ( modal_lv > 0 )
modal_lv-- ;
});
The advantage of the above is that it won't have any effect when there is only one modal, it only kicks in for multiples. Secondly, it delegates the handling to the body to ensure future modals which are not currently generated are still catered for.
Update
Moving to a js/css combined solution improves the look - the fade animation continues to work on the backdrop;-
var modal_lv = 0 ;
$('body').on('show.bs.modal', function(e) {
if ( modal_lv > 0 )
$(e.target).css('zIndex',1051+modal_lv) ;
modal_lv++ ;
}).on('hidden.bs.modal', function() {
if ( modal_lv > 0 )
modal_lv-- ;
});
combined with the following css;-
.modal-backdrop ~ .modal-backdrop
{
z-index : 1051 ;
}
.modal-backdrop ~ .modal-backdrop ~ .modal-backdrop
{
z-index : 1052 ;
}
.modal-backdrop ~ .modal-backdrop ~ .modal-backdrop ~ .modal-backdrop
{
z-index : 1053 ;
}
This will handle modals nested up to 4 deep which is more than I need.
Working on a project that has a lot of modals calling other modals and a few HTML guys that might not know to initiate it everytime for each button. Came to a similar conclusion as @gmaggio, begrudgingly after going the long way around first.
EDIT: Now supports modals called via javascript.
EDIT: Opening a scrolling modal from another modal now works.
$(document).on('show.bs.modal', function (event) {
if (!event.relatedTarget) {
$('.modal').not(event.target).modal('hide');
};
if ($(event.relatedTarget).parents('.modal').length > 0) {
$(event.relatedTarget).parents('.modal').modal('hide');
};
});
$(document).on('shown.bs.modal', function (event) {
if ($('body').hasClass('modal-open') == false) {
$('body').addClass('modal-open');
};
});
Just place the modal calling button in as normal, and if it is picked up to be inside a modal, it will close the current one first before opening the one specified in data-target.
Note that relatedTarget
is provided by Bootstrap.
I also added the following to smooth out the fading a bit: I am sure more can be done though.
.modal-backdrop.fade + .modal-backdrop.fade {
transition: opacity 0.40s linear 0s;
}
try this
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</head>
<body>
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#test1">Open Modal 1 </button>
<div id="test1" class="modal fade" role="dialog" style="z-index: 1400;">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-body">
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#test2">Open Modal 2</button>
</div>
</div>
</div>
</div>
<div id="test2" class="modal fade" role="dialog" style="z-index: 1600;">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-body">
content
</div>
</div>
</div>
</div>
</body>
</html>