在浏览器窗口上添加遮罩层的方法


Posted in Javascript onNovember 12, 2012

如何在浏览器窗口上添加一个遮罩层

背景
在web2.0中,页面弹窗是一个很常见的交互方式,这样既可以避免不必要的页面跳转,也可以改进界面的布局和可交互性。
但是,浏览器原生的弹窗函数(alert, confirm, prompt)有着很大的局限性,主要是它们的展现UI一来很不美观,二来也不够灵活,因此,我们经常需要自行定义弹窗函数。
当我们要实现一个模式弹窗时(模式弹窗,即是说出现弹窗时,页面其它地方不可点击),通常的做法是用一个div将整个页面窗口遮挡住。
实现
下面,我们一步步地实现一种较为简洁有效的遮罩层:

Step 1:
首先我们要考虑定义一个遮挡浏览器窗口的div,考虑下面一段html+css代码:
<div unselectable="on" style="background:#000;filter:alpha(opacity=10);opacity:.1;left:0px;top:0px;position:fixed;height:100%;width:100%;overflow:hidden;z-index:10000;"></div>
它可以实现遮挡浏览器窗口的功能,其中几个需要注意的css属性分别解释如下:
1)background:#000: 将div的背景色设置为黑色; filter:alpha(opacity=10): 在IE下,将div的透明度设置为0.1; opacity:.1: 在非IE下,将div的透明度设置为0.1
以上三个属性联合起来,实现了页面其余元素的“被挡住但可见”的效果。
2)left:0px;top:0px;position:fixed;height:100%;width:100%: 定义div的高度和宽度分别是浏览器高度和宽度的100%。这里有个小技巧,如果div的position是fixed或者absolute,那么当div的高度设置为百分比(例如100%)时,div的高度将参照浏览器可视区域(viewport)的高度来计算。此外,设置position为fixed,可以使得浏览器即使在scroll或resize时也保证遮罩层一直挡在页面的可视区域。
3)overflow:hidden 用来避免滚动条的出现。

Step 2:
细心的读者应该可以发现上述的css代码并不适用于IE 6,原因有两个:一来,IE6不支持position:fixed;二来,更重要的是,在IE 6中,height:100%不起作用,div的高度不再参照浏览器可视区域的高度。
修正第一个缺陷很简单,只需用css hack,加上 _position:absolute 就行。
修正第二个缺陷,我们需要借助javascript,动态地计算出遮罩层的高度和宽度,特别注意的是,为保证遮罩层在页面滚动时也遮住窗口,遮罩层的高宽应该覆盖住滚动区域。
动态计算的代码如下,其中mask变量指向遮罩层:

function calculateSize() { 
var b = document.documentElement.clientHeight ? document.documentElement : document.body, 
height = b.scrollHeight > b.clientHeight ? b.scrollHeight : b.clientHeight, 
width = b.scrollWidth > b.clientWidth ? b.scrollWidth : b.clientWidth; 
mask.css({height: height, width: width}); 
}

此外,还需注意到,当页面大小发生变化时,要重新计算遮罩层的高宽,否则可能会新扩大的区域没有被遮罩。
function resize() { 
calculateSize(); 
$(window).on(“resize”, calculateSize); 
}

Step 3:
通过Step 1和Step 2,我们基本上已完成了构建遮罩层的工作。但工作并未完成,在IE6下,还需考虑一些特殊的情况:当页面上存在select元素的时候,遮罩层将无法遮住select元素,这是IE 6的一个著名bug,解决方案是在遮罩层中增加一个iframe。
Html+css代码如下:
<div unselectable="on" style="display:none;background:#000;filter:alpha(opacity=10);opacity:.1;left:0px;top:0px;position:fixed;_position:absolute;height:100%;width:100%;overflow:hidden;z-index:10000;"><div style="position:absolute;width:100%;height:100%;top:0;left:0;z-index:10;background-color:#000"></div><iframe border="0" frameborder="0" style="width:100%;height:100%;position:absolute;top:0;left:0;z-index:1"></iframe></div>

有几个小技巧需要稍作解释:
1)iframe的样式使用 width:100%;height:100%; ,这是可行的,因为它的父定位元素的高宽已经确定了
2)在遮罩层内部,除了一个iframe外,还增加了一个div,并且该div和iframe的position都是absolute,div的z-index大于iframe的z-index,这样一来,就使得内部div遮挡住了iframe。这具有现实意义:使得页面的一些事件(例如onclick, onmouseup, onmousemove)依然会被响应在本页面上,而不是被iframe截获。
代码示例
综合以上的分析,整体的实现代码如下,大家可以参考一下:
var windowMask = (function($) { var isIE6 = $.browser.msie && $.browser.version == "6.0"; 
var mask = '<div unselectable="on" style="display:none;background:#000;filter:alpha(opacity=10);opacity:.1;left:0px;top:0px;position:fixed;height:100%;width:100%;overflow:hidden;z-index:10000;"></div>'; 
isIE6 && (mask = '<div unselectable="on" style="display:none;background:#000;filter:alpha(opacity=10);opacity:.1;left:0px;top:0px;position:fixed;_position:absolute;height:100%;width:100%;overflow:hidden;z-index:10000;"><div style="position:absolute;width:100%;height:100%;top:0;left:0;z-index:10;background-color:#000"></div><iframe border="0" frameborder="0" style="width:100%;height:100%;position:absolute;top:0;left:0;z-index:1"></iframe></div>'); 
mask = $(mask); 
$("body").append(mask); 
function show() { 
isIE6 && resize(); 
mask.show(); 
} 
function hide() { 
isIE6 && $(window).off("resize", calculateSize); 
mask.hide(); 
} 
function calculateSize() { 
var b = document.documentElement.clientHeight ? document.documentElement : document.body, 
height = b.scrollHeight > b.clientHeight ? b.scrollHeight : b.clientHeight, 
width = b.scrollWidth > b.clientWidth ? b.scrollWidth : b.clientWidth; 
mask.css({height: height, width: width}); 
} 
function resize() { 
calculateSize(); 
$(window).on("resize", calculateSize); 
} 
return { 
show: show, 
hide: hide 
}; 
})();

