这里有一个两秒钟的回顾。 如果一个元素有 ID,您可以使用浏览器的自然行为链接到它。 标题有 ID 非常棒,因为直接链接到特定内容部分通常很有用。
<h3 id="step-2">Step 2</a>
如果我愿意,我可以直接链接到此标题,无论是通过 URL,例如 https://my-website.com/#step-2
,还是通过页面内链接,例如
<a href="#step-2">Jump to Step 2</a>
因此,所有标题都有唯一的 ID 是理想的。
但我发现手动为所有标题添加 ID 太费事了。 很多年来,我一直使用这个网站上的 jQuery 来做到这一点(别告我)。
// Adjust this for targetting the headers important to have IDs
const $headers = $(".article-content > h3");
$headers.each((i, el) => {
const $el = $(el);
// Probably a flexbox layout style page
if ($el.has("a").length != 0) {
return;
}
let idToLink = "";
if ($el.attr("id") === undefined) {
// give it ID
idToLink = "article-header-id-" + i;
$el.attr("id", idToLink);
} else {
// already has ID
idToLink = $el.attr("id");
}
const $headerLink = $("<a />", {
html: "#",
class: "article-headline-link",
href: "#" + idToLink
});
$el.addClass("has-header-link").prepend($headerLink);
});
该脚本除了添加 ID(如果它还没有 ID)之外,还在标题内添加了一个 #
链接,该链接指向该标题。 这样做的目的是为了证明标题确实有 ID,并且方便了右键单击复制链接等操作。 这里有一个演示,如果您想查看。
问题! 突然间,它停止工作了。
不是脚本本身,脚本工作正常。 但是,允许浏览器在页面加载时跳转到标题的原生浏览器行为已损坏。 我想这可能是一个竞争条件。
- HTML 到达
- 页面开始渲染
- 浏览器正在寻找 URL 中的 ID 以滚动到该位置
- 它没有找到它……
- 哦,等等,它就在那里!
- 滚动到那里。
哦,等等,它就在那里! 这一步来自脚本执行并把 ID 添加到标题上。 我真的不怪浏览器没有跳转到动态插入的链接。 我很惊讶它能工作这么长时间。
在 HTML 到达之前就让标题上有 ID 要好得多。 这个网站是 WordPress,我知道我可以使用某种内容过滤器来做到这一点。 事实证明,我甚至不需要费心,因为当然,有一个插件可以做到这一点:Karolína Vyskočilová 的 Add Anchor Links。 对我来说效果很好。 它的技术是在锚点链接本身添加 ID,这也是完全可以的。 我想这是另一种避免弄乱现有 ID 的方法。

如果我没有 WordPress,我会找到其他方法来在服务器端处理 HTML,以确保以某种方式发生某种标题链接。 总是会有办法的。 事实上,如果在构建过程中或在服务器端过滤器中这样做太奇怪、太麻烦或其他什么,我会考虑在服务工作者中完成它。 我一直玩得很好玩 Cloudflare 的 HTMLRewriter,它完全能够做到这一点。
值得注意的是 Chrome 默认启用的新滚动到文本片段:https://caniuse.cn/#feat=url-scroll-to-text-fragment
是的,我最近在从 Google 到页面的点击中注意到这一点。 我想知道它是否会传播到所有浏览器? 我不知道,这不像必须是 Web 标准的东西。 到目前为止,我发现它并不十分有用,他们在搜索结果中实现的方式。 但是我喜欢它存在,因为它是一种在页面上可用内容之外创建定制链接的方法。
您可能会在文档就绪时刷新位置哈希来稍微改进脚本?
它有效吗? 我认为你需要在里面添加一个 setTimeout 或其他东西,否则 JavaScript 引擎可能会优化掉第一个哈希设置。
或者,在文档就绪时使用
window.scrollTop
等滚动到位置,前提是 URL 哈希存在并且窗口页面 Y 偏移量为 0。是的! 我和一个人聊天,他告诉我他们就是这样做的(这也允许平滑滚动)。 但是我有点希望保留浏览器的默认行为。 编写更少的代码而不是更多,你知道吗? 但是这是一个完全可行的选择。 我也很好奇标题上的链接是否会对 SEO 或搜索页面体验有益,但似乎没有。
您过去会像这样为标题分配 ID
#article-header-id-${index}
现在使用 WordPress 插件,ID 是根据标题中的文本生成的,例如
#the-easy-way
。这意味着所有指向文章标题的现有链接现在都已损坏。
哦,是的,这是真的。 我应该提到这一点。 URL 本身仍然链接到正确的页面,因此我发现这是一个可以接受的折衷方案,链接实际上没有损坏,并且这个新系统将更容易维护,并且依赖于浏览器的默认行为。
在静态页面上使用运行时 JavaScript 添加 ID 不是一个合适的解决方案,因为这些 ID 需要在 HTML 中已经存在。 这就是为什么上面的解决方案是黑客行为,并且会导致各种浏览器出现问题,并且还会毫无理由地浪费 CPU 资源。
最好的方法是手动添加 ID,但既然您不想要这样做,那么第二好的解决方案是自动修改/烹饪 HTML,例如使用非常小的 Python 或 node.js 脚本,您可以选择任何语言。
该脚本的工作原理如下 3)保存修改后的 HTML,就是这样。
1)使用正则表达式收集页面中的所有 ID,并将它们存储在字典中。
2)使用正则表达式或简单的
是的。 这就是我在文章中谈论的哈哈。 如果你想分享 Python 脚本的想法,这对未来的用户会有所帮助。
我喜欢这个。 我更喜欢的是,如果它只引用 HEADINGS 而不是 HEADERS,因为它们是两件不同的事情,对吧? 每当我看到
<head>
、<header>
或标题(<h1>
等)时,我都会停下来思考一下。 #namingstuffishard :)我看到我们错过了一个实例,但它在其余部分中确实都是“headings”。 谢谢你指出来! :)
Marc Jenkins:
我也为此使用 scrollTop,我认为添加动画确实为用户提供了一些背景。 “哦,它正在把我跳转到我想要的内容,”也许吧。 巧合的是,我最近开发了一个 Drupal 模块,专门用于此目的,它通过在页面中查找所有匹配的元素并对重复的元素进行编号来处理唯一 ID 的生成。 https://www.drupal.org/project/auto_anchors