设置超链接锚点目标样式

2023-03-25 ⏳2.8分钟(1.1千字)

我一直使用 Markdown 创作。随着创作的深入,使用脚注的情况越来越多。Pandoc 会自动处理脚注的编号,并将所有脚注锚链接追加到文章末尾。如果脚注非常多,点击脚注编号会跳转到文章结尾。但这里有很多脚注,读者可能分不清刚才点的是哪一个数字😂虽然可以再点一下脚注末尾的↩︎跳回原文,但总归是不方便。如果文章内容比较短,或者同一行中有多个脚注,读者更对不上号。今天就通过 CSS 解决这个问题,进一步优化阅读体验。

在开始之前先普及一下锚点的概念。

我们通常见到的超链接都不带锚点,比如https://taoshu.in/。点击这样的链接,浏览器只会打开对应的页面,并停留页面开始的位置。如果我们想打开后跳转到文章中间的某个位置,就需要设置锚点。

这里的锚点说白了就是设置了id属性的元素。不论是<div>还是<h1>,只要设置了唯一的id,就能当锚点。比如在某子标题上设置锚点<h2 id="foo">Foo</h2>,这样在页面链接加上#foo后缀,点击就可以自动跳转到 Foo 标题的位置。

以上是锚点的概念。我们的目标是希望浏览器跳转之后能临时修改锚点元素的样式,比如背景,这样读者就能明确哪部分是锚点。如果你分享过 StackOverflow 的回答或者 GitHub Issue 中的讨论就有体会,因为打开链接之后,浏览器不但会自动跳转到对应的回复或者回复,还会闪一下目标的背景。这处设计非常贴心。

实现这种效果的核心思想是利用 CSS 中的:target伪类修改链接锚点样式。

*:target {
    background-color: yellow;
}

如果浏览器通过锚点链接跳转到某个元素,那么该元素就能被:target伪类匹配到。上面的 CSS 指定浏览器跳转到某锚点元素时将其背景修改为黄色。这样读者就能明确哪部分是锚点了。

但是上面的方案有一个小问题,黄色背景无法自动消失。一般来说这不是什么问题。但一直显示有点傻,所以得想办法自动取消这个背景色。早期只能使用 js 动态修改背景。但现在浏览器都给元素设置动画1。我们可以利用动画平滑地去掉背景色。

*:target {
    background-color: yellow;
    animation: restore-color 3s forwards;
}
@keyframes restore-color {
    0% {
        background-color: yellow;
    }
    100% {
        background-color: inherit;
    }
}

这里添加了animation属性,指定动画关键帧。关键帧由@keyframes指定,通过百分比确定动画位置。我这里指定开始时背景为黄色,动画结束时背景为默认颜色(也就是从父元素继承)。浏览器在渲染动画时会自动将背景从黄色过渡到默认色。

animation的第二个参数是动画时长,可以根据需要调整。我试验发现 3s 比较合适。

最后的forwards表示 fill mode2。简单来说就是动画结束后要不要修改被作用元素的样式。在本文中,我们通过动画将背景色由黄色改为默认色。动画结束之后,我们希望锚点的颜色保持为默认色,所以我们需要将这个属性设置为forwards。有时候需要在动画结束后将样式恢复到动画开始的样子,这时候就得设成backwards。其他选项请参考 MDN 文档。

到这里我们这实现动态修改锚点背景色功能了。大家可以点击本文中的的脚注链接体验效果。


  1. https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations↩︎

  2. https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode↩︎