使用过iOS 7的朋友会看到上面有一种非常酷的顶部固定导航菜单效果-磨砂效果。顶部导航菜单是半透明的模糊效果,当往下滚动页面的时候,顶部导航菜单遮住页面的内容,因为它是半透明的,它下面的内容淡淡的显示,形成一种非常酷的磨砂效果。
我们使用CSS的blur
滤镜完全可以在页面中实现这个效果。但是使用CSS滤镜只能在元素本身内容上产生效果,它不能影响到它下方的元素。也就是说,CSS的blur
滤镜不能对使用该滤镜的元素下面的元素产生模糊效果。有一个新的属性-webkit-backdrop-filter
可以实现这个功能,但这是一个实验性的属性,只在webkit内核的浏览器中可以运行。
其实,还有另外的方法可以实现这种效果,这就是我们这批文章要介绍的内容。
制作一个模糊导航条
在这个demo中,这个模糊导航条是一个空的元素,它的位置设置为固定定位。真正的导航菜单位于它的上方,使用和模糊导航条相同的大小和坐标。下面的代码使用Sass来书写,没有添加浏览器厂商的前缀。
#blurrycontent { padding: 1rem; top: 0; left: 0; width: 100%; height: 5rem; overflow: hidden; position: fixed; filter: blur(4px); } nav { @extend #blurrycontent; filter: none; text-align: right; }
在页面中的主要元素是一个<main>
元素。
<main id="content"> <h1>London</h1> <p>With roots at least 7,000 years old, London is an accretion of artifacts old and new, from the remnants of wooden Neolithic settlements buried in the mud of the Thames to gleaming 21st century spires of glass and steel… </main>
#blurrycontent
元素和<nav>
元素以固定单位的方式固定在页面的最上方,其余部分都是<main>
元素的范围。
main { margin: 0; background: url(london_background.jpg); background-size: cover; padding: 2rem; }
这个时候,页面向下滚动的时候,导航菜单下面的内容是看不见的,我们下面要来制作磨砂效果。
磨砂效果
正如前面说的,filter
只能在元素本身使用,不会影响到它下面的元素。所以我们要为<main>
元素制作一个副本,并使用cloneNode
方法将它放入到#blurrycontent
元素中。
var pageContent = document.getElementById("content"), pagecopy = pageContent.cloneNode(true), blurryContent = document.getElementById("blurrycontent"); blurryContent.appendChild(pagecopy);
通过上面的设置之后,现在的效果非常的勉强。现在#blurrycontent
中的内容不会随页面一起往下滚动,我们需要将它和页面滚动进行同步:
window.onscroll = function() { blurryContent.scrollTop = window.pageYOffset; }
现在,滚动页面就相当于移动了#blurrycontent
内容,它们被同步起来了。因为<nav>
元素被固定在#blurrycontent
元素上面,所以它不会受到影响。
效果限制
将页面上的内容复制为一个副本,并对它使用模糊滤镜会对浏览器和GPU增加一些负担,所以你要在复制<main>
元素之前想清楚它里面要放多少内容。cloneNode
是一个“实时”的复制方法:浏览器中任何对原始元素的改变都会反射到复制的元素上。
下面对制作这个效果总结4个要注意的地方。
- 因为IE浏览器不支持CSS filters,所以在IE浏览器中不会有效果。页面的内容还是会正常滚动,但是你不会看到任何磨砂效果。
- 在手机和平板上使用
fixed
属性要非常注意:手机浏览器在position: fixed
时可能会锁定某个屏幕的区域。 - 如果用户使用屏幕阅读器来浏览这个页面,它会阅读两次相同的内容。解决这个问题可以像下面这样:
<div id="blurrycontent" aria-hidden="true"></div>
- 在复制元素的时候要注意ID问题,被复制的元素不能使用ID,否则可能在后面的CSS和js中会发生异常不可测的错误。