6 个创意 CSS 链接悬停效果

Avatar of Harshil Patel
Harshil Patel

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

创建 CSS 链接悬停效果可以为原本单调的网页添加一些趣味。如果您曾经在尝试制作炫酷的悬停效果时遇到困难,那么我这里有六种 CSS 效果供您在下一个项目中使用。

A default link hover effect above a styled link hover effect with a rainbow underline.

让我们开始吧!

我知道我们正在讨论 :hover,但有时(但也许并非总是)将 :focus 也包含进来是一个好主意,因为并非所有交互都直接来自鼠标,而是可能是点击或按键操作。

此效果会将一个盒阴影应用于内联链接,并在过程中更改链接文本的颜色。我们首先在链接周围添加填充,然后添加相同值的负边距以防止填充破坏文本流。

我们将使用 box-shadow 而不是 background 属性,因为它允许我们进行过渡。

a {
  box-shadow: inset 0 0 0 0 #54b3d6;
  color: #54b3d6;
  margin: 0 -.25rem;
  padding: 0 .25rem;
  transition: color .3s ease-in-out, box-shadow .3s ease-in-out;
}
a:hover {
  box-shadow: inset 100px 0 0 0 #54b3d6;
  color: white;
}

这是一个有趣的效果,我们可以在悬停时将链接的文本与其他一些文本交换。将鼠标悬停在文本上,链接文本会滑出,而新文本会滑入。

展示比解释更容易理解。

此链接悬停效果中包含相当多的技巧。但神奇之处在于使用 数据属性 来定义滑入的文本,并使用链接的 ::after 伪元素的 content 属性来调用它。

首先,HTML 标记

<p>Hover <a href="#" data-replace="get a link"><span>get a link</span></a></p>

有很多内联标记,但您看到的是一个包含链接和跨度的段落标签。

让我们为链接添加一些基本样式。我们需要为其提供相对定位以将伪元素(将被绝对定位)固定到位,确保其显示为 inline-block 以获得盒元素样式的功能,并隐藏伪元素可能导致的任何溢出。

a {
  overflow: hidden;
  position: relative;
  display: inline-block;
}

::before::after 伪元素应该有一些绝对定位,以便它们与实际链接堆叠在一起。我们将确保它们设置为链接的完整宽度,在左侧位置具有零偏移量,从而为一些滑动操作做好准备。

a::before,
a::after {
 content: '';
  position: absolute;
  width: 100%;
  left: 0;
}

::after 伪元素从 HTML 标记中链接的数据属性获取内容

a::after {
  content: attr(data-replace);
}

现在我们可以使用 transform: translate3d()::after 伪元素元素向右移动 200%。我们在 :hover 上将其移回原位。顺便说一句,我们可以在 top 方向上为其提供零偏移量。这在稍后我们像文本下划线一样使用 ::before 伪元素时会很重要。

a::after {
  content: attr(data-replace);
  top: 0;
  transform-origin: 100% 50%;
  transform: translate3d(200%, 0, 0);
}

a:hover::after,
a:focus::after {
  transform: translate3d(0, 0, 0);
}

我们还将 transform: scale() ::before 伪元素,使其默认隐藏,然后在 :hover 上将其缩放回原大小。我们将使其变小,例如高度为 2px,并将其固定在 bottom 上,使其看起来像是与 ::after 交换的文本下划线。

a::before {
  background-color: #54b3d6;
  height: 2px;
  bottom: 0;
  transform-origin: 100% 50%;
  transform: scaleX(0);
}

a:hover::before,
a:focus::before {
  transform-origin: 0% 50%;
  transform: scaleX(1);
}

其余都是偏好问题!我们在 transform 效果上添加一个 transition,一些颜色等等以获得完整的效果。这些值完全取决于您。

查看完整 CSS
a {
  overflow: hidden;
  position: relative;
  display: inline-block;
}

a::before,
a::after {
 content: '';
  position: absolute;
  width: 100%;
  left: 0;
}
a::before {
  background-color: #54b3d6;
  height: 2px;
  bottom: 0;
  transform-origin: 100% 50%;
  transform: scaleX(0);
  transition: transform .3s cubic-bezier(0.76, 0, 0.24, 1);
}
a::after {
  content: attr(data-replace);
  height: 100%;
  top: 0;
  transform-origin: 100% 50%;
  transform: translate3d(200%, 0, 0);
  transition: transform .3s cubic-bezier(0.76, 0, 0.24, 1);
  color: #54b3d6;
}

a:hover::before {
  transform-origin: 0% 50%;
  transform: scaleX(1);
}
a:hover::after {
  transform: translate3d(0, 0, 0);
}

