CSS element()函数

发布于 大漠

七月份我写了一篇有关于先进的CSS filters技术,比如说backdrop-filterfilter()的特性。今天我想分享一个更牛逼的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-repeatbackground-size等等。

拿个示例来演示一下我们前面所说的一切。(请使用Firefox浏览示例,才能看到效果(^_^))

如果你没有安装Firefox浏览器,下面的视频演示了Demo的整个效果:

Firefox浏览器中效果

记住,任何网站的任何部分都可以被引用,如果你需要,整个网站都可以被引用。不过有一点需要小心,当心自身是引用元素的子元素,如果这样的话,元素可能会出现两次或更多次。值得庆幸的是,Firefox做得较好的是可以递归引用。

**element()以一种轻松的方式将CSS设计提高到一个新的水平。**自从版本4的出现,我的很多想法都得以实现。

  • 在一些高级效果中不需要处理重复的内容
  • 可以在一张幻灯片(slideshow)中显示前一张和下一张的缩略图
  • 放大一张图片,比如说在一个电子商务产品的页面中
  • 使用CSS的动画、视频、canvas或者svg可以实现动画背景
  • 模拟backdrop-filter或者filter()效果
  • 实现水印背景效果(@Lea Verou的创意)

注意事项

在使用element()函数时,有些事项需要注意:

浏览器兼容性

前面提及到多次了,目前仅Firefox支持这个特性,希望以后会有更多浏览器支持。有关于element()的兼容性,可以查看下表:

倒影(Reflections)

众所周知,倒影的效果在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制作倒影》。

3D折叠效果

制作一些特效,有时你不得不处理重复的内容,唯一合理的理由是通过JavaScript来处理。如果处理的是静态内容,比如说图像、文本等是较为容易;反之,如果处理的是动态内容,那就让你痛不欲生。如果你使用element(),你的人生一下就变得美好幸福了。

例如,你可以轻松的将Twitter登录表单折叠成两半(在Firefox浏览器中把鼠标悬停在表单上能看到效果):

Firefox下的效果

让我来解释一下:

  • HTML创建登录表单并且设置定位
  • 通过mask制作一个朦板覆盖在登录表单上,设置不可见
  • 通过两个伪元素(::before::after)添加两个登录表单,并且放在蒙板的上面
  • 使用element()渲染登录表单,并且将这两个伪元素定位在完全相同的位置
  • 使用CSS的transformanimationfilter给这两个伪元素添加特效
  • 使用pointer-events:none;给表单设置防穿透
  • 将其放置在@supports里面,只有支持element()函数的浏览器才能看到效果

更深入一层,我们可以折叠页面里的任何东西,如下面的地图效果:

Firefox中效果

动画背景图

还有一个简单的效果,就是创建动画背景。你可能会认为动画背景是GIF动画,其实element()可以使用<video><canvas>或者<svg>来实现动画背景。结合<video><canvas>和一些重复的内容,你就可以创建一个奇特的效果,而且你可以随时在上面画画,在背景中就能产生对应效果。很好玩!

Firefox中效果

你可能会注意到,这个示例的效果在Webkit浏览器中也能运行。方法如下:

  • 在CSS背景中使用<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:0overfow:hidden。这样,页面中的元素仍然存在,但是不再可见,这样你就可以不要蒙层。问题是,一些浏览器对unvisible元素(CSS动画,GIF动画等等)会降低浏览器性能,这并不是我们想要的结果。

所以我最终使用了蒙层的技术。不知道您还有没有更好的解决方案。

如果您对蒙层相关技术从未有过了解,可以点击这里进行了解。

总结

希望你看完这篇文章之后,你会觉得element()函数是有多么的强大,尽管浏览器对其支持度很低,并且性能较差。你应该尝试一下自己去写一些效果,并且将这些效果分享出来。我们是在为我们的兴趣而努力,而且我们不断的在使用与推广也能促进浏览器对其支持度的提高与改进。

本文根据@iamvdo的《CSS element() function》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://iamvdo.me/en/blog/css-element-functionKyrie 1 Dark Grey Silver Grey Dark Reflect Black Green Glow 705277-001