引子
使用 position
transform
实现从右边滑出的 h5 浮层效果,但在手机浏览器上左右滑动时,页面产生了左右滚动条,浮层也出来了。这是问题页面,移动端访问如下:
这个现象不应该出现,问题好解决,但为什么会这样?想了一下,好像知道相关点,但又讲不清,所以在此梳理一下。
原因
产生了滚动,很自然的就会想到 overflow
属性,那么就先来了解一下。
overflow
属性指定了块容器元素的内容溢出时是否被剪裁,是 overflow-x
和 overflow-y
的简写。
Name | overflow |
---|---|
可取值 | visible、hidden、scroll、auto、inherit |
默认值 | visible |
适用于 | 块级容器和建立了格式化上下文的盒子 |
继承性 | 无 |
- visible:这个值表示内容不会被剪切,可能会在盒子之外渲染。
- hidden:这个值表示内容被剪切,并且不应提供滚动用户界面来查看剪裁区域之外的内容。
- scroll:这个值表示内容被剪切,并且如果用户代理使用在屏幕上可见的滚动机制(例如滚动条或窗格),则无论盒子中的任何内容是否被剪裁,都应为盒子显示该机制。这是为了避免滚动条在一个动态环境中,出现和消失造成的任何问题。当指定这个值且目标媒介是打印时,溢出的内容可能会被打印,也可能不会打印。当用在 table boxes 时,这个值跟 visible 作用一致。
- auto:这个值表示依赖用户代理,但应为溢出的盒子提供滚动机制。当用在 table boxes 时,这个值跟 visible 作用一致。
通过上面的了解,想先纠正一下取值为 auto
的一种认识:浏览器会自动根据内容决定是否产生滚动。从现象上看似乎是这样,但标准上不是这样的,只是建议。如果用户代理不提供滚动,那就没有,而且也不一定是滚动,这都依赖于用户代理。
再来分析一下上面有问题的情况,主要的结构和样式如下:
<!doctype html>
<html>
<body>
<div class="pop"></div>
</body>
</html>
html {overflow-x: hidden;}
html,body { height: 100%; }
body { position: relative; }
.pop {
position: absolute;
top: 0;
left: 0;
100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
transform: translateX(100%);
}
body
没有显式设置 overflow
的值,所以默认是 visible
,由于浮层使用 transform
超出了可视区,那么先来确定一下 body
的 overflow
是否有效。
设置 body
宽度的效果页面,移动端访问如下:
发现符合 overflow: visible
的效果,没有产生左右滚动条。
接着有了下面的猜想:只要超出了可视区就会产生滚动。在前面的基础上,设置浮层 transform
超出可视区,这是效果页面,移动端访问如下:
结果跟猜想的一样,这也说明从一开始并不是 body
产生了滚动,而是 viewport 产生了滚动。继续查找资料,发现了下面的标准说明:
用户代理必须将根元素上设置的
overflow
属性应用于 viewport 。当根元素是一个 HTML 的 html 元素且它的overflow
值是visible
,并且它拥有body
元素作为后代,用户代理必须将这样的第一个后代元素的overflow
的属性值应用于 viewport 。如果visible
应用于 viewport ,则必须将其解释为auto
。从中传播值的元素必须有一个overflow
已使用的值为visible
。
从上面的说明以及实际测试,推测上述情况中 body 的 overflow
属性应用到了 viewport 上,导致产生了滚动。把 body 设置 overflow-x: hidden
,就发现不会产生左右滚动了,移动端访问如下:
后记
在 IOS 和 安卓上测试了 4、5 个浏览器都会出现左右滚动,但一些安卓手机上的 Chrome 浏览器没有出现滚动,例如在红米6手机。还有一点就是:PC 端浏览器都不会产生左右滚动。
此外,标准上其实说的并不是很清楚,再加上标准是一回事,各家实现并不一定都是符合标准。
以上见解都是个人结合资料和实际测试得出,是否真是这样,真不好说,不过可以当作一个思考的方向。