让我们创建一个纯 CSS 效果,在悬停时更改文本链接的颜色…… 但让新颜色滑入,而不是简单地交换颜色。

我们可以使用四种不同的技术来做到这一点。 让我们在了解重要事项(如可访问性、性能和浏览器支持)的同时,研究一下这些技术。
让我们开始吧!
技术 1:使用 background-clip: text
在撰写本文时,background-clip: text
属性是一个实验性功能,在 Internet Explorer 11 及更低版本中不受支持。
此技术涉及使用 击穿文本 和 硬停止渐变。 标记包含单个 HTML 链接(<a>
)元素以创建超链接。
<a href="#">Link Hover</a>
我们可以开始向超链接添加样式。 使用 overflow: hidden
将在悬停过渡期间剪切超链接外部的任何内容。
a {
position: relative;
display: inline-block;
font-size: 2em;
font-weight: 800;
color: royalblue;
overflow: hidden;
}
我们需要使用线性渐变,并在 50% 处硬停止到我们希望链接为的起始颜色以及它将更改到的颜色。
a {
/* Same as before */
background: linear-gradient(to right, midnightblue, midnightblue 50%, royalblue 50%);
}
让我们使用 background-clip
剪切渐变,并使用 text
值显示文本。 我们还将使用 background-size
和 background-position
属性使起始颜色出现。
a {
/* Same as before */
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 200% 100%;
background-position: 100%;
}
最后,让我们将 transition
CSS 属性和 :hover
CSS 伪类添加到超链接。 为了让链接在悬停时从左到右填充,请使用 background-position
属性。
a {
/* Same as before */
transition: background-position 275ms ease;
}
a:hover {
background-position: 0 100%;
}
虽然此技术确实实现了悬停效果,但 Safari 和 Chrome 将 剪切文本装饰和阴影,这意味着它们不会显示。 使用 text-decoration CSS 属性应用文本样式(如下划线)将不起作用。 也许可以考虑使用 其他方法来创建下划线。
技术 2:使用 width/height
这是通过使用 数据属性 来实现的,该属性包含与 <a>
标签中的文本相同的文本,并将 width
(从左到右或从右到左填充文本)或 height
(从上到下或从下到上填充文本)从 0% 设置为 100% 在悬停时。
这是标记:
<a href="#" data-content="Link Hover">Link Hover</a>
CSS 与之前技术类似,减去了 background CSS 属性。 text-decoration
属性在这里可以工作。
a {
position: relative;
display: inline-block;
font-size: 2em;
color: royalblue;
font-weight: 800;
text-decoration: underline;
overflow: hidden;
}
这是我们需要使用 data-content
属性中的内容时。 它将放置在 <a>
标签中的内容上方。 我们将使用一个小技巧,即复制数据属性中的文本,并通过元素的 ::before
伪元素的内容属性上的 attr()
函数来显示它。
a::before {
position: absolute;
content: attr(data-content); /* Prints the value of the attribute */
top: 0;
left: 0;
color: midnightblue;
text-decoration: underline;
overflow: hidden;
transition: width 275ms ease;
}
为了防止文本换行,将应用 white-space: nowrap
。 为了更改链接填充颜色,请使用 ::before
伪元素设置颜色 CSS 属性的值,并将 width
从 0 开始。
a::before {
/* Same as before */
width: 0;
white-space: nowrap;
}
将 ::before
伪元素的 width
增加到 100%,以在悬停时完成文本效果。
a:hover::before {
width: 100%;
}
虽然此技术确实有效,但使用 width
或 height
属性不会产生 高性能 CSS 过渡。 最好使用 transform
或 opacity
属性来实现流畅的 60fps 过渡。
使用 text-decoration
CSS 属性可以使不同的下划线样式在 CSS 过渡中出现。 我创建了一个演示,展示了使用下一项技术(clip-path
CSS 属性)来实现这一点。
技术 3:使用 clip-path
对于此技术,我们将使用带有多边形形状的 clip-path
CSS 属性。 多边形将有四个顶点,其中两个在悬停时向右扩展。

