在锚标签内创建另一个锚标签

93

在我的随机测试中,我发现了一个行为,即我将一个锚点标签放在另一个锚点标签内部。我制作了jsfiddle示例。

<a class="groupPopper">
     <a class="name"> content</a>
</a>

但是在开发者工具中,它看起来不同:

enter image description here

我认为我们不能把一个锚标签放在另一个锚标签里,因为点击内部锚标签将会将点击事件冒泡到父级锚标签中,这是不允许的。

我的假设正确吗?

12个回答

135

正如@j08691所描述的,HTML语法不允许嵌套的a元素。 HTML规范没有说明原因,只是强调了这个规则。

从实际角度来看,浏览器在它们的解析规则中有效地执行此限制,因此与许多其他问题不同,违反规范就行不通。解析器有效地将打开的a元素内部的 <a>开始标记视为隐含终止打开元素,然后才开始一个新的元素。

因此,如果您编写<a href=foo>foo <a href=bar>bar</a> zap</a>,您将无法获得嵌套的元素。浏览器会将其解析为<a href=foo>foo</a> <a href=bar>bar</a> zap,即两个连续的链接,后面跟一些纯文本。

嵌套的a元素本质上并没有任何不合逻辑:可以实现为单击“foo”或“zap”激活外部链接,单击“bar”激活内部链接。但我认为没有理由使用这样的结构,HTML的设计者可能也没有看到,因此他们决定禁止它,从而简化了事情。

(如果您真的想模拟嵌套链接,则可以使用普通链接作为外部链接,使用带有适当事件处理程序的span元素作为内部“链接”。或者,您可以复制链接:<a href=foo>foo</a> <a href=bar>bar</a> <a href=foo>zap</a>。)


1
似乎目前至少有一些最新的浏览器可以允许这样做。我有一个结构 a > div > a,Chrome 和 Firefox 都能够按照我编写的方式存在,并且它们在解析过程中不会将其重组(我还未测试 Edge)。 - trusktr
说这不可能并没有什么帮助,抱歉。 - PJ Brunet
1
@trusktr 我也进行了测试,甚至像 a > div > a 这样的结构也会被转换成 <a></a><div><a></a></div>,所以浏览器确实不允许嵌套链接(即使中间有个 div)。 - G. Egli
@G.Egli 哦,你说得对。我可能疏忽了,或者是用纯JavaScript做的。解析器不允许这样做(真遗憾,在我看来它不应该将你没有编写的HTML转换成其他东西)。以下是如何使用JavaScript实现它的方法:https://jsfiddle.net/0ozfcn1d/ - trusktr

26

这可能是什么原因?我只是想要更多的解释。 - Anoop
1
我不知道背后的确切原因,但至少从语义上讲,嵌套链接是没有意义的。更不用说将具有href值的实际链接嵌套起来似乎完全没有意义。 - j08691
这也是我的假设。只是想更加确定一下。因为我可以在A标签内放置其他标签(例如span)。 - Anoop
8
完全没有意义。假设您有一个作为大型块级元素样式的外部锚点。现在在该大块的任意位置上,您想要一个单独的跨度级别的锚点,将您带到其他地方,例如#comments快捷方式。除非使用嵌套锚点,否则无法实现此操作。 - DMCoding
@DanielJames - 这完全没有任何意义。 - j08691
在我的情况下,我想要有两个嵌套的a href。 <a href="https://google.com"> <div> <span>一些外部元素</span> <a href="https://google.com" target="_blank"> <span>一些内部元素</span> </a> </div> </a> 如果用户点击外部元素而不是内部元素,则将其重定向到同一标签中的链接。 如果用户单击内部元素,则将其重定向到新的浏览器选项卡。 在我的情况下,这更像是UI方面的东西,我不想为这样一个简单的事情注入Javascript。 - Dzintars

19

我遇到了与@thinkbonobo相同的问题,并找到了一种不需要JavaScript的解决方法:同样的问题

.outer {
  position: relative;
  background-color: red;
}
 
.outer > a {
  position: absolute;
  top: 0; left: 0; bottom: 0; right: 0;
}
 
.inner {
  position: relative;
  pointer-events: none;
  z-index: 1;
}
 
.inner a {
  pointer-events: all;
}
<div class="outer">
  <a href="#overlay-link"></a>
  <div class="inner">
    You can click on the text of this red box. It also contains a
    <a href="#inner-link">W3C compliant hyperlink.</a>
  </div>
</div>

关键在于创建一个覆盖整个 .outer div 的锚点,然后给内部 div 中的其他锚点一个正的 z-index 值。全部功劳归功于 https://bdwm.be/html5-alternative-nested-anchor-tags/


9
您可以使用object标签来解决这个问题。例如:
<a><object><a></a></object></a>

