我应该使用'name'还是'id'来创建HTML锚点?

845

当想要使用 "http://example.com/#foo" 方法引用网页的某个部分时,应该使用什么?

<h1><a name="foo"/>Foo Title</h1>
或者
<h1 id="foo">Foo Title</h1>

它们都可以使用,但是它们是否完全相等,还是有语义上的区别?


2
链接应该是 http://example.com#foo(所以在 # 前面没有 /)。 - Dana
87
实际上,在 URIs 的一份 RFC 中定义的内容中,http://example.com#foohttp://example.com/#foo 是等效的。 - Oliver
1
请查看此答案:https://dev59.com/D3E95IYBdhLWcg3wJKl_#69869066 - Almir Campos
请注意,<h1 id="foo"></h1> 可以在 Javascript 中从 window.foo 引用,这可能不是您所期望的,请参见 https://dev59.com/BXRB5IYBdhLWcg3w3K8J#28568419。 - Flimm
15个回答

666
根据HTML5规范中的5.9.8 导航至片段标识符,需要按照以下处理模型来确定文档中指定部分所在的位置。

对于HTML文档(以及text/html MIME类型),必须遵循以下处理模型以确定文档中指定的部分。

  1. 解析URL,并将fragid设置为URL的<fragment>组件。
  2. 如果fragid为空字符串,则文档的指定部分为文档的顶部。
  3. 如果DOM中存在一个ID完全等于fragid的元素,则树中第一个这样的元素是文档的指定部分;停止算法处理。
  4. 如果DOM中存在一个带有名称属性且其值完全等于fragid的a元素,则树中第一个这样的元素是文档的指定部分;停止算法处理。
  5. 否则,文档中没有指定的部分。
因此,它会查找id="foo",然后会继续查找name="foo"

编辑:正如@hsivonen所指出的,在HTML5中,a元素没有名称属性。然而,上述规则仍适用于其他命名的元素。


81
算法和有效性之间没有隐含的关系。现行起草的HTML5中,<a name>是无效的。 - hsivonen
14
实际上这并不适用于其他“已命名的元素”。就名称属性而言,它只适用于<a name>。然而,作者可能不会使用该属性。它只需要被用户代理在旧的HTML页面中遵守。 - Anne
21
@RafaelSoares <h1 id="foo">Foo Title</h1> 即使在IE6中也可以工作,并且是HTML 4.01规范的一部分。 - Aprillion
4
它不会寻找 name="foo",而是寻找 <a name="foo">。请参见链接 - Daniel Herzog
3
在一个HTML5文档中,如果有一个名为fooname属性和一个id属性(无论它们在页面中的顺序如何),Chrome和Firefox会跳转到id,但是IE(测试版本为11)和Edge会跳转到name - Alvaro Montoro
显示剩余5条评论

196

在任何一种以text/html格式服务的HTML中,不应使用 <h1><a name="foo"/>Foo Title</h1>, 因为XML空元素语法在text/html中不受支持。然而,在HTML4中使用 <h1><a name="foo">Foo Title</a></h1> 是可以的。但是在当前起草的HTML5中无效。

<h1 id="foo">Foo Title</h1> 在HTML4和HTML5中都可以使用。这在Netscape 4中不起作用,但您可能会使用其他数十个在Netscape 4中不起作用的功能。


8
+1,谈论浏览器支持。NS4是唯一不支持url#id => element.id的浏览器吗? - Hashbrown
17
@Hashbrown找不到答案,所以我进行了一些测试。我发现即使是非常老的浏览器,在URL片段和CSS:target选择器的兼容性方面也会像name锚点一样对待id。测试过的浏览器包括:Chrome 6,Firefox 1.5,IE6,Opera 8.02,Safari 3.1.2,Netscape 7.2,Lynx 2.24以及移动浏览器:Android 2.2,Chrome 26,Dolphin 9.3,Firefox 19,IE10,Safari 4和Opera Mini 5.1。 - Stephen M. Harris
1
@smhmic,我找到了一个。Off-By-One浏览器可以识别通过<a name="foo"/>定义的锚点,但无法识别通过<sometag id="foo">定义的锚点。OB1最后一次更新是在8年前。它的作者自夸它“可能是全球最小、最快的支持完整HTML 3.2的Web浏览器”。它声称支持Win95到XP,但在64位Win7上也能正常工作。那么,为什么要使用这样的恐龙呢?当然是为了测试,以确保我的网站不会在真正的古老浏览器中出现太大的问题。此外,我还将OB1放在闪存驱动器上。它很小,自包含且免疫于感染。 - Dave Burton
37
2016年读到这句话就像是…… 网景导航者4? - ADTC
我正在使用Outlook企业邮件应用程序,当我输入“<a id="something">scroll to element</a>”时,它无法正常工作,但是使用“name”而不是“id”可以正常工作,这很遗憾。 - Coty Embry
1
使用 <a name="something" id="something></a>[ELEMENT TO SCROLL TO] 可能是最好的选择,因为它兼容性好,并且不会对要滚动到的元素进行样式设置。 - JustinCB

