Skyphobia

CSS学习笔记(渐变色文本)

曾经在《利用Canvas实现网页文字颜色渐变》一文中提到过用Canvas解决非webkit/blink内核浏览器展示渐变色文字的方案。

用Canvas处理一些CSS难以解决的问题看似酷炫,实则有若干痛点(可能还不止这几点):

  • JavaScript掺和进了样式层面,有违纯粹原则;
  • Canvas依赖分辨率,对文本的渲染支持很差;
  • 在不支持Canvas的浏览器上难以回退样式。

因此在这里介绍下上次文章中提到的另一种网页文字颜色渐变的实现方案——SVG,它可以在一定程度上解决Canvas的这些痛点(当然也会引入一些新的问题,下面会提到)。下面祭出我们的利器,SVG Texts & Gradients。

SVG 文本

通过SVG 文本 (SVG Texts) ,我们可以在SVG中写入文本。相较HTML的文本而言,它既拥有DOM上的可操作性,又可以通过fill/stroke属性对文本本身进行千变万化的填充,其中就包括实现文字渐变的关键:SVG 渐变 (SVG Gradients)

下面的代码创建了一个font-size为2rem的SVG文本:

看上去和普通的文本没什么区别

1
2
3
4
5
<svg xmlns="http://www.w3.org/2000/svg">
<text dy="2rem" class="hanzo">
竜が我が敵を喰らう!
</text>
</svg>
1
2
3
.hanzo {
font-size: 2rem;
}

创建出来的SVG文本和普通的HTML文本看上去并没有什么很大的差异,它同样可以被用户选择、复制或者粘贴,看起来这是一个不错的开端。

SVG 渐变

有两种类型的SVG 渐变 (SVG Gradients) ,线性渐变和径向渐变。前者沿着直线改变颜色,后者从一个点开始发散改变颜色,分别用<linearGradient><radialGradient>来定义。
要注意的是,这里做的仅仅只是定义,如果不被其他SVG元素引用的话,被定义的SVG渐变并不会产生任何视觉上的效果。此外,虽然可以在svg画布上直接定义这两种渐变,但出于可读性和复用性的考虑,推荐把它们定义在<defs>内部:

1
2
3
4
5
6
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient></linearGradient>
<radialGradient></radialGradient>
</defs>
</svg>

现在我们创建了两个没有任何效果的SVG渐变,接下来就是见证奇迹的时刻。

线性渐变

x1x2y1y2四个属性定义了渐变路线走向,可以设置为百分比,默认水平方向。
定义在<linearGradient>内部的<stop>结点用于指定渐变的offset(偏移位置)以及stop-color颜色中值。

下面的代码创建了一个纵向红白渐变:

1
2
3
4
5
6
7
8
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient x1="0" y1="0" x2="0" y2="100%">
<stop stop-color="red" offset="10%" />
<stop stop-color="white" offset="90%" />
</linearGradient>
</defs>
</svg>

径向渐变

径向渐变的<stop>和线性渐变相似,<radialGradient>略显复杂:cxcy定义渐变中心,r定义渐变半径,fxfy定义了渐变的焦点。

下面的代码创建了一个中心扩散的红白渐变:

1
2
3
4
5
6
7
8
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop stop-color="red" offset="10%" />
<stop stop-color="white" offset="90%" />
</radialGradient>
</defs>
</svg>

最终实现效果

最后在SVG文本上通过fill属性或者CSS的fill属性应用应用上之前创建的SVG渐变就能看到最终效果了:

最终实现效果

1
2
3
4
5
6
7
8
9
10
11
<svg xmlns="http://www.w3.org/2000/svg">
<text dy="2rem" class="hanzo">
竜が我が敵を喰らう!
</text>
<defs>
<linearGradient x2="0" y2="100%" id="red-white">
<stop stop-color="red" offset="10%" />
<stop stop-color="white" offset="90%" />
</linearGradient>
</defs>
</svg>
1
2
3
4
5
6
7
8
svg {
width: 20rem;
height: 2.5rem;
.hanzo {
font-size: 2rem;
fill: url('#red-white');
}
}

关于兼容和样式回退

通过Can I use可以看到SVG在主流浏览器中的支持程度几乎是一片绿灯的,在不关心IE8及以下用户的时候可以放心使用SVG来实现渐变色文本。

IE8以上的主流浏览器均支持SVG

至于在那些不支持SVG的浏览器中,我们的SVG文本会像过了午夜零时的灰姑娘一样失去绚丽的外表,恢复成原本黑漆漆的文字。不过这点总比只能显示原本预设好内容的Canvas要好,因为我们还能用CSS为黑漆漆的SVG文本(这个时候只是普通的HTML文本了)提供基础的回退样式。

还是啰嗦个几句

最早在写GSR第四版的时候发现Canvas不太适合用来实现渐变色文本的问题,那个时候对SVG不怎么了解,最近在看《CSS Secrets》时意识到了SVG的便利性,一直在琢磨是时候该尝试用SVG来替代Canvas实现这个效果了,毕竟用JS来操作这种样式实在是蛋疼得不要不要的……

十界 Jikkai Xiao
Shanghai China

就职于普陀区中环餐饮联锁的前端膜法师、一生あさきスト、碱式碳酸铜名 GITADORA 玩家、SLG 厨、猫奴。