2
这个工作效果出奇的好。但是根据规范,它是否“合法”呢?规范非常密集和复杂,很难确定。 - mpoisot
1
@mpoisot 这是极其糟糕的做法和hacky。这绝对不是HTML语法方面的合法或建议性做法。如果需要更多信息,请阅读此文:https://www.w3.org/TR/html401/struct/links.html#h-12.2.2 - A Friend
这在 Windows PC 上很有效,但链接在 iPhone 上的 Safari 浏览器中不能被点击,尤其是在 iOS 15.x 版本。即使它不会因为无效规范而移动到一些奇怪的地方,最好不要使用这种 hack。 - Eason Lin

4
我发现当我尝试使一个包含按钮的 div 面板可点击时出现了问题。 我建议的解决方法是使用 JavaScript 事件。这里是我创建的 CodePen 示例.... http://codepen.io/thinkbonobo/pen/gPxJGV 以下是其 HTML 代码部分:

嵌入链接的示例...

<div class=panel onclick="alert('We\'ll hi-ii-ii-ide')">
  If you say run<br>
  <button onclick="app.hitMe(event)">more</button><br>
  <br>
  And if you say hide...<br>
</div>

请注意如何捕获内部链接的事件并使用stopPropagation(),这对确保外部触发器不运行非常关键。

1
我不得不在Chrome上使用event.preventDefault(); - Daniel F
它存在一个问题,即mmb-click无法在新标签页中打开链接。 - Daniel F
您也可以不使用JS来实现此操作,请参见下面的我的回答 - user5707327

3

这是无效的HTML。

你不能嵌套 a 元素。

因此,根据定义,行为未定义。


这可能是什么原因?我只是想要更多的解释。 - Anoop
@Sushil - 回答我这个问题 - 嵌套的 a 元素有什么意义?它可能意味着什么? - Oded
是的,这没有任何意义,但对我来说是一个新东西,所以我想要确定一下是否可以在锚点标签内嵌套span、img等标签。 - Anoop
1
@Sushil - 当然,作为内容是有意义的。但在命令中放置另一个命令就没有意义了。 - Oded
1
@Anoop 我知道这是一个非常老的帖子,但我仍然会提供我的建议。我猜想为什么您不能将a标签嵌套在其他a标签中,是因为当您单击嵌套链接时,浏览器将检测到同时单击了两个a标签(子级和父级)。这意味着它们需要知道某种优先级,例如哪个a标签更重要。浏览器可能也会以不同于其他浏览器的方式处理优先级,这样就开始变得不必要地棘手了,所以最好完全避免允许嵌套的a标签。 - A Friend

1

我知道这是一篇旧帖子,但我想指出user9147812的答案比其他建议都更好。

这就是我如何堆叠整个东西的方法。

    <style>
    * {
      padding: 0;
      margin: 0 border:0;
      outline: 0;
    }

    .outer_anchor {
      display: inline-block;
      padding: 5px 8px;
      margin: 2px;
      border: 1px solid #252632;
      border-radius: 3px;
      background: #1c1d26;
      color: #fff;
      text-shadow: 0 1px 0 #616161;
      box-shadow: 1px 1px 3px #000;
      transform: translateY(0);
      transition: background 250ms;
    }
    .inner_anchor {
      display: inline-block;
      padding: 5px 8px;
      margin: 2px;
      border: 1px solid #252632;
      border-radius: 3px;
      background: #1c1d26;
      color: #fff;
      transform: translate(0px);
    }
    .inner_anchor:hover {
      background: #647915;
    }
    </style>


<a href="#">ItemX<object><a class="elim_btn" href="#" title='Eliminate'>&times;</a></object></a>

1
对于嵌套锚点,为了防止内部事件冒泡到外部事件,您需要在内部事件被单击时立即停止传播。
在内部事件的OnClick中,使用e.stopPropagation();

0

您不能嵌套'a'标签。相反,将外部容器设置为'position:relative',第二个'a'设置为'position:absolute'并增加其z-index值。您将获得相同的效果。

<div style="position:relative">
<a href="page2.php"><img src="image-1.png"></a>
<a style="position:absolute;top:0;z-index:99" href="page1.php"></a>
</div>

0

.outer {
  position: relative;
  background-color: red;
}
 
.outer > a {
  position: absolute;
  top: 0; left: 0; bottom: 0; right: 0;
}
 
.inner {
  position: relative;
  pointer-events: none;
  z-index: 1;
}
 
.inner a {
  pointer-events: all;
}
<div class="outer">
  <a href="#overlay-link"></a>
  <div class="inner">
    You can click on the text of this red box. It also contains a
    <a href="#inner-link">W3C compliant hyperlink.</a>
  </div>
</div>


你的回答可以通过添加更多支持信息来改进。请[编辑]以添加进一步的细节,例如引用或文献资料,以便其他人能够确认你的回答是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

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