a span {
  display: inline-block;
  transition: transform .3s cubic-bezier(0.76, 0, 0.24, 1);
}

a:hover span {
  transform: translate3d(-200%, 0, 0);
}

我在很多地方都见过这种非常流行的效果。其理念是使用链接的 ::before 伪元素作为一条粗下划线,使其略微位于链接的实际文本后面。然后,在悬停时,伪元素会扩展以覆盖整个内容。

好的,链接的一些基本样式。我们不需要 text-decoration,因为 ::before 将充当下划线,然后是一些相对定位以在为其提供绝对定位时将 ::before 固定到位。

a {
  text-decoration: none;
  position: relative;
}

现在让我们设置 ::before,使其高度约为 8px,使其看起来像一条粗下划线。我们还将为其提供绝对定位,以便我们可以控制使其成为实际链接的完整宽度,同时对其进行偏移,使其位于 left 处,并且仅略微偏离 bottom,使其看起来像在微妙地突出显示链接。不妨也为其设置 z-index: -1,这样我们就可以确保它位于链接的后面。

a::before {
  content: '';
  background-color: hsla(196, 61%, 58%, .75);
  position: absolute;
  left: 0;
  bottom: 3px;
  width: 100%;
  height: 8px;
  z-index: -1;
}

很好,很好。让我们使 ::before 在链接悬停时看起来像是在增长。我们只需要将高度从 3px 更改为 100%。请注意,我也将 bottom 偏移量恢复为零,以便背景在增长时覆盖更多空间。

a:hover::before {
  bottom: 0;
  height: 100%;
}

现在对这些更改进行轻微的过渡

a::before {
  content: '';
  background-color: hsla(196, 61%, 58%, .75);
  position: absolute;
  left: 0;
  bottom: 3px;
  width: 100%;
  height: 8px;
  z-index: -1;
  transition: all .3s ease-in-out;
}
查看完整 CSS
a {
  text-decoration: none;
  color: #18272F;
  font-weight: 700;
  position: relative;
}

a::before {
  content: '';
  background-color: hsla(196, 61%, 58%, .75);
  position: absolute;
  left: 0;
  bottom: 3px;
  width: 100%;
  height: 8px;
  z-index: -1;
  transition: all .3s ease-in-out;
}

a:hover::before {
  bottom: 0;
  height: 100%;
}

我个人喜欢在导航中的链接使用此效果。链接以一种颜色开始,没有下划线。然后,在悬停时,一种新颜色会从右侧滑入,而下划线则会从左侧滑入。

很整洁,对吧?其中有很多运动,因此您可能需要考虑可访问性影响,并将所有内容包装在 prefers-reduced-motion 查询中,以便为那些对运动敏感的人替换为更微妙的内容。

以下是其工作原理。我们为链接提供了一个线性背景渐变,在中途两个颜色之间有一个硬停止。

a {
  background-image: linear-gradient(
    to right,
    #54b3d6,
    #54b3d6 50%,
    #000 50%
  );
}

我们将背景设置为链接宽度的两倍,或 200%,并将其完全定位到左侧。这样,就好像只有一个渐变的两种颜色显示出来。

a {
  background-image: linear-gradient(
    to right,
    #54b3d6,
    #54b3d6 50%,
    #000 50%
  );
  background-size: 200% 100%;
  background-position: -100%;
}

当我们使用几个非标准的 -webkit- 前缀属性时,就会发生神奇的事情。一个会去除文本中的颜色使其透明。另一个会将背景渐变剪切到文本,使其看起来文本实际上是背景的颜色。

