WEB前端开发中经常需要用到模态框,如果你使用了bootstrap、easyui等前端框架,可以很方便的调用一个模态框,今天我们自己动手创建一个自定义模态框。
弹出一个模态框需要以下两个步骤
- 显示一个蒙版遮罩整个浏览器可见区域
- 弹出模态框
创建背景
背景用于测试蒙版和模态框,内容随便。
<style type="text/css">
body{font-size: 24px;margin: 0;padding: 0}
.background{margin-left: 100px;}
p{height: 40px;line-height: 40px;}
</style>
<body>
<div class="background">
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
</div>
</body>
创建打开模态框按钮
虽然我们用<input type="button" value="弹出模态框"></input>
就可以创建一个按钮了,但默认样式的按钮实在太丑了,我们来简单的对它化妆下,需要注意的是浏览器默认有个user agent stylesheet,当按钮被点击后外围会添加一个黑框,我们重写:focus样式覆盖浏览器默认样式。
/*user agent stylesheet*/
:focus {
outline: -webkit-focus-ring-color auto 5px;
}
<div class="open-model">
<input type="button" value="弹出模态框"></input>
</div>
<style type="text/css">
.open-model{
text-align: center;
}
.open-model input{
padding: 10px 20px;
font-size: 24px;
line-height: 24px;
border: 0px;
background: #F53639;
color: #FFF;
cursor: pointer;
}
.open-model input:hover{
background: #F3726D;
}
.open-model input:focus{
border: 0px;
outline-width: 0px;
}
</style>
创建蒙版
蒙版的作用是遮罩浏览器可见区域,同时带一点透明度。为了使蒙版遮罩浏览器所有可见区域,需要设置蒙版position:fixed
,同时要设置上下左右全部为0,这样蒙版就覆盖浏览器所有可见区域了,另外还可以设置透明度opacity:0.75
和背景background: #666
。初始时蒙版是隐藏的,需要添加一个classhide
。
<div class="model hide"></div>
<style type="text/css">
.model{
opacity: 0.75;
background: #666;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1000;
}
.hide{
display: none;
}
</style>
创建模态框
假设模态框的宽度为600px,高度为400px,为了方便观察,设置模态框的背景为background: #F3726D
,模态框是在蒙版之上的,所以模态框的z-index
必须大于蒙版的,这里设置模态框的z-index
为1001,一般情况下模态框在整个浏览器中居中显示的,且模态框弹出时不能影响其它元素布局,所以模态框的position必须为absolute或者fixed。当position为absolute时不能使用margin:0 auto
居中显示div,此时用margin-left和margin-top手动调整,margin-left值为(浏览器可见区域宽度-模态框宽度)/2,然后用jquery css方法设置模态框的margin-left属性值即可实现左右居中,上下居中同理。
var marginLeft = (document.documentElement.clientWidth - $(".model-dialog").outerWidth())/2;
var marginHeight = (document.documentElement.clientHeight - $(".model-dialog").outerHeight())/2;
$('.model-dialog').css('margin-left',marginLeft);
$('.model-dialog').css('margin-top',marginHeight);
在创建背景时故意让背景超过浏览器高度,这样就会出现垂直滚动条,此时弹出模态框用鼠标滚轮还是可以上下滚动,如何禁止弹出模态框时主界面上下滚动呢?给body添加overflow:hidden
。但问题又来了,给body添加overflow:hidden
后浏览器右边的垂直滚动条会消失,此时body内的元素就会右移而导致页面抖动,影响用户体验,那如何来避免呢?可以在添加完overflow:hidden
后设置bodypadding-right
为垂直滚动条的宽度,问题又来了,我怎么知道垂直滚动条的宽度啊,我的思路是在添加overflow:hidden
之前读取body的宽度,在添加overflow:hidden
后再读取body的宽度,后面读取的宽度减去前面读取的宽度就是垂直滚动条的宽度了。
重新梳理下点击打开模态框按钮时执行的动作:
- 计算margin-left和margin-top
- 设置margin-left和margin-top
- 设置body
overflow:hidden
- 计算垂直滚动条宽度
- 给body添加一个垂直滚动条宽度的padding-right
- 显示模态框和蒙版
$(".open-model").click(function(){
var oldWidth = $('body').outerWidth();
var marginLeft = (document.documentElement.clientWidth - $(".model-dialog").outerWidth())/2;
var marginHeight = (document.documentElement.clientHeight - $(".model-dialog").outerHeight())/2;
$('.model-dialog').css('margin-left',marginLeft);
$('.model-dialog').css('margin-top',marginHeight);
$('body').css('overflow','hidden');
var newWidth = $('body').outerWidth();
var scrollbarWidth = newWidth-oldWidth;
$('body').css('padding-right',scrollbarWidth+'px');
$('.model').removeClass('hide');
$('.model-dialog').removeClass('hide');
})
附上完整的html代码
<!DOCTYPE html>
<html>
<head>
<title>模态框</title>
<style type="text/css">
body{font-size: 24px;margin: 0;padding: 0}
.background{margin-left: 100px;}
p{height: 40px;line-height: 40px;}
.open-model{
text-align: center;
}
.open-model input{
padding: 10px 20px;
font-size: 24px;
line-height: 24px;
border: 0px;
background: #F53639;
color: #FFF;
cursor: pointer;
}
.open-model input:hover{
background: #F3726D;
}
.open-model input:focus{
border: 0px;
outline-width: 0px;
}
.model{
opacity: 0.75;
background: #666;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1000;
}
.model-dialog{
width: 600px;
height: 400px;
background: #F3726D;
position: absolute;
z-index: 1001;
left:0;
top: 0;
}
.hide{
display: none;
}
</style>
</head>
<body>
<div class="model hide"></div>
<div class="model-dialog hide"></div>
<div class="open-model">
<input type="button" value="弹出模态框"></input>
</div>
<div class="background">
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
<p>我是无辜的背景文字</p>
</div>
<script src="http://cdn.bootcss.com/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript">
// 打开模态框
$(".open-model").click(function(){
var oldWidth = $('body').outerWidth();
var marginLeft = (document.documentElement.clientWidth - $(".model-dialog").outerWidth())/2;
var marginHeight = (document.documentElement.clientHeight - $(".model-dialog").outerHeight())/2;
$('.model-dialog').css('margin-left',marginLeft);
$('.model-dialog').css('margin-top',marginHeight);
$('body').css('overflow','hidden');
var newWidth = $('body').outerWidth();
var scrollbarWidth = newWidth-oldWidth;
$('body').css('padding-right',scrollbarWidth+'px');
$('.model').removeClass('hide');
$('.model-dialog').removeClass('hide');
})
//点击蒙版关闭模态框
$('.model').click(function(){
$('body').css('overflow','auto');
$('body').css('padding-right','0px');
$('.model').addClass('hide');
$('.model-dialog').addClass('hide');
})
</script>
</body>
</html>