网站有一些改动的时候,为了让用户熟知新的操做位置,每每会增长一个引导,常见的方式就是使用一个黑色的半透明蒙版,而后须要关注的区域是镂空的。css
而后上周五我去微云转悠的时候,也看到了引导层,因而职业病又犯了,去学习下别人是怎么实现的。下面是观测的结果:html
为了实现镂空蒙层效果,做者发挥了小时候拼积木的才能,使用两层HTML结构,内层使用5块独立区域拼接造成,至于中间镂空的区域的阴影则是使用的图片实现的。css3
虽然最终的效果知足了产品的需求,对于用户而言,目的已经达到。可是,从代码质量层面、潜在的体验提高可能性、使用场景广度上来说,仍是弱了不少的。浏览器
举例来讲,若是咱们某个提示区域面积很大,那中间的那个镂空区域尺寸是否是要变,那后面的背景图片怎么办?搞新图,有人看到了使用了background-size:cover
, 那IE7,IE8怎么办?哦,可能微云不须要管IE7, IE8.ide
若是不须要管IE7, IE8,那这里的实现就显得更加小白了。咱们实际上只须要一层标签,一层空标签就能够实现咱们的效果,且不须要图片。wordpress
主要在于思惟方式的变化。拼积木这种想法你们都比较容易想到,符合平常认知,可是,但代码层面,咱们能够进行思惟转换,发散思考,偌大的半透明遮罩层,咱们不要老想着背景色块背景色块,能够突破常规思惟,把它认为是边框,一个很大很大的边框(咱们平时使用border都是1
像素巨多),这样,咱们天然就有了镂空效果。学习
以下图示意:动画
可是,目前咱们中间的镂空区域方的,有没有什么办法变成圆的呢?
天然有,方法1是元素设置超大圆角,可是,此时为了边框依然填满整个屏幕,border
边框尺寸要大大增大,可是,为了避免影响页面的滚动条,咱们必须再嵌套一层标签,就显得啰嗦了;
方法2则是方法1某些方面的逆向思惟处理,就是把当前元素做为外层限制标签,里面从新生成一个大尺寸伪元素,实现自适应尺寸的圆角效果,这个好,HTML干净不啰嗦,CSS一步到位(代码以下示意);网站
.cover::before { content: ''; width: 100%; height:100%; border-radius: 50%; border: 400px solid #000; position: absolute; left: -400px; top: -400px; /* 本身瞎填的参数,示意 */ box-shadow: inset 0 0 5px 2px rgba(0,0,0,.75); }
你们能够看到,上面的伪元素的各个参数都是固定参数值,与外部元素的尺寸什么的没有任何关系,只要外部元素尺寸不超过400,里面永远会有一个正椭圆的内阴影的镂空图形(由于超出部分会被.cover
隐藏),要理解圆角和正椭圆的关系,能够参考我以前的文章:“秋月什么时候了,CSS3 border-radius知多少?”。ui
眼见为实,耳听为虚,您能够狠狠地点击这里:一层标签实现网站引导镂空蒙版功能demo (点击黑色蒙层会有引导切换效果)
demo这个镂空蒙层所使用的HTML代码以下:
<div class="cover"></div>
没错,就这么简单,没什么嵌套,没有什么五个元素变形金刚合体,没有使用图片。
微云这张图片3K多,以微云的用户访问量,估计流量费要很多钱的。
并且,你们若是点击蒙版,会发现,镂空的区域大小每次都是不同的,有大有小,有高有瘦,而微云的那个实现方法要知足此需求就棘手;并且,你们发现没,这些尺寸位置的变化都是动画来动画去的,不是嗙嗙嗙这种生硬的效果,更soft, 对用户视觉引导效果更好,你看,我从这里到这里了,为何能够实现动画效果呢,由于咱们的镂空和内阴影都是CSS实现的,而微云的图片方法,显然是没法有动画的。
JS代码辅助
固然,个人实现也离不开JS的辅助,JS的工做很简单,让蒙层的width
/height
以及border
大小和须要引导的元素相关联。
我特地整了个能够公用的方法coverGuide
(命名不喜欢本身随便改):
var coverGuide = function(cover, target) { var body = document.body, doc = document.documentElement; if (cover && target) { // target size(width/height) var targetWidth = target.clientWidth, targetHeight = target.clientHeight; // page size var pageHeight = doc.scrollHeight, pageWidth = doc.scrollWidth; // offset of target var offsetTop = target.getBoundingClientRect().top + (body.scrollTop || doc.scrollTop), offsetLeft = target.getBoundingClientRect().left + (body.scrollLeft || doc.scrollLeft); // set size and border-width cover.style.width = targetWidth + 'px'; cover.style.height = targetHeight + 'px'; cover.style.borderWidth = offsetTop + 'px ' + (pageWidth - targetWidth - offsetLeft) + 'px ' + (pageHeight - targetHeight - offsetTop) + 'px ' + offsetLeft + 'px'; cover.style.display = 'block'; // resize if (!cover.isResizeBind) { if (window.addEventListener) { window.addEventListener('resize', function() { coverGuide(cover, target); }); cover.isResizeBind = true; } else if (window.attachEvent) { window.attachEvent('onresize', function() { coverGuide(cover, target); }); cover.isResizeBind = true; // IE7, IE8 box-shadow hack cover.innerHTML = '<img src="guide-shadow.png">'; } } } };
这里的coverGuide
方法使用原生JS实现,IE6+浏览器都是兼容的,不依赖JS库,你们能够随意使用。固然,写得匆忙,没有严格验证,可能有bug,你们能够稍微留点心。
使用很是简单,语法以下:
coverGuide(cover, target);
其中cover
就是.cover
这个单独的蒙版元素,target
则是咱们须要指引的元素,按钮啊,导航什么的。而后,咱们的镂空区域自动定位到target
的位置,大小也是target
元素的大小。超省心。
具体使用,可参考上面的demo,源代码就在页面上。
IE7,IE8怎么办
若是你须要兼容IE7,IE8,咱们不妨就方框效果;若是设计和产品接受不了,则可使用图片打个补丁,例如上面JS代码部分的:
cover.innerHTML = '<img src="guide-shadow.png">';
我demo使用的这个图片长下面这样:
大小还有阴影都是我本身随手一搞的,旨在示意,真实项目你们能够向设计师索要图片。
而后,CSS超easy, 图片撑满咱们的cover
就能够。
/* IE7, IE8 img */ .cover > img { width: 100%; height: 100%; }
这种蒙版覆盖思想呢,不只仅适用于这种大面积的引导。咱们上传图片,尤为上传头像以后,要对头像进行剪裁,常见的交互之一就是四周黑色,中间镂空,也可使用巨大border
来实现咱们的效果,一层标签足矣,根本不须要上下左右额外4层标签拼接合体实现。
内部自适应的圆角效果单看文字,不少小伙伴估计不知道我在说些什么,建议去demo页面看下伪元素的代码,真实区域大小和最终效果,估计就会明白了。
感谢阅读,欢迎交流,欢迎提供更好的实现方法,必定有的,只是我功力不够。
以上~