定制图片加载失败时的样式

2016-03-28 W.Y. 更多博文 » 博客 » GitHub »

Styling

原文链接 https://bubkoo.github.io/2016/03/28/styling-broken-images/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


<img src="http://bubkoo.com/broken.jpg" alt="图片加载失败,默认样式有木有很丑陋?" class="no-fancy">
.no-fancy{
    margin-top:20px;
}

但也并非一定要如此,我们可以通过 CSS 为加载失败的图片定制样式,提供更好的体验。

<!--more-->

关于 img 标签的两个事实

要了解如何为破裂的图片定制样式,需要先搞清楚连个事实:

  1. 我们可以为 <img> 元素指定字体样式,这些样式将用于破裂图片的替代文字,不会影响正常显示的图片。
  2. <img> 元素实际上是一种替换元素,其外观和尺寸由外部资源定义,所以通常情况下 :before:after 这两个伪元素都不起作用,一旦图片加载失败时这两个伪元素将出现。

正是基于以上两点,我们可以为破裂的图片定制样式,而不会影响正常加载的图片。

实践

使用下面的无效的图片地址:

<img src="http://bubkoo.com/broken.jpg" alt="图片裂开了" >

添加一些帮助信息

处理破裂图片的一种方式就是为破裂图片提供更多的帮助信息,以方便用户理解这是一个破裂的图片,使用 attr() 表达式我们还可以将破裂图片的地址显示出来。

<img src="http://bubkoo.com/broken.jpg" alt="图片裂开了" class="no-fancy broken-img">
.broken-img {  
  font-family: 'Helvetica';
  font-weight: 300;
  line-height: 2;  
  text-align: center;

  width: 100%;
  height: auto;
  display: block;
  position: relative;
}

.broken-img:before {  
  content: "We're sorry, the image below is broken :(";
  display: block;
  margin-bottom: 10px;
}

.broken-img:after {  
  content: "(url: " attr(src) ")";
  display: block;
  font-size: 12px;
}

替换默认的替代文本

我们可以使伪元素盖在破裂的图片元素之上,从而在外观上替换掉默认的替代文本:

<img src="http://bubkoo.com/broken.jpg" alt="图片裂开了" class="no-fancy broken-img-alt">
.broken-img-alt {  
  font-family: 'Helvetica';
  font-weight: 300;
  line-height: 2;  
  text-align: center;

  width: 100%;
  height: auto;
  display: block;
  position: relative;
}
.broken-img-alt:after {  
  content: "\f016" " " attr(alt);

  font-size: 16px;
  font-family: FontAwesome;
  color: rgb(100, 100, 100);

  display: block;
  position: absolute;
  z-index: 2;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #fff;
}

更丰富的样式

除了定制自定义的提示信息外,我们还可以通过伪元素来提供更丰富的样式。

<img src="http://bubkoo.com/broken.jpg" alt="图片裂开了" class="no-fancy broken-more">
.broken-more {  
  font-family: 'Helvetica';
  font-weight: 300;
  line-height: 2;  
  text-align: center;

  width: 100%;
  height: auto;
  min-height: 50px;
  display: block;
  position: relative;
}
.broken-more:before {  
  content: " ";
  display: block;

  position: absolute;
  top: -10px;
  left: 0;
  height: calc(100% + 10px);
  width: 100%;
  background-color: rgb(230, 230, 230);
  border: 2px dotted rgb(200, 200, 200);
  border-radius: 5px;
}
.broken-more:after {  
  content: "\f127" " Broken Image ";
  display: block;
  font-size: 16px;
  font-style: normal;
  font-family: FontAwesome;
  color: rgb(100, 100, 100);

  position: absolute;
  top: 5px;
  left: 0;
  width: 100%;
  text-align: center;
}

浏览器兼容性

不幸的是,这种方案并不兼容所有浏览器。对某些浏览器而言,即便是图片破裂了,伪元素也不会出现。

下面是通过我的测试列举出来的兼容表:

Browser Alt :before: :after:
Chrome (Desktop and Android)
Firefox (Desktop and Android)
Opera (Desktop)
Opera Mini ✓ **
Safari (Desktop and iOS) ✓ *
iOS Webview (Chrome, Firefox, others) ✓ *

** 不支持定义替代文本的样式 * 只有当图片的宽度足够包含替换文本时才显示,如果没有为图片指定宽度,那么替代文本可能压根就不显示

对于那些不支持伪元素的浏览器,为伪元素指定的样式也将被忽略,所以不用担心会打乱页面布局。这意味着我们可以为那些兼容的浏览器定制这类样式,为用户提供一个更好的体验。