这篇文章发布于 2016年03月7日,星期一,00:22,归类于 CSS相关。 阅读 84796 次, 今日 1 次 34 条评论
by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=5290
一、微云的实现
网站有一些改动的时候,为了让用户熟知新的操作位置,往往会增加一个引导,常见的方式就是使用一个黑色的半透明蒙版,然后需要关注的区域是镂空的。
然后上周五我去微云转悠的时候,也看到了引导层,于是职业病又犯了,去学习下别人是怎么实现的。下面是观测的结果:
为了实现镂空蒙层效果,作者发挥了小时候拼积木的才能,使用两层HTML结构,内层使用5块独立区域拼接形成,至于中间镂空的区域的阴影则是使用的图片实现的。
虽然最终的效果满足了产品的需求,对于用户而言,目的已经达到。但是,从代码质量层面、潜在的体验提升可能性、使用场景广度上来讲,还是弱了很多的。
举例来说,如果我们某个提示区域面积很大,那中间的那个镂空区域尺寸是不是要变,那后面的背景图片怎么办?搞新图,有人看到了使用了background-size:cover
, 那IE7,IE8怎么办?哦,可能微云不需要管IE7, IE8.
如果不需要管IE7, IE8,那这里的实现就显得更加小白了。我们实际上只需要一层标签,一层空标签就可以实现我们的效果,且不需要图片。
二、我的实现
主要在于思维方式的变化。拼积木这种想法大家都比较容易想到,符合日常认知,但是,但代码层面,我们可以进行思维转换,发散思考,偌大的半透明遮罩层,我们不要老想着背景色块背景色块,可以突破常规思维,把它认为是边框,一个很大很大的边框(我们平时使用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知多少?”。
眼见为实,耳听为虚,您可以狠狠地点击这里:一层标签实现网站引导镂空蒙版功能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页面看下伪元素的代码,真实区域大小和最终效果,估计就会明白了。
感谢阅读,欢迎交流,欢迎提供更好的实现方法,一定有的,只是我功力不够。
以上~
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载(图片请勿直接外链)请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:http://www.zhangxinxu.com/wordpress/?p=5290
(本篇完)
- jquery.guide.js新版上线操作向导镂空提示jQuery插件 (0.774)
- 小tip:CSS3下的圆形遮罩效果实现与应用 (0.636)
- CSS3 box-shadow兼容loading效果兼IE10+ CSS Hack介绍 (0.364)
- CSS3 box-shadow盒阴影图形生成技术 (0.364)
- CSS3 text-fill-color简介及应用展示 (0.330)
- 小tip: CSS3与文字渐变光影流动动画效果实现 (0.330)
- CSS3/SVG clip-path路径剪裁遮罩属性简介 (0.330)
- 图片动态局部毛玻璃模糊效果的实现 (0.330)
- 小tips: CSS3 webkit下彩条文字效果实现 (0.330)
- -webkit-box-reflect属性简介及元素镜像倒影实现 (0.330)
- 小tip: CSS3如何实现圆角的outline效果? (RANDOM - 0.286)
我想实现进入首页不点击而是自动播放也可以吗
我想问,如果一个遮罩里要有大于一个镂空的,这样是不是就没法实现了····
你好,方法非常棒。我动手模拟了一把,发现似乎存在一个问题。js代码中
var pageHeight = doc.scrollHeight,
pageWidth = doc.scrollWidth;
是否应为
var pageHeight = doc.clientWidth,
pageWidth = doc.clientWidth;
很容易实现
.mask {
width: 180px;
height: 80px;
position: fixed;
left: 50px;
top: 100px;
border-radius: 50%;
box-shadow: inset 0 0 20px 1px,0 0 5px 2000px rgba(0,0,0,0.5);
}
以前用修改border-width实现圆形遮罩扩散,木有想到还能用4个不同的width+inset shadow实现这个
学习了,很棒的方法,创意和技术结合的典范!~
想较于你的方案。。。我可以吐下槽原来腾讯里有些人水平也一般嘛,当然我是嫉妒羡慕恨而已。但是很明显,他没看过你的博客。。。我记得这招你以前的博客也谢过 : )
这种方式很早就有人用了。。
早就有人用又怎么样,JavaScript 也早就有人用了,html css 也早就有人用了,你所学的东西也早就有人用了,你又怎样,以50步笑100步。醉了。。。
很棒的实现啊。
楼主你挺幽默的,每次结束语必看啊
厉害
遇到个问题,没有滚动条的时候,document.documentElement.scrollHeight的值是0
思考方式上受教了。感谢大神
学习了
IE11表示高亮会错位。还有项目里用了frame。加载慢的不得了。出来了就错位了。大神,有什么好方法么。
大神,有了镂空效果,请问如果旁边添加文字解释这个效果有吗?
@tiny 文字解释你另外覆盖定位就好了,文字又不需要遮罩。
没有想到会被鑫旭老师点名(非常感谢),我是写这个蒙版的UI,为了兼容到 IE7 才使用这个写法而没有用 box-shadow。
background-size: cover; 是为了将来如果镂空区域如果只是微调,为了节省开发时间先保证在主流浏览器下直接替换镂空图片就可以,所以加上去的
思路很好,只是这样实现的效果边框太生硬了。看着不舒服。
这思路太棒了!get!
长姿势,学习啦!
旭哥 很牛,向你学习!
你现在这个站点一个月广告费也不少吧
我来膜拜一下前端大神~
张老师,js没怎么学过,用jQuery不知道该怎么做
旭神,看到文章学到了很多,非常感谢!
有个小小的问题,DEMO在UC浏览器webkit内核下运行,镂空位置移动到“回到相关文章”位置时,width和height会变为0,导致镂空的区域消失了,其他位置没问题,还不太清楚bug产生的原因。
PS:直接用chrome浏览器打开无此问题。
@Poko CSS缓存~
啊 受教了~
你的demo里 点击关闭按钮之后打开控制台 遮罩层又会出现了
@Mad 好的,感谢反馈,已fix~
那应该怎么解决呢?还有,我点击到了第二个镂空,然后缩小浏览器,他又自动回到第一个镂空了
一个内阴影+一个外阴影+一个超大外阴影+圆角
.cover {
border-radius: 100%;
opacity: 0.75;
box-shadow: inset 0 0 10px #464646, 0 0 10px #fff, 0 0 0 9999px #000;
}
太聪明了!
又涨了一个新姿势!!
太赞了!!!!!以思维驾驭技术很有代表性的一篇文章!