Shellway

CSS高级技巧:使用形状字符、图片精灵(sprites)和伪元素

2002年,Mark Newhouse发表了一篇题为“驯服列表”的有趣文章,文章中他解释了如何使用伪元素创建自定义列表标记。近10年后,Nicolas Gallagher提出“伪背景组”技术,其使用伪元素和图片精灵实现。

如今,站在巨人的肩上,我们试着更进一步。我们将探讨如何不通过使用多余的标记标签和使用一种友好的高对比的CSS图像精灵技术来为元素定义样式。这种技术可以很好的兼容IE6/7。

插图一

从特殊字符开始

我们有很多特殊字符可以替代图片,用以实现自定义图标。这可以改进:

  • 性能 (无HTTP请求);
  • 可用性 (这些字符将根据用户设置伸缩);
  • 维护 (无需图片精灵,无需组合图片碎片);
  • 可及 (详见下文)。
    <!–
    .glyphs {
    list-style-type: none;
    }

.glyphs li:before,
.glyphs b {
display: inline-block;
width: 1.5em;
font-size: 1.5em;
text-align: center;
}

.one,
.one:before {
content: “\2660”; //
background-image: expression(this.runtimeStyle.backgroundImage=”none”,this.innerHTML =’**♠’+this.innerHTML);
}

.two,
.two:before {
content: “\2663”; //
background-image: expression(this.runtimeStyle.backgroundImage=”none”,this.innerHTML =’♣**’
+this.innerHTML);
}

.three,
.three:before {
content: “\2665”; //
background-image: expression(this.runtimeStyle.backgroundImage=”none”,this.innerHTML =’
+this.innerHTML);
}

.four,
.four:before {
content: “\2666”; //
background-image: expression(this.runtimeStyle.backgroundImage=”none”,this.innerHTML =’
+this.innerHTML);
}

.red b,
.red:before {
color: red;
}
–>

例子:

如上列表的符号(♠, ♣, ♥, ♦)是通过以下HTML和CSS生成的:

HTML:

<ul class=”glyphs”>

<li class=”one”>performance</li>

<li class=”two”>usability</li>

<li class=”three red”>maintenance </li>

<li class=”four red”>accessibility</li>

</ul>

CSS:

.glyphs {
list-style-type: none;
}

.glyphs li:before,
.glyphs b {
display: inline-block;
width: 1.5em;
font-size: 1.5em;
text-align: center;
}

.one,
.one:before {
content: “\2660”; //
background-image: expression(this.runtimeStyle.backgroundImage=”none”,this.innerHTML =’<b>&spades;</b>’
+this.innerHTML);
}

.two,
.two:before {
content: “\2663”; //
background-image: expression(this.runtimeStyle.backgroundImage=”none”,this.innerHTML =’<b>&clubs;</b>’
+this.innerHTML);
}

.three,
.three:before {
content: “\2665”; //
background-image: expression(this.runtimeStyle.backgroundImage=”none”,this.innerHTML =’<b>&hearts;</b>’
+this.innerHTML);
}

.four,
.four:before {
content: “\2666”; //
background-image: expression(this.runtimeStyle.backgroundImage=”none”,this.innerHTML =’<b>&diams;</b>’
+this.innerHTML);
}

.red b,
.red:before {
color: red;
}

 

这是如何工作的?

  • content属性值必须是一个指向Unicode字符值的十六进制转义索引值(IE中,我们用CSS表达式来生成html代码)。
  • IE6、7不支持“::before”和“:before”伪元素,所以字符需要通过CSS表达式插入到HTML中。
  • IE8不支持“::before”,但是支持单冒号的“:before”。
  • 请注意:在不考虑浏览器支持与否的情况下,“:before”与“::before”或者“:after”与“::after”之间是没有什么区别的。CSS3之前的所有CSS版本中,单冒号的语法用作伪类和伪元素选择器。随着CSS3的引入,为了区分伪类和伪元素的区别,CSS3中的所有伪元素必须使用双冒号语法,而所有的伪类必须使用单冒号语法。
  • IE下,字符被包裹在<b>元素中,这样我们就可以定位到这些字符并给他们附上样式(您可能更喜欢用class来实现)。
    注意:此处使用的CSS表达式并非如用来模拟min-width之类的技术一般糟。这些只被执行一次,对性能的影响极小。

