在文本下方显示图像(并提供可接受的回退)

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费积分!

2014 年 4 月更新,内容更加现代化。

WebKit 支持酷炫的 background-clip CSS3 属性,您可以用它做一些非常棒的事情。我们第一次接触到它是在 iPhone 的滑动解锁 想法中,我们设置了一个渐变来在文本背景中进行动画。然后我们在 透明边框 想法中再次接触到它。

让我们看看如何使用它来使图像仅通过文本的字母可见。这是另一件很酷的事情,我们不再需要羡慕印刷设计师的能力了。

查看演示

基本思路

h1 {
   color: white;  /* Fallback: assume this color ON TOP of image */
   background: url(images/fire.jpg) no-repeat;
   -webkit-background-clip: text;
   -webkit-text-fill-color: transparent;
}

这就是全部内容。在元素上设置背景图像,然后裁剪它,并将文本填充颜色设置为透明。

问题

我确信每个人都痛苦地意识到,这并不会在所有浏览器中都起作用。当前的支持仅限于 WebKit。那么回退会发生什么?如您在上面的代码中看到的,您也声明了一个 color 值。此值在支持它的浏览器中会被 -webkit-text-fill-color 覆盖,因此我们在这里很清楚。然后在不支持 -webkit-background-clip: text 的浏览器中,我们将看到完整的背景图像,因此我们将看到背景图像上方的文本。因此,如果您不再阅读,请设置一个在该背景图像上清晰可见的颜色值。

所以我们得到了这样的效果

这并不是世界末日,至少我们准备了文本使其在某种程度上可读。但这与我们设想和 WebKit 用户将体验到的效果相差甚远。基本上:该回退很糟糕,让我们做得更好。

更好的回退

更好的回退的终极工具是 Modernizr。只需在您的页面上包含(相当小的)JavaScript 文件,它就会向您页面上的 html 标签添加类名,指示当前浏览器能够做什么。它还提供了一个用于在 JavaScript 中测试功能的 API,但我们今天不需要它。

不幸的是,Modernizr 没有开箱即用的 background-clip 测试。我问了其中一位创建者 Paul Irish,他为我提供了一种快速添加此测试的方法。整个部分

<script src="modernizr-1.6.min.js"></script>
<script>
  Modernizr.addTest('backgroundclip',function() {

    var div = document.createElement('div');

    if ('backgroundClip' in div.style)
      return true;

    'Webkit Moz O ms Khtml'.replace(/([A-Za-z]*)/g,function(val) { 
      if (val+'BackgroundClip' in div.style) return true;
    });

  });
</script>

现在我们将知道当前浏览器是否支持 background-clip,或者不支持。如果支持,则 html 标签将具有 backgroundclip 类,如果不支持,则将具有 no-backgroundclip 类。

现在我们在确定浏览器支持 background-clip 的情况下应用背景图像。

.backgroundclip h1 {
  background: url(images/west.jpg) -100px -40px no-repeat;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

h1 {
  color: orangered;
}

搞定,现在回退是一个纯色,而不是杂乱的图像剔除。

查看演示

但是……没有完美的系统可以做到这一点。

Android(包括 4.2 在内)存在一个问题,即它实际上不支持 -webkit-background-clip——即使任何测试都会返回它确实支持。该属性及其任何值(包括 text)。即使 Modernizr 的 testAllProps() 也无法捕获它。但是 -webkit-text-fill-color 确实有效,因此您基本上会得到一个没有文本的图像。非常糟糕。

如果您绝对需要使用它,您可能只需要针对 Android 进行 UA 测试

var NastyBrowserSniffing = {

  ua: navigator.userAgent.toLowerCase(),

  init: function() {
    var isAndroid = NastyBrowserSniffing.ua.indexOf("android") > -1;
    if (isAndroid) {
      $("html").addClass("android");
    }
  }

};

NastyBrowserSniffing.init();

如果是 Android,则恢复效果

html.android .gradient-text {
  color: white;
  background: none;
  -webkit-text-fill-color: white;
  -webkit-background-clip: border-box;
}
.gradient-text {
  background: -webkit-linear-gradient(gray, black);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

Stephen Morley 介绍了 如何使用滤镜为 IE 实现此效果