在开发过程中,有时候需要用到iframe复用不同域名下的页面内容。为了提供连贯的用户体验,经常需要在主页面(父页面)和iframe子页面之间共享滚动位置。当用户在父页面中滚动时,我们希望子页面的滚动条也能相应地移动到相同的位置。本文将介绍其中较为常见的一种方法,即使用postMessage
来实现父子页面间的通信,从而实现滚动同步。
基本原理
1.隐藏iframe的滚动条
我们可以通过iframe属性frameborder="0"
和scrolling="no"
来隐藏iframe的滚动条,从而避免嵌入iframe的页面双滚动条的出现。
<iframe src="son.html" frameborder="0" scrolling="no"></iframe>
2.使用sticky粘性定位固定子页面
iframe设置了以上属性之后,子页面无法滚动,而随着父页面滚动,子页面也会跟着滚上去,不是我们想要的效果。所以需要用css的sticky粘性定位固定子页面top上升到顶部就固定。
<style>
.container{
width: 100%;
min-height: 1500px;
position: relative;
}
iframe{
position: sticky;
top: 0;
width: 100%;
height: 900px;
overflow: hidden;
}
</style>
<div class="container">
<iframe src="son.html" frameborder="0" scrolling="no"></iframe>
</div>
3.通过postMessage通信实现父子页面滚动联动
我们可以通过监听父页面的滚动事件,将滚动信息传给子页面,子页面通过监听父页面的postMessage事件,获取滚动信息,手动触发滚动事件,从而实现滚动联动。
- 父页面代码:
window.onscroll = function(){
document.querySelector('iframe').contentWindow.postMessage({'scrollTop':window.scrollY},'*');
}
- 子页面代码:
window.addEventListener('message', function (event) {
window.scrollTo(0,event.data.scrollTop);
});
完整代码
- 父页面:parent.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>parent</title>
</head>
<style>
body{
padding: 0;
margin: 0;
}
.container{
width: 100%;
min-height: 1500px;
position: relative;
}
iframe{
position: sticky;
top: 0;
width: 100%;
height: 900px;
overflow: hidden;
}
</style>
<body>
<div class="container">
<iframe src="son.html" frameborder="0" scrolling="no"></iframe>
</div>
</body>
<script>
// 监听message事件
window.addEventListener('message', function(event) {
document.querySelector('.container').style.height = event.data.message + 'px';
document.querySelector('iframe').style.height = window.screen.availHeight + 'px';
},false);
window.onscroll = function(){
document.querySelector('iframe').contentWindow.postMessage({'scrollTop':window.scrollY},'*');
}
</script>
</html>
- 子页面:son.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>son</title>
</head>
<style>
body{
margin: 0;
padding: 0;
}
div{
width: 100%;
height: 30vw;
border-bottom:#000 solid 1px;
background: #f5f5f5;
line-height: 30vw;
text-align: center;
}
</style>
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
<div>9</div>
<div>10</div>
<div>11</div>
<div>12</div>
</body>
<script>
function sendMessage(){
window.parent.postMessage({
sendHeight: true,
message: document.body.scrollHeight,
}, '*')
}
sendMessage();
window.addEventListener('message', function (event) {
window.scrollTo(0,event.data.scrollTop);
sendMessage();
});
</script>
</html>