56

如果你要链接到页面上的某个区域,例如page.html#foo,而“Foo标题”不是一个链接,那么你不应该使用它:

<h1 id="foo">Foo Title</h1>
如果你把标题用<a>包裹起来,你的标题将受到网站中<a>特定CSS的影响。这只是额外的标记,你不需要它。我强烈建议在标题上放置一个id,这不仅格式更好,而且可以让你在Javascript或CSS中针对该对象进行操作。

不仅如此,我一直在解决一个奇怪的错误,在IE中display:none的内容会显示出来。由于缺乏攻击点的想法,我将它交给验证器进行检查,它标记了<a name="foo">条目,所以我改变它们--现在display:none正常工作了。 - Loren Pechtel
这已经足够了,为了效果而不需要锚标签。 - Wallace Sidhrée

30

维基百科大量使用这个功能,如下所示:

<a href="#History">[...]</a>
<span class="mw-headline" id="History">History</span>

维基百科为每个人服务,因此我会感到安全,坚持使用这种形式。

还要记住,您不仅可以使用还可以在

或甚至是表格单元格中使用,然后您就可以访问元素上的:target伪类。只需注意不要更改宽度(例如加粗文本),因为这会使内容移动,影响用户体验。

锚点名称 - 我建议避免使用:

  • "名称和ID在相同的命名空间中..." - 具有相同命名空间的两个属性是非常混乱的。让我们说废弃已经足够了。
  • "没有href属性的锚元素" - 再次,拥有属性(超链接还是其他)定义了元素的性质?!简直疯狂。常识告诉我们应该完全避免这种情况。
  • 如果您未使用伪类样式化锚点,则样式将适用于每个锚点。在CSS3中,您可以使用属性选择器(或相同的伪类样式)解决此问题,但仍然是一个变通方法。这通常不会成为问题,因为您会为每个伪类选择颜色,而默认存在下划线只需要将其删除即可,这将使其与其他文本相同。但是,如果您决定使链接加粗,则会出现问题。
  • Netscape 4可能不支持ID特性,但是一个未知的属性不会造成任何麻烦。这就是所谓的兼容性。

1
建议编辑4个中的第3个项目:如果您曾经使用a {color:red}样式,它将同时应用于<a href>链接和<a name>片段。您可以通过伪类a:link {color:red]}或属性选择器a:not([href]) {color:red;}来解决这个问题。 - Bob Stein
你说得对,但对我来说,第三点正是这个意思。可能是我的英语不太好... - Zoltán Morvai
最后,我明白了你的意思: “如果你没有使用伪类来为锚点设置样式,那么这个样式会应用到每一个锚点。” 有歧义:你可能认为是“每一个伪类”,对吗?但是我想表达的是“每一种”使用锚点的情况,也就是指定了名称和href。已经澄清了。 :) 在你的评论之后不需要编辑,但如果你坚持,我可以编辑。但是通常颜色不容易出现这种情况,因为你通常希望它们保持不同,但是字体粗细仍然是相同的情况... - Zoltán Morvai
很喜欢阅读你的评论@ZoltánMorvai。"double crazy"和"netscape 4"双倍棒。 - Randy L
1
两个具有相同命名空间的属性是不可思议的 - 其实并不是。在进行用户生成内容时,能够将某些内容指定为片段链接 <a name="heading1"></a> ... document.html#heading1 而无需设置 ID 是非常有用的,因为 ID 可能会与页面上的另一个 ID 冲突。HTML5 没有放置 name 属性真是遗憾。 - Jez
显示剩余2条评论

15

提醒JavaScript用户:在window所有ID都将成为全局变量

<h1 id="foo">Foo Title</h1>

刚刚创建了JS全局变量:

window.foo

window.foo 的值将会是 h1 元素的 HTMLElement

除非你能保证在 id 属性中使用的所有值都是安全的,否则你可能更喜欢使用 name

<h1 name="foo">Foo Title</h1>

12
好消息是,您无法覆盖在window中定义的函数。例如,<div id="open"></div>不会覆盖函数window.open - Flimm
1
为什么您应该保证在id属性中使用的所有值都是安全的? - Alex78191
1
关于这个陷阱的文章:https://css-tricks.com/named-element-ids-can-be-referenced-as-javascript-globals/ - Flimm
谢谢@Flimm - 这是一个好的参考,我已经在答案中包含了它作为一个链接。 - mikemaccana

