手机常见的一种设计:在弹出消息提示框浮层后(有的还要求提示框内容可滑动),禁止body部分滑动。
常见的解决方法是:
body { overflow:hidden }
,这在pc端很有效,但是在手机端却不生效。
解决办法
先说解决办法吧:
不管 安卓 还是ios,只需用css 即可完美解决!
css加上这段代码即可(注意:一定要直接加在css里,不可用js在页面动态修改,当然,弹出消息提示框时,可以动态修改body 的overflow:hidden)
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
html, body {
height: 100%;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
body {
position: relative;
}
原理解释
关于这个问题,我找了不少资料,但是国内文章解决方案基本都是互相抄袭,都有点小问题。
比如,见的最多就是:
html, body {
height: 100%;
overflow: hidden;
}
在弹出消息提示框时,同时修改html和body的overflow: hidden
,确实会生效,但是会导致页面回到顶部!
还有 监听 body 的 ontouchmove 事件,判断弹出框然后禁止默认行为的(太繁琐,不优雅),引入第三方js的(大材小用不值得)等等。
总之都有瑕疵,要想完美解决还得了解根本原理才行。
首先,overflow的实现原理:
整个viewport的overflow是由html中的overflow来决定的;
假如你不去设置html的overflow(也就是默认的visible属性),而去设置body的overflow:hidden,也是可以的;
假如你设置了html的overflow属性的值(除去默认的visible),那么body的overflow属性就不会生效了。
上面的几点在大部分的现代浏览器里都是成立的,但ios下的除外,包括iphone和ipad
ios认为,网页内容是个整体,需要将所有的都显示出来,所有overflow就不该起作用,这是他们刻意的,不是bug,而且在更高版本的ios7,8,9中也是这样设定的。
对viewport我们没法改变,但是我们可以通过改变body自身的overflow:
改变html的overflow默认属性(visible)为auto,这样body就不会继承viewport的overflow属性,然后通过设置body的overflow:hidden,大部分的溢出内容就会被隐藏掉。
不过设置了position:absolute的除外,因为它默认是相对viewport进行绝对定位的,这个时候你要对body进行设置position:relative。
总结
要达到这个效果:
html和body的padding,margin都不能有,盒子模型最好是用border-box,以免设置了body的padding等导致溢出。(一般css reset的时候就会有)。
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body需要设置viewport的高,将html和body的高和overflow一起设置,-webkit-overflow-scrolling: touch
解决ios滑动不流畅的问题:
html,body {
height: 100%;
overflow: auto;
}
设置body的 position:relative
,使position:absolute
的元素相对body定位:
body {
position: relative;
}
然后在弹出消息提示框时,设置 body { overflow:hidden }
,关闭时设置 body { overflow:auto }
或者去掉body { overflow:hidden }
。
完成!
demo
源代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>有弹出框时,body不可滑动</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
html, body {
height: 100%;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
body {
position: relative;
}
.main {
color: #fff;
font-size: 30px;
background-color: #853FFB;
height: 2000px;
position: relative;
}
.d1 {
height: 600px;
background-color: red;
}
.d2 {
position: absolute;
bottom: 0;
left: 0;
height: 50px;
}
.shade {
display: none;
background-color: rgba(0,0,0,.8);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.shade1 {
margin: 5% auto;
width: 90%;
background-color: #AF41F9;
height: 50%;
overflow: auto;
}
button {
font-size: 20px;
}
</style>
</head>
<body>
<div class="main">
<div class="d1">繁星海风的demo</div>
<button id="btn">弹出层</button>
<div class="d2">底部</div>
</div>
<div id="shade" class="shade">
<div id="shade1" class="shade1">
<button id="btn1">关闭</button>
<div id="shade11" style="background-color: #fff">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
</div>
</div>
</div>
<script>
var btn = window.document.getElementById("btn");
var btn1 = window.document.getElementById("btn1");
var shade = window.document.getElementById("shade");
btn.onclick = function (e) {
shade.style.display = "block";
document.body.style.overflow = "hidden";
};
btn1.onclick = function (e) {
shade.style.display = "none";
document.body.style = "";
}
</script>
</body>
</html>