css 挑战——四种方式实现文字颜色滑动

701 阅读4分钟

css-art.jpg
先看下效果

hover.gif

可以看到并不是简单地hover改变文字颜色,而是颜色滑动改变效果

方法1:使用背景渐变

<a href="#">A smile hovered on her lips</a>
a{
    position: relative;
    font-size: 30px;
    color: #333;/*无效*/
    overflow: hidden;
    background: linear-gradient(to right, #1890ff, #1890ff 50%, #333 50%);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-size: 200% 100%;
    background-position: 100%;
    transition: background-position 0.3s ease;
}
a:hover {
    background-position: 0 100%;
}

实现该效果的要点

background: linear-gradient------背景渐变,这个不用多说

background-clip: text------设置背景的绘制区域只针对文字

text-fill-color: transparent------文字的填充颜色,值为透明时,背景渐变才会对文字生效;该属性跟color同时设置时,会覆盖掉color

background-size: 200% 100%------使背景的长度扩大为原来的两倍,也就是文字长度的两倍

background-position: 100%------这个属性的百分比并不是根据父元素的宽度来计算的,它有自己的一些计算原理

background-position: x y x:{容器(container)的宽度—背景图片的宽度}*x百分比,超出的部分隐藏。 y:{容器(container)的高度—背景图片的高度}*y百分比,超出的部分隐藏。

  • top left, left top 等价于 0% 0%.
  • top, top center, center top 等价于 50% 0%.
  • right top, top right 等价于 100% 0%.
  • left, left center, center left 等价于 0% 50%.
  • center, center center 等价于 50% 50%.
  • right, right center, center right 等价于 100% 50%.
  • bottom left, left bottom 等价于 0% 100%.
  • bottom, bottom center, center bottom 等价于 50% 100%.
  • bottom right, right bottom 等价于 100% 100%.

方法2:伪元素+宽度变化

<a href="#" data-content="A smile hovered on her lips">A smile hovered on her lips</a>
a{
    position: relative;
    font-size: 30px;
    color: #333;
    font-weight: 800;
    text-decoration: underline;
    overflow: hidden;
}
a::before {
    position: absolute;
    top: 0;
    left: 0;
    width: 0;
    content: attr(data-content);
    color: #1890ff;
    text-decoration: underline;
    transition: width .3s ease;
    overflow: hidden;
    white-space: nowrap;
}
a:hover::before {
    width: 100%;
}

这个方法比较简单,主要是伪元素使用attr属性获取标签自定义属性的值,伪元素初始宽度为0,并定位到a标签的最左边,然后设置伪元素的内容强制不换行

方法3:伪元素+clip-path

<a href="#" data-content="A smile hovered on her lips">A smile hovered on her lips</a>
a::before {
    position: absolute;
    content: attr(data-content);
    color: #1890ff;
    text-decoration: underline;
    clip-path: polygon(0 0, 0 0, 0% 100%, 0 100%);
    transition: clip-path .3s ease;
}
a:hover::before {
    clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}

要点:跟第二种方法有点类似,只不过换了种思路,使用了clip-path:路径剪切

先看下clip-path的值

  • 0 0 = 左上方
  • 0 0 = 右上方
  • 100% 0 = 右下
  • 0 100% = 左下角

如果不太理解,这里分享一个很有意思的网站css路径剪切生成器,可能你会豁然开朗

方法4:伪元素+translate

<a href="#">
    <span data-content="A smile hovered on her lips">
    </span>
    A smile hovered on her lips
</a>
a span{
    position: absolute;
    top: 0;
    left: 0;
    overflow: hidden;
    transform: translateX(-100%);
    color: #1890ff;
    transition: transform 0.3s ease;
}
span::before { 
    display: inline-block;
    content: attr(data-content);
    color: #1890ff;
    transform: translateX(100%);
    transition: transform .3s ease;
    text-decoration: underline;
}
a:hover span {
    transform: translateX(0);
}
a:hover span::before {
    transform: translateX(0);
}

要点:这里在a标签里面嵌套了一个span元素,然后用translateX把该元素移动到了a标签的外面;span元素设置了一个伪元素,同上面一样,用attr属性获取标签自定义属性的值,也用translateX把伪元素移动到跟a标签重合的位置,因为span元素设置了overflow: hidden,所以该元素不会表现出来,hover的时候同时移动span跟伪元素使他们重合

来看下放慢并去掉overflow:hidden的效果

1.gif

只从视觉效果可以看到span标签的伪元素并没有发生移动,但其实是在相对span元素在移动

总结一下

上面四种方法相对来说,第二种方法兼容性较好,第四种方法采用transform过度,表现得更为平滑

本文的方法跟部分内容来自于原文链接