我在iOS 12的Safari的iframe中显示的Bootstrap 4.1模态出现问题,所有其他经过测试的浏览器均按预期运行(甚至在iOS 11上也使用Safari)。该问题似乎特定于iOS12。
我创建了一个minimal example demonstrating the issue。前两个按钮的功能似乎与预期的一样,但是后四个按钮可以看到此问题,当您向下移动时,每个按钮都会变得更糟,当您尝试滚动或聚焦于其中的某个元素时,最后一个按钮会一起消失模态(请参见下面的屏幕截图):
我会注意到,我们正在以某种非常规的方式处理此功能,因为与其让iframe的内容滚动,我们还通过在父级和子级之间通过以下方式在邮件之间传递消息来调整其高度: message
事件处理程序和postMessage
:https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
我怀疑这是哪里有问题(但仍无法对其进行跟踪(并且如前所述,这仅是在运行版本12的ios设备上的问题))。
最近发现,此问题不是iOS 12上的Safari特有的,而是Chrome。
下面的代码来自先前的最小示例链接:
父级(/modal-test/index.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Title</title>
<link rel="stylesheet" href="./bootstrap.min.css">
<script src="./jquery.min.js"></script>
<script src="./popper.min.js"></script>
<script src="./bootstrap.min.js"></script>
<script>
$(document).ready(function(){
$ifCon = $("#ifCon");
window.addEventListener("message", function(event){
if(event.data.method === "returnWindowSize"){
$ifCon.height(event.data.content);
}
}, false);
});
</script>
<style>
#ifCon {
display: flex;
width: 100%;
height: 100%;
flex-direction: column;
background-color: #F2F2F2;
overflow: hidden;
border-radius:10px;
border:1px solid grey;
margin-left:auto;
margin-right:auto;
/*box-shadow:2px 2px 3px #000;*/
box-shadow: 0px 1px 3px 0px rgba(0,0,0,0.75);
}
#ifCon iframe {
flex-grow: 1;
border: none;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col text-center">
<div id="ifCon">
<iframe height="100%" width="100%" scrolling="no" src="/modal-test/frameable.html"></iframe>
</div>
</div>
</div>
</div>
</body>
</html>
孩子(/modal-test/frameable.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Title</title>
<link rel="stylesheet" href="./bootstrap.min.css">
<script src="./jquery.min.js"></script>
<script src="./popper.min.js"></script>
<script src="./bootstrap.min.js"></script>
<script>
var $embedContent, modalState;
$(document).ready(function(){
$embedContent = $('#embedContent');
parent.postMessage({method:"returnWindowSize", content:$embedContent.height()}, '*');
$('.modal').on('shown.bs.modal', function(e){
modalState = {
id:$(this).attr('id'),
contentElement:$(this).find('.modal-content'),
initialContentContainerHeight:$embedContent.height(),
invokerElement:$(e.relatedTarget)
};
adjustModal();
});
$('.modal').on('hidden.bs.modal', function(e){
modalState = null;
$(this).find('.modal-content').css("margin-top", "0px");
$embedContent.css('height', 'auto');
parent.postMessage({method:"returnWindowSize", content:$embedContent.height()}, '*');
});
});
function adjustModal(){
if(modalState.contentElement.css('margin-top') !== modalState.invokerElement.offset().top){
modalState.contentElement.animate({'margin-top':modalState.invokerElement.offset().top}, 200, "linear");
}
if(
// modal position + modal height is greater than or equal to the height of the embedContent so we need to resize the
// embedContent (make it taller)
((modalState.invokerElement.offset().top + modalState.contentElement.height()) >= $embedContent.height()) ||
// modal position + modal height is less than or equal to the height of the embedContent AND the current height of the
// embedContent is greater than or equal to the size of the embedContent height when the modal was originally shown
(((modalState.invokerElement.offset().top + modalState.contentElement.height()) <= $embedContent.height()) &&
($embedContent.height() > modalState.initialContentContainerHeight))
){
var newEmbedContentHeight = modalState.invokerElement.offset().top + modalState.contentElement.height() + 30;
$embedContent.height(newEmbedContentHeight);
parent.postMessage({method:"returnWindowSize", content:newEmbedContentHeight}, '*');
}
}
</script>
</head>
<body>
<div id="embedContent" class="container">
<div class="row" style="height:200px;margin-top:100px;">
<div class="col text-center">
<button id="btn1" type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
</button>
</div>
</div>
<div class="row" style="height:200px;">
<div class="col text-center">
<button id="btn2" type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
</button>
</div>
</div>
<div class="row" style="height:200px;">
<div class="col text-center">
<button id="btn3" type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
</button>
</div>
</div>
<div class="row" style="height:200px;">
<div class="col text-center">
<button id="btn3" type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
</button>
</div>
</div>
<div class="row" style="height:200px;">
<div class="col text-center">
<button id="btn3" type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
</button>
</div>
</div>
<div class="row" style="height:200px;">
<div class="col text-center">
<button id="btn3" type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
</button>
</div>
</div>
</div>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog"
aria-labelledby="exampleModalLabel" aria-hidden="true" data-focus="false" style="overflow-y:hidden;">
<div class="modal-dialog" role="document">
<div class="modal-content" style="margin-top:500px;">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label for="exampleFormControlInput1">Email address</label>
<input type="email" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com">
</div>
<div class="form-group">
<label for="exampleFormControlInput1">Email address</label>
<input type="email" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com">
</div>
<div class="form-group">
<label for="exampleFormControlSelect1">Example select</label>
<select class="form-control" id="exampleFormControlSelect1">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
<div class="form-group">
<label for="exampleFormControlSelect1">Example select</label>
<select class="form-control" id="exampleFormControlSelect1">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
<div class="form-group">
<label for="exampleFormControlSelect1">Example select</label>
<select class="form-control" id="exampleFormControlSelect1">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
<div class="form-group">
<label for="exampleFormControlSelect1">Example select</label>
<select class="form-control" id="exampleFormControlSelect1">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</body>
</html>
答案 0 :(得分:3)
最终的解决方案是,我们需要通过在子文档的<head></head>
(iframe中的元素(本例中为frameable.html))中加入以下CSS来强制硬件加速:>
<style>
body{
transform: translate3d(0,0,0);
}
</style>
但是我无法解释为什么这可以解决问题,或者为什么ios12(而不是ios11)需要它。如果其他人可以对这个话题有所了解,我相信它会帮助其他人。
答案 1 :(得分:0)
您需要将margin-top
的{{1}}设置为父文档的滚动高度。
这会将文档精确地放在顶部,您可能需要在该位置提供model-content
之类的偏移值,以使其不粘在顶部。
+80
'margin-top':modalState.invokerElement.offset().top
答案 2 :(得分:0)
在您的CSS中,为#ifCon添加
#ifCon {
height: 100vh;
}
您可以根据自己的喜好随意调整数字,VH将“查看高度”设置为100%。