a {
  background-image: linear-gradient(
    to right,
    #54b3d6,
    #54b3d6 50%,
    #000 50%
  );
  background-size: 200% 100%;
  background-position: -100%;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

跟上了吗?现在让我们通过使用 ::before 来创建链接的伪下划线。我们将为其提供与链接隐藏部分的背景渐变相同的颜色,并将其定位在实际链接下方,使其看起来像一个合适的 text-decoration: underline

a:before {
  content: '';
  background: #54b3d6;
  display: block;
  position: absolute;
  bottom: -3px;
  left: 0;
  width: 0;
  height: 3px;
}

在悬停时,我们将 ::before 滑动到位,从左侧进入

a:hover {
 background-position: 0;
}

现在,这有点棘手。在悬停时,我们将链接的 ::before 伪元素设置为链接宽度的 100%。如果我们将其直接应用于链接的悬停,我们将使链接本身变为全宽,这会将其移动到屏幕周围。糟糕!

a:hover::before {
  width: 100%;
}

添加一点过渡以使事物平滑过渡

a {
  background-image: linear-gradient(
    to right,
    #54b3d6,
    #54b3d6 50%,
    #000 50%
  );
  background-size: 200% 100%;
  background-position: -100%;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  transition: all 0.3s ease-in-out;
}
查看完整 CSS
a {
  background-image: linear-gradient(
    to right,
    #54b3d6,
    #54b3d6 50%,
    #000 50%
  );
  background-size: 200% 100%;
  background-position: -100%;
  display: inline-block;
  padding: 5px 0;
  position: relative;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  transition: all 0.3s ease-in-out;
}

a:before {
  content: '';
  background: #54b3d6;
  display: block;
  position: absolute;
  bottom: -3px;
  left: 0;
  width: 0;
  height: 3px;
  transition: all 0.3s ease-in-out;
}

a:hover {
 background-position: 0;
}

a:hover::before {
  width:100%;
}

我们无法使用 text-decoration-color: rainbow,但我们可以通过将一些 background 魔法与线性渐变混合来伪造它。

首先,我们删除链接的 text-decoration

a {
  text-decoration: none;
}

现在是这些渐变。我们在同一 background 属性上链接了两个线性渐变。一个渐变是悬停前的初始颜色。第二个是在悬停时的彩虹。

a {
  background:
    linear-gradient(
      to right,
      rgba(100, 200, 200, 1),
      rgba(100, 200, 200, 1)
    ),
    linear-gradient(
      to right,
      rgba(255, 0, 0, 1),
      rgba(255, 0, 180, 1),
      rgba(0, 100, 200, 1)
  );
}

让我们使背景大小仅为 3px 高,使其看起来像,你知道的,下划线。我们可以在 background-size 属性上同时调整两个渐变的大小,以便初始渐变为全宽且 3px 高,而彩虹为零宽度。

a {
  background:
    linear-gradient(
      to right,
      rgba(100, 200, 200, 1),
      rgba(100, 200, 200, 1)
    ),
    linear-gradient(
      to right,
      rgba(255, 0, 0, 1),
      rgba(255, 0, 180, 1),
      rgba(0, 100, 200, 1)
  );
  background-size: 100% 3px, 0 3px;
}

现在我们可以定位背景渐变(在 background-position 属性上同时定位),以便第一个渐变完全可见,而彩虹则被推到视野之外。哦,在我们处理它的同时,让我们确保背景不重复。

a {
  background:
    linear-gradient(
      to right,
      rgba(100, 200, 200, 1),
      rgba(100, 200, 200, 1)
    ),
    linear-gradient(
      to right,
      rgba(255, 0, 0, 1),
      rgba(255, 0, 180, 1),
      rgba(0, 100, 200, 1)
  );
  background-size: 100% 3px, 0 3px;
  background-position: 100% 100%, 0 100%;
  background-repeat: no-repeat;
}

让我们在悬停时更新 background-size,以便渐变交换值

a:hover {
  background-size: 0 3px, 100% 3px;
}

最后,在悬停发生时进行轻微的过渡

a {
  background:
    linear-gradient(
      to right,
      rgba(100, 200, 200, 1),
      rgba(100, 200, 200, 1)
    ),
    linear-gradient(
      to right,
      rgba(255, 0, 0, 1),
      rgba(255, 0, 180, 1),
      rgba(0, 100, 200, 1)
  );
  background-size: 100% 3px, 0 3px;
  background-position: 100% 100%, 0 100%;
  background-repeat: no-repeat;
  transition: background-size 400ms;
}

瞧!

Geoff Graham 最近在分析 Adam Argyle 的流畅悬停效果时,实际上也介绍了同样的效果。在他的演示中,链接后面会从左侧进入一个背景颜色,然后在鼠标移出时从右侧退出。

我的版本简化了背景,使其更像是一个下划线。

a {
  position: relative;
}

a::before {
    content: '';
    position: absolute;
    width: 100%;
    height: 4px;
    border-radius: 4px;
    background-color: #18272F;
    bottom: 0;
    left: 0;
    transform-origin: right;
    transform: scaleX(0);
    transition: transform .3s ease-in-out;
  }

a:hover::before {
  transform-origin: left;
  transform: scaleX(1);
}

这不是实现此效果的唯一方法!Justin Wong 使用 background 提供了另一种方法

Geoff 还提供了一个CSS 链接悬停效果的汇总,从简洁到荒谬不一。值得一看!对于链接和按钮样式的实用方法,请查看Philip Zastrow 在 DigitalOcean 上的初学者教程

尽情链接吧!

使用 CSS 创建自己的内联链接悬停效果有很多选择。你甚至可以玩转这些效果并创造出新的东西。希望你喜欢这篇文章。继续尝试吧!