通过伪元素显示图片

使用伪元素来显示图片的主要优势在于,它允许设计师裁切图片精灵(sprites)。实际上,这也没什么新鲜的。如今很多站点已在使用附加标记(实则是垃圾标记)来实现此技术。如,雅虎搜索使用空的<s>元素,Facebook则用空的<i>标记来达到这个目的。此方法需要创建复杂的CSS图片精灵(sprites),其中图片之间没有空白间隔。

下面两例没有使用额外的标记,而且他们用的是同一张sprites图片:

Sprite in Styling Elements With Glyphs, Sprites and Pseudo-Elements

下面两张图,也就是上图的第二个图标,是用两种技术分别生成的。

Nicolas Gallagher的方法

给伪元素添加背景图:

#first:before {
  content: "";
  float: left;
  width: 15px;
  height: 15px;
  margin: 4px 5px 0 0;
  background: url(sprite.png) -15px 0;
}

新的url() / clip方法

使用content属性插入图片精灵,之后会被clip属性裁切:

#second {
position: relative;
padding-left: 20px;
background-image: expression(this.runtimeStyle.backgroundImage=”none”,this.innerHTML =
‘<img alt=”” src=”sprite.png”>’+this.innerHTML);
}

#second:before,

#second img {
content: url(sprite.png);position: absolute;
top: 3px;
clip: rect(0 30px 15px 15px);
left: -15px; / to offset the clip value /
_left: -35px; / some massaging for IE 6 /
}
可能你会纳闷,为什么我要在上面的规则中用position: absolute。那是因为clip属性仅会作用于绝对定位元素。

新技术:她是如何工作的?

  • 我们使用伪元素来插入图片(用content属性),而不是给元素定义背景样式。
  • 使用clip属性,我们裁切图片成我们想显示的那一部分。也就是说,我们再也没有必要为了避免显示图片的其他部分,而给图片添加多余的空白了(一般被用作大元素的背景图片)。
  • 我们用left和top属性使clip偏移到想要的位置。
    使用“无裁切”技术时,sprites中的图片应该右对齐或者左对齐排列来迎合RTL/LTR的文本排版模式(background-position: [left]|[right] [竖向值])。另外一个局限是,创建挨着排的图片sprites(其他图片可能也显示出来)。但是,用裁切sprites技术,这些问题就随之消失了,这样所有的图片就可以紧挨着排列了。

例如下图所示:

Figure-2 in Styling Elements With Glyphs, Sprites and Pseudo-Elements

此方法较之以前技术的优点:

打印样式
跟背景图片不一样,打印的时候,这些图片将会被传送到打印机中打印出来。

可及性样式
跟背景图片不一样的是,这些图片在微软视窗高对比度模式或者高对比样式表渲染下不会消失。

兼容IE8之前浏览器的样式
IE 6、7中同样有效.

注意:数据URI scheme可用于避免HTTP请求。IE6/7不支持数据URI scheme,但是我们可以使用IE6、7的MHTML来使IE7及更老浏览器也能理解它。

用伪元素定义链接样式

Nicolas Gallager秀出了 很多很酷的玩意儿,我们可以用这些来处理为元素。在此我仅说一件,就是用“::after”为链接添加样式,如下所示:

更多详情>>

CSS:

.more,
.more:after {
white-space: nowrap;
content: " \00BB"; /* » */
background-image: expression(this.runtimeStyle.backgroundImage="none",
this.innerHTML = this.innerHTML+' &raquo;');
}

可及性

您可以假设内容是给屏幕阅读器看的。既然没有任何机制可以为content属性所插入的图片提供替代文本,那我们就应该确保这些图片只是纯粹的装饰用的,原因是我们的屏幕阅读用户可能看不到这些图片信息。

原文作者:Thierry Koblentz

原文地址:http://www.smashingmagazine.com/2011/03/19/styling-elements-with-glyphs-sprites-and-pseudo-elements/