15
<h1 id="foo">Foo Title</h1>

应该使用标记, 除非您需要一个链接,否则不要使用锚点。


与Tim Knight半年前发布的答案完全相同。-1 - Luc

9

ID方法在旧版浏览器上无法使用,锚点名称方法将在新版HTML版本中被弃用...我会选择使用id。


3
你有这些主张的来源吗?别误会,我只是普遍感兴趣。 - Henrik Paul
12
这并没有解释“不适用于旧版浏览器”的信息。除了Netscape 4,还有哪些浏览器属于旧版浏览器? - Robert Siemer
3
我已经尝试在一个 div 上使用 id,即使在 IE 7 中也可以工作。虽然我无法在 IE 6 中进行测试,但是现在谁还在使用 IE 6 呢... - Gilly
在某些情况下(取决于HASLAYOUT),@deathApril会出现错误。 - Knu
@RobertSiemer 这个几乎普遍适用 -- 请看我在 这个答案 下的评论。 - Stephen M. Harris
@Knu 在 WinXP SP2 上的 IE6 中,似乎在具有和不具有 hasLayout 的情况下都可以正常工作(http://wiki.jalakai.co.uk/css-demos/ie-keyboard-navigation.php)。 - Stephen M. Harris

9
没有语义上的区别;标准的趋势是使用id而不是name。然而,在某些情况下,存在可能使人们更喜欢使用name的差异。HTML 4.01规范提供了以下提示
使用id还是name?作者在决定为锚点名称使用id还是name时应考虑以下问题:
  • id属性可以充当不仅仅是锚点名称(例如样式表选择器、处理标识符等)。
  • 一些较旧的用户代理不支持使用id属性创建的锚点。
  • name属性允许使用实体创建更丰富的锚点名称。

14
要明确的是,当他们说“老旧用户代理”时,他们指的是真正的老旧用户代理。我不会担心这个问题。 - Eli
1
HTML5也允许使用“丰富”的ID。有没有市场份额大于0.1%的版本号无法处理ID锚定片段的浏览器?或者恐龙Netscape 4.7实际上是最广泛使用的浏览器吗? - Robert Siemer
7
顺便说一下,我无法在iOS 5的Safari中使用"id"锚点,所以这不仅是在'09年已经非常陈旧的浏览器存在的问题。我不得不添加“name”才能使我的网站在iPad上正常工作。这个问题现在可能已经被修复了,但我没有任何iOS 6设备来进行检查。 - Daniel Saner
@DanielSaner 真的吗?所以 http://en.wikipedia.org/wiki/IPad#Applications 在你的iPad上无法使用? - Aprillion
我刚刚再次检查了一下,在我的iOS 5 iPad 2上使用Safari无法正常工作。您的链接总是将我带到文章顶部。但在Opera上可以正常工作。我还在手机上尝试了一下:id锚点在Gingerbread 2.3.7附带的标准浏览器上不起作用,但在最新版本的Opera和Firefox中可以。 - Daniel Saner
1
@DanielSaner 我使用模拟器测试了Mobile Safari 5.02和5.1以及Android浏览器2.2和2.3,id锚点似乎在所有设备上都能正常工作。如果这个简单的例子在你的移动设备上无法正常工作,我建议检查设备的可访问性设置。(@deathApril Wikipedia移动站点使用的Javascript会有效地忽略URL片段。) - Stephen M. Harris

5
在HTML5中,id=""属性定义了一个元素的唯一标识符,也是片段链接的锚点。在先前的HTML标准中,<a>元素的name=""属性定义了片段链接的锚点。我建议使用以下格式:
<a name="foo" id="foo"></a><h1>Foo Title</h1>
因为对于id=""属性的支持有些不稳定(尽管所有主要浏览器的最新版本都支持它,但不支持的版本不超过几年[如果没有充分的理由最好不要破坏它])。这种格式兼容性好,并且不会为链接元素中的内容设置样式,因为关闭的</a>仍然在元素外部,但在所有当前标准中仍然有效。

请确保<a>元素的name=""id=""属性相同。


2
并非所有使用HTML的都是浏览器。我正在使用一个Java库,它使用HTML在窗口中显示信息。这是唯一有效的方法。需要使用锚标签上的“name”属性;在“hN”或“span”上放置属性无效。 - Mars

3

我有一个网页,由许多垂直堆叠的 div 容器组成,这些容器在格式上完全相同,只是序列号不同。我想隐藏每个 div 顶部的名称锚点,因此最经济的解决方案是将锚点作为 id 包含在开放的 div 标签中,即

<div id="[serial number]" class="topic_wrapper">

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接