标记与之前的技术相同。 我们将再次使用 ::before
伪元素,但 CSS 不同。
a::before {
position: absolute;
content: attr(data-content);
color: midnightblue;
text-decoration: underline;
clip-path: polygon(0 0, 0 0, 0% 100%, 0 100%);
transition: clip-path 275ms ease;
}
与之前的技术不同,必须将 text-decoration: underline
声明为 ::before 伪元素
,以便颜色在悬停时填充下划线。
现在让我们看看 clip-path
技术的 CSS。
clip-path: polygon(0 0, 0 0, 0% 100%, 0 100%);
clip-path
属性的多边形顶点以百分比设置,以按写入顺序定义坐标。
0 0
= 左上角0 0
= 右上角100% 0
= 右下角0 100%
= 左下角
通过修改坐标可以更改填充效果的方向。 现在我们已经了解了坐标,我们可以让多边形在悬停时向右扩展。
a:hover::before {
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}
此技术效果很好,但请注意,clip-path
属性的浏览器 支持程度各不相同。 使用 clip-path
创建 CSS 过渡是比使用 width
/height
技术更好的选择; 但是,它确实会影响浏览器 绘制。
技术 4:使用 transform
此技术的标记使用带有 <span>
元素的遮罩方法。 由于我们将在一个单独的元素中使用重复的内容,因此我们将使用 aria-hidden="true"
来 提高可访问性 - 这将使它对屏幕阅读器隐藏,因此内容不会被读取两次。
<a href="#"><span data-content="Link Hover" aria-hidden="true"></span>Link Hover</a>
<span>
元素的 CSS 包含一个过渡,该过渡将从左侧开始。
span {
position: absolute;
top: 0;
left: 0;
overflow: hidden;
transform: translateX(-100%);
transition: transform 275ms ease;
}
接下来,我们需要让 <span>
像这样向右滑动。

为此,我们将使用 translateX()
CSS 函数并将其设置为 0。
a:hover span {
transform: translateX(0);
}
然后,我们将使用 <span>
的 ::before
伪元素,再次使用之前使用的 data-content
属性。 我们将通过沿 x 轴平移 100% 来设置位置。
span::before {
display: inline-block;
content: attr(data-content);
color: midnightblue;
transform: translateX(100%);
transition: transform 275ms ease;
text-decoration: underline;
}
与 <span>
元素非常相似,::before
伪元素的位置也将设置为 translateX(0)
。
a:hover span::before {
transform: translateX(0);
}
虽然此技术是其中跨浏览器兼容性最好的技术,但它需要更多标记和 CSS 来实现。 也就是说,使用 transform CSS 属性对 性能而言很棒,因为它不会触发重绘,从而产生流畅的 60fps CSS 过渡。
就是这样!
我们刚刚研究了四种实现相同效果的不同技术。 尽管每种技术都有其优缺点,但您可以看到,在文本上滑动颜色变化完全有可能。 这是一种很酷的小效果,让链接感觉更具互动性。
用另一种变换抵消一种变换并不能在所有浏览器和设备上产生稳定的结果。 例如:它在 Firefox 中会产生非常明显的 1 像素抖动。
仅在我系统上的嵌入式 codepen 中。 在新选项卡中打开 codepen 可以解决这个问题,这可能就是作者没有遇到这个问题的原因。
在看到技术 4 中提到了可访问性之后,我想知道技术 2 和 3 是否也会出现可访问性问题。 我认为,屏幕阅读器也会读取伪元素中的重复内容以及实际的链接文本。
看起来有一种方法可以为“content”css 属性设置备用文本
https://stackoverflow.com/questions/47438877/how-to-hide-css-generated-content-from-screen-readers-without-html-markup/47451397#47451397
Katherine,专业级黑客,感谢!
我用最后一个例子做了一个 Svelte 组件
https://svelte.net.cn/repl/c6aefed780b949139dea95a323d8e48f?version=3.19.2
哈哈。不过可能会在项目中使用它。
和酷一样简单。非常感谢这些小技巧。
也试试这个