使用很简单,当需要展现遮罩层时,调用 windowMask.show(),要移除遮罩层时,调用 windowMask.hide()。
Javascript 相关文章推荐
jQuery(非HTML5)可编辑表格实现代码
Dec 11 Javascript
JS去除数组重复值的五种不同方法
Sep 06 Javascript
5个JavaScript经典面试题
Oct 13 Javascript
js实现漂浮回顶部按钮实例
May 06 Javascript
如何利用AngularJS打造一款简单Web应用
Dec 05 Javascript
jQuery Dialog对话框事件用法实例分析
May 10 Javascript
微信小程序 Storage API实例详解
Oct 02 Javascript
jQuery实现二维码扫描功能
Jan 09 Javascript
AngularJs+Bootstrap实现漂亮的计算器
Aug 10 Javascript
Vue.js组件实现选项卡以及切换特效
Jul 24 Javascript
javascript设计模式 ? 迭代器模式原理与用法实例分析
Apr 17 Javascript
Vue生命周期activated之返回上一页不重新请求数据操作
Jul 26 Javascript
php对mongodb的扩展(小试牛刀)
Nov 11 #Javascript
php对mongodb的扩展(初识如故)
Nov 11 #Javascript
JavaScript判断DOM何时加载完毕的技巧
Nov 11 #Javascript
JavaScript中的匀速运动和变速(缓冲)运动详细介绍
Nov 11 #Javascript
jQuery语法总结和注意事项小结
Nov 11 #Javascript
javascript继承之为什么要继承
Nov 10 #Javascript
jquery表单验证使用插件formValidator
Nov 10 #Javascript
You might like
php设计模式 Delegation(委托模式)
2011/06/26 PHP
php使用ffmpeg获取视频信息并截图的实现方法
2016/05/03 PHP
Smarty模板引擎缓存机制详解
2016/05/23 PHP
Javascript技巧之不要用for in语句对数组进行遍历
2010/10/20 Javascript
javascript学习笔记(十三) js闭包介绍(转)
2012/06/20 Javascript
JavaScript中的值类型详细介绍
2014/12/29 Javascript
用Move.js配合创建CSS3动画的入门指引
2015/07/22 Javascript
react-native-video实现视频全屏播放的方法
2018/03/19 Javascript
jQuery实现导航样式布局操作示例【可自定义样式布局】
2018/07/24 jQuery
Vue通过ref父子组件拿值方法
2018/09/12 Javascript
VUE v-for循环中每个item节点动态绑定不同函数的实例
2018/09/26 Javascript
微信小程序MUI侧滑导航菜单示例(Popup弹出式,左侧不动,右侧滑动)
2019/01/23 Javascript
[01:00:25]2018DOTA2亚洲邀请赛3月30日 小组赛A组 VG VS Liquid
2018/03/31 DOTA
[02:05:03]完美世界DOTA2联赛循环赛 LBZS VS Matador BO2 10.28
2020/10/28 DOTA
从零学Python之入门(二)基本数据类型
2014/05/25 Python
Python类属性的延迟计算
2016/10/22 Python
python之验证码生成(gvcode与captcha)
2019/01/02 Python
pycharm的console输入实现换行的方法
2019/01/16 Python
python实现QQ邮箱/163邮箱的邮件发送
2019/01/22 Python
python操作gitlab API过程解析
2019/12/27 Python
new_zeros() pytorch版本的转换方式
2020/02/18 Python
Python 日期与时间转换的方法
2020/08/01 Python
基于CSS3实现的几个小loading效果
2018/09/27 HTML / CSS
通过一张图教会你CSS3倒影的实现
2017/09/26 HTML / CSS
关于 HTML5 的七个传说小结
2012/04/12 HTML / CSS
HTML5中的网络存储实现方式
2020/04/28 HTML / CSS
澳大利亚当地社区首选的光学商店:1001 Optical
2019/08/24 全球购物
Street One瑞士:德国现代时装公司
2019/10/09 全球购物
董事长助理岗位职责
2014/02/18 职场文书
股权转让协议书
2014/12/07 职场文书
工作失职自我检讨书
2015/05/05 职场文书
2015年信息中心工作总结
2015/05/25 职场文书
2015年信息化建设工作总结
2015/07/23 职场文书
Nginx+Tomcat负载均衡集群的实现示例
2021/10/24 Servers
python垃圾回收机制原理分析
2022/04/13 Python
python playwright之元素定位示例详解
2022/07/23 Python