Menu

CSS hover 悬停效果::hover、:active 与链接颜色

:hover 伪类在指针停在元素上时为它设置样式。本文讲解按钮和卡片的悬停效果、平滑过渡、按正确顺序使用 :link、:visited、:hover 和 :active 设置链接颜色,以及触摸屏上的悬停。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

:hover 的工作原理

:hover 是一个伪类,当鼠标指针停在元素上时匹配该元素。把它加到任意选择器后面,再写出悬停状态的样式:

只有 :hover 规则里的声明会改变,其余样式都沿用 .btn 的。指针移开后,元素恢复到正常样式。

用 transition 实现平滑的悬停效果

悬停时的变化是瞬间完成的,除非你把 transition 加在普通规则上(而不是 :hover 规则上),这样移入和移出都会有动画:

transform 和 opacity 是做动画开销最小的属性;它们不会挤动周围的元素。给 width、height 或 margin 做动画,会让页面在每一帧都重新排版。时长、延迟和缓动曲线见 CSS transition 一页。

链接颜色::link、:visited、:hover、:active

链接有四个经典状态,外加键盘焦点,而且规则的顺序很重要:

伪类何时生效
:link链接还没有被访问过
:visited该 URL 在浏览器历史记录中
:hover指针停在链接上
:active链接正在被按下
:focus-visible链接获得了键盘焦点

这些伪类的优先级都相同,所以两条规则同时匹配时,后写的胜出。一个被悬停的已访问链接会同时匹配 :visited 和 :hover;如果 :visited 写在最后,悬停颜色就永远不会显示。安全的顺序是 Link、Visited、Hover、Active(LVHA):

为了防止网页读取你的浏览历史,浏览器限制了 :visited 能修改的内容。只有与颜色相关的属性(color、background-color、border-color、outline-color 等少数几个)会生效,而脚本读到的始终是未访问时的值。

:active:按下状态

:active 在元素被按下时匹配。加一点位移,就能让按钮有真实的按压感:

悬停父元素来设置子元素样式

悬停状态属于指针下方的元素及其所有祖先元素。所以 .card:hover .title 会在卡片的任何部分被悬停时为标题设置样式,同样的思路也能用来显示隐藏的元素:

:focus-within 这一行很重要:没有它,用 Tab 键移到 Delete 按钮的键盘用户就会按下一个看不见的按钮。每个靠悬停显示的元素都要配一条焦点规则。

触摸屏上的悬停

手机和平板没有可以停在元素上的指针。大多数移动浏览器会在第一次点击时应用 :hover,并一直保持到你点击别处,所以悬停样式可能看起来“卡住”了。两条规则可以控制住这个问题:

  • 永远不要让 :hover 成为访问某些内容的唯一途径。悬停时打开的菜单,点击时也必须能打开。
  • 把纯装饰性的悬停效果包进一个检测真实悬停设备的媒体查询里:
@media (hover: hover) {
  .card:hover { transform: translateY(-4px); }
}

常见错误

  • 冒号前面多了一个空格。 .btn :hover 的意思是“.btn 里面一个被悬停的元素”。应写成 .btn:hover。
  • 只在 :hover 规则上写 transition。 这样移入时有动画,移出时却会直接跳回去。把它写在普通规则上。
  • 链接伪类顺序错误。 保持 :link、:visited、:hover、:active 的顺序。
  • 有悬停样式却没有焦点样式。 键盘用户永远不会触发 :hover;也要给可交互元素设置 :focus-visible 样式。
  • 悬停的元素被别的元素盖住了。 一个看不见的遮罩层(通常是绝对定位的伪元素)可能会截获指针。给遮罩层加上 pointer-events: none 即可解决。

常见问题

CSS 中怎么添加悬停效果?

在选择器后面加上 :hover 写一条规则:.btn:hover { background: #1d4ed8; }。指针停在元素上时,这些声明就会生效。在普通规则里加上 transition: background 0.2s;,变化就会带有动画。

:hover 和 :active 有什么区别?

:hover 在指针停在元素上时生效。:active 在元素被按下时生效,从按下鼠标键到松开为止。一个被按下的按钮通常同时处于悬停和激活状态。

链接伪类应该按什么顺序写?

:link、:visited、:hover、:active(记作 LVHA,英文口诀是 "LoVe HAte")。它们的优先级相同,所以后写的规则胜出;换成其他顺序,visited 或 hover 的样式可能会把 hover 或 active 的样式盖住。

CSS 中怎么修改链接颜色?

给 a 元素设置样式:a { color: #2563eb; },再用 a:visited { color: #7c3aed; } 和 a:hover { color: #1d4ed8; } 设置其他状态。在 a 上设置 color 会同时作用于未访问和已访问的链接。

hover 在手机上有效吗?

触摸屏没有可以停在元素上的指针。大多数移动浏览器会在点击时应用 :hover,并一直保持到你点击别处,这可能让悬停样式“卡住”。把仅用于悬停的效果包进 @media (hover: hover),并且绝不要把关键内容藏在悬停之后。

Coddy 编程语言插图

和 Coddy 一起学编程

开始