七月份我写了一篇有关于 先进的CSS filters技术 ,比如说 backdrop-filter
和 filter()
的特性。今天我想分享一个更牛逼的CSS特性。但是在分享之前让大家先知道,这个特性到目前为止只有 Firefox 浏览器支持,而且其他浏览器还没有表示要支持这个特性。当然,有可能后面会支持这个特性,但这并不影响我们一起对这个特性的探讨。
有关于CSS filters相关的技术,可以阅读《高级CSS filters》一文。
如果你不太使用Firefox,你要看到文中的演示示例的效果,你得切换到Firefox下。当然,你也可以通过示例下的视频看示例的演示效果。
element()
CSS图像值和内容替换模块四( CSS Image Values and Replaced Content Module Level 4 )介绍了 element()
函数。其实该模块的第三个版本就定义了这个函数,2011年5月份第四版本出来时就得到了Firefox浏览器的支持。简单点说, 这个函数可以将网站中的某部分当作图片渲染 。当一个DOM元素在浏览器中得到正确的渲染时,其实你得到的就是一张图片。只要修改了元素图片就会立马得到改变,甚至是选中文本也能呈现出来。
2011年我发现这个特性时,我无法相信自己的眼睛。它真的很酷,不由让人觉得,没有做不到的,只有想不到的。
那么我们来往下看,它的语法是非常简单。你只需要给渲染成图像的元素定认一个 id
属性。举个例子来说,这里有一个 div#css-source
元素,其包含了图片和文本,而且将 div#css-source
元素当作 div#css-result
元素的背景图像来渲染。
<div id="css-source"> <p>Lorem ipsum</p> <img src="" alt=""> </div> <div id="css-result"></div> #css-result { background: element(#css-source); background-size: 50% 50%; }
使用 element()
函数实际上是创建了一个图像,就像是一张背景图,可以使用熟悉的CSS属性来控制它,比如 background-repeat
、 background-size
等等。
拿个示例来演示一下我们前面所说的一切。( 请使用Firefox浏览示例,才能看到效果(^_^) )
如果你没有安装Firefox浏览器,下面的视频演示了Demo的整个效果:
记住,任何网站的任何部分都可以被引用,如果你需要,整个网站都可以被引用。不过有一点需要小心,当心自身是引用元素的子元素,如果这样的话,元素可能会出现两次或更多次。值得庆幸的是,Firefox做得较好的是可以递归引用。
element()
以一种轻松的方式将CSS设计提高到一个新的水平。 自从版本4的出现,我的很多想法都得以实现。
canvas
或者 svg
可以实现动画背景 backdrop-filter
或者 filter()
效果 在使用 element()
函数时,有些事项需要注意:
-moz-element()
backdrop-filter
和 filter()
更差,但还是很有必要考虑的 前面提及到多次了,目前仅Firefox支持这个特性,希望以后会有更多浏览器支持。有关于 element()
的兼容性,可以查看下表:
众所周知,倒影的效果在Web中运用的并不广泛,但这个效果能帮助大家更好的理解 element()
的特性。下面的示例演示的是一个图像及其 <figcaption>
都放在 <figure>
标签内。在 <figure>
的伪元素 ::after
上运用 element()
在 Y
做了一个翻转,生成一个倒影效果,并且配合一个SVG做渐入的朦板效果。而整个效果通过 @supports
做了一个渐进增强处理:
<figure class="reflection" id="css-element"> <img src="image.jpg" alt=""> <figcaption>San Francisco, CA</figcaption> </figure> @supports (background: element(#css-element)) { .reflection::after { background: element(#css-element); transform: scaleY(-1); mask: url('#mask'); opacity: .3; } }
这个效果可以在Firefox中运行,对于Webkit内核的浏览器,可以通过Webkit私有属性 -webkit-box-reflect
属性来制作。对于IE或Edge那就没法玩了。
是的,看这种效果会让你的眼睛很疲劳。我们不纠结这个,继续往下,了解更有意思的东东。
在Webkit内核的浏览器有一个私有属性 -webkit-box-reflect
可以轻易实现倒影效果,如果你对这个属性的使用感兴趣的话,可以阅读早前分享的一篇博文《使用CSS3制作倒影》。
制作一些特效,有时你不得不处理重复的内容,唯一合理的理由是通过JavaScript来处理。如果处理的是静态内容,比如说图像、文本等是较为容易;反之,如果处理的是动态内容,那就让你痛不欲生。如果你使用 element()
,你的人生一下就变得美好幸福了。
例如,你可以轻松的将Twitter登录表单折叠成两半(在Firefox浏览器中把鼠标悬停在表单上能看到效果):
让我来解释一下:
mask
制作一个朦板覆盖在登录表单上,设置不可见 ::before
和 ::after
)添加两个登录表单,并且放在蒙板的上面 element()
渲染登录表单,并且将这两个伪元素定位在完全相同的位置 transform
、 animation
和 filter
给这两个伪元素添加特效 pointer-events:none;
给表单设置防穿透 @supports
里面,只有支持 element()
函数的浏览器才能看到效果 更深入一层,我们可以折叠页面里的任何东西,如下面的地图效果:
还有一个简单的效果,就是创建动画背景。你可能会认为动画背景是GIF动画,其实 element()
可以使用 <video>
、 <canvas>
或者 <svg>
来实现动画背景。结合 <video>
, <canvas>
和一些重复的内容,你就可以创建一个奇特的效果,而且你可以随时在上面画画,在背景中就能产生对应效果。很好玩!
你可能会注意到,这个示例的效果在Webkit浏览器中也能运行。方法如下:
<video>
标签替换了GIF动画。缺点是GIF文件比视频文件在大好多: ~4MB
(GIF动画) 对比 ~400KB
(MP4)和 ~600KB
(WEBM)。所以在这种情况下减少帧数。 -webkit-canvas()
,其类似于 element()
功能,但只限于 <canvas>
元素。在这里我引用了一个 <canvas>
,这是一个不坏的解决方案。值得注意,这不是一个标准的函数,有可能会被弃用。 backdrop-filter
效果 使用 element()
可以轻易的模拟出 backdrop-filter
的效果。你所有做的就是给一个元素设置一个 background
。是很简单吧。
你可以在 以前的文章中看到相关的示例 ,现在可以在支持 element()
的Firefox中看到同样的效果:
注: backdrop-filter
属性到目前仅在Safari9+能实现效果。
再来看一个动态让文本模糊的效果:
用代码帮我解释这发生的一切吧:
h1 { … } @supports ( backdrop-filter: blur(1px) ) { h1 { backdrop-filter: grayscale(1) contrast(3) blur(1px); } } @supports (not (backdrop-filter: blur(1px))) and (background: element(#back)) { h1::before { content: ''; position: absolute; z-index: -1; top: 0; left: 0; bottom: 0; right: 0; background: element(#back) fixed; filter: grayscale(1) contrast(3) blur(1px); } }
使用 @supports
,你可以测试出:
backdrop-filter
得到支持,样式将运用于 <h1>
上生效 backdrop-filter
没得到支持,但 element()
得到支持,创建一个伪元素并且定位到标题的下面,设置他的背景,并且运用 filter
属性。 值得一提的,你可以使用SVG模拟 backdrop-filter
效果,例如下面的示例:
这种方式得到较好的支持,但也有很多缺点。这个SVG Filter不是动态的。事实上,任何浏览器都支持backgroundImage做为过滤器的输入源( backgroundImage as input for filter primitives )。IE/Edge放弃了对 enable-background
属性来 接受backgroundImage的输入源 ,但这仅仅是SVG内容。
在许多效果中,我们不得不创建一个蒙板层来隐藏这个引用源。那是因为现实中无法给一个设置了 display:none
的元素引用到背景中。实际上,这个元素一直都不应该显示。
我也尝试着将引用源放在一个 <div>
的标签内,并且设置 height:0
和 overfow:hidden
。这样,页面中的元素仍然存在,但是不再可见,这样你就可以不要蒙层。问题是,一些浏览器对unvisible元素(CSS动画,GIF动画等等)会降低浏览器性能,这并不是我们想要的结果。
所以我最终使用了蒙层的技术。不知道您还有没有更好的解决方案。
如果您对蒙层相关技术从未有过了解,可以点击这里进行了解。
希望你看完这篇文章之后,你会觉得 element()
函数是有多么的强大,尽管浏览器对其支持度很低,并且性能较差。你应该尝试一下自己去写一些效果,并且将这些效果分享出来。我们是在为我们的兴趣而努力,而且我们不断的在使用与推广也能促进浏览器对其支持度的提高与改进。
本文根据 @iamvdo 的《 CSS element() function 》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处: http://iamvdo.me/en/blog/css-element-function 。
常用昵称“大漠”,W3CPlus, Sass中国 创始人,目前就职于手淘。中国Drupal社区核心成员之一。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《 图解CSS3:核心技术与案例实战 》。