一些不规则投影的解决办法

 2016-10-03 14:50

当我们想给一个矩形或者其他能用border-radius生成的形状加投影时,box-shadow的表现都堪称完美。但是,当元素增加一个伪元素或者半透明的装饰之后,它就有些力不从心了。因为border-radius会忽视部分透明。这类情况包括:

  • 半透明图像、背景图像或者border-image;

  • 元素设置了点状、虚线或者半透明的边框,但没有背景的;

  • 对话气泡,它的小尾巴常用伪元素生成的;

  • 几乎所有的折角;

  • 通过clip-path生成的形状,比如“菱形图片”。

如果我们打算对这类元素直接用box-shadow,那会得到一些奇怪的效果,怎么来解决这个问题呢?

滤镜效果(不完全支持)

滤镜效果规范为这个问题提供了一个解决方案:filter,这个属性也是从SVG那里借鉴过来的。尽管CSS滤镜基本上就是SVG滤镜,但我们并不需要任何的SVG知识。相反,只需要一些函数就可以很方便地指定滤镜效果了,比如:blur()、grayscale()以及我们需要的deop-shadow()!如果你喜欢,甚至可以把多个滤镜串连起来,只要空格把它们隔开就可以了,比如:

filter:blur() grayscale() deop-shadow();

deop-shadow()滤镜可接受的参数基本上跟box-shadow属性是一样的,但不包括扩张半径,不包括inset关键字,也不支持逗号分割的多层投影语法。它就像这样:

filter:drop-shadow(2px 2px 10px rgba(0,0,0,.5));

CSS滤镜最大的好处在于它们可以平稳退化:当浏览器不支持时,不会出现问题,只不过没有任何效果而已。如果你确实需要这个效果在尽可能多的浏览器中显示出来,可以同时附上一个SVG滤镜,这样可以得到稍微好一些的浏览器支持。

你可以在滤镜效果规范(http://www.w3.org/TR/filter-effects)中为每个滤镜函数找到对应的SVG滤镜版本。可以把SVG滤镜和简化的CSS滤镜放在一起使用,让层叠机制来决定哪一行最终生效:

filter:url(drop-shadow.svg#drop-shadow);
filter:drop-shadow(2px 2px 10px rgba(0,0,0,.5));

不幸的是,如果SVG滤镜是存放在一个独立文件里,那它就无法像一个简洁易用的函数那样在CSS代码中进行随意配置;如果它是内联的,则又会搅乱你的代码。参数需要写死在文件内部,因此每当我们新加一种,都需要多装备一个文件,这显然是难以接受的。这个方法只有一种回退方案,因此只要我们把SVG滤镜控制在一定数量以内,哪怕他们的效果大同小异,也是说得过去的。

另外一件需要牢记的事情就是,任何非透明的部分都被一视同仁地打上投影,包括文本。

作者头像

作者:紫铜炉

自由博主,网页设计师。我关注科技产品和个人博客发展,注重用户体验和界面优化。

 发表评论: