把div放在锚点内是否正确?

609

我听说把块级元素放在内联元素里是HTML的大忌:

<a href="http://example.com">
    <div>
        What we have here is a problem. 
        You see, an anchor element is an inline element,
        and the div element is a block level element.
    </div>
</a>

如果在样式表中将外部锚点样式设置为display:block,会怎么样呢?这样做仍然有问题吗? HTML 4.01规范关于块级元素和内联元素似乎是这样认为的:

样式表提供了指定任意元素呈现方式的手段,包括元素是作为块级元素还是内联元素呈现。在某些情况下,例如为列表元素设置内联样式,这可能是适当的,但一般来说,作者不应该以这种方式覆盖HTML元素的传统解释。

是否有人对此问题有进一步的建议?


3
请参见:https://dev59.com/WUjSa4cB1Zd3GeqPEVA3。 - DisgruntledGoat
@DisgruntledGoat - 感谢提供链接 - 希望我早点看到它 :-) - Tom
锚点和\或链接元素是浏览器自动化控件。因此,它具有浏览器预定义的呈现和行为。然而,在 span 中包装一个真正的纯 html 元素:div 是一种罪过。A 标签不添加任何级别行为的原因是需要标记文本部分而不干扰文档流,而不是因为它们被设计为内联元素。从这个角度来看,A 是一个无用的标签。它的存在超出了问题,并不是一种罪过,但可能会导致代码丑陋和\或模糊不清。 - Bekim Bacaj
1
所有以后查看此处内容的人请注意,在HTML5中,尽管锚点标记(anchor tags)能够包含块级元素,但是它们不能包含另一个锚点标记所包含的块级元素!因为基本上来说,锚点标记不能在其内部包含其他锚点标记。您可以在这里了解更多信息:https://dev59.com/pGcs5IYBdhLWcg3wMxFF - aderchox
16个回答

859

根据您需要呈现的HTML版本:

  • HTML 5 规定 <a> 元素 "可以包含整个段落,列表,表格等甚至整个部分,只要其中没有交互式内容(例如按钮或其他链接)"。

  • HTML 4.01 规定 <a> 元素只能包含内联元素。而<div>是一个块级元素,因此不能出现在 <a> 内部。

    当然,您可以自由地样式化内联元素以使其看起来像块级元素,或者将块级元素样式化成行内元素。 在 HTML 中使用术语“内联”和“块级”是为了描述元素与文档的语义结构之间的关系,而在 CSS 中使用相同的术语则更多地与元素的视觉样式相关联。如果使内联元素以块状方式显示,那没问题。

    但是您应该确保在没有 CSS 的情况下文档结构仍然有意义,例如当通过辅助技术(例如屏幕阅读器)或强大的 Googlebot 访问时。


4
在http://www.w3.org/TR/REC-html40/sgml/dtd.html上有一个4.01的DTD。A元素可以包含%inline%; %inline%是各种不同的东西(您可以跟随链接),但DIV不在其中。因此,包含DIV的A元素无法通过XML验证。我认为该DTD很好地表达了委员会的意图,所以我的结论是:不行。 - Carl Smotricz
2
<!ELEMENT A - - (%inline;)* -(A) 具体来说,规范中的 (%inline;)* 部分表示只包含内联元素。更多关于阅读 DTD 文档的内容请参考:http://www.w3schools.com/dtd/dtd_elements.asp - Brian Chavez
67
在读到有关HTML5的最后一行之前,我差点放弃在项目中做这件事情,现在知道了这点,谢谢。 - Elaine Marley
20
Mozilla 开发者网络(https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a)反映了 HTML5 的 <a> 元素现在支持像 <div>、<ul> 或 <table> 这样的流内容元素。 - AxeEffect
23
在HTML5下,a元素被归类为transparent,这意味着它只有在a元素的父元素可以包含flow元素(默认为块级元素)时才可以包含flow元素。否则,只有phrasing元素(默认为行内元素)是允许的。因此,如果a元素在一个formdiv中,它可以包含一个div,但在一个p中就不行。请参见http://www.w3.org/TR/html-markup/terminology.html - Patanjali
显示剩余10条评论

83

不,它不会通过验证,但是在现代浏览器中通常可以正常工作。话虽如此,请在您的锚点内部使用一个span,并在其上设置display:block,这样它将在任何地方都能起作用,并且能够通过验证!


8
如果你将 display: block 设为样式,那么从技术上讲,它会变成一个块级元素吗? - WhyNotHugo
22
@hugo 这在技术上有影响吗? - Andy Chase
5
HTML 4.01规定a元素只能包含内联元素。如果你将span元素变成块级元素,严格来说,它不应该在锚点内部。 - WhyNotHugo
23
@Hugo:看起来 HTML4 中的限制是语义上的,而不是呈现上的。从语义上讲,<div>是块级元素,而<span>是内联元素,即使文档的伴随 CSS 反过来规定了也是如此。 - Roy Tinker
在 span 标签中添加 style="display:block;",它就像魔法一样奏效了。只需调整填充即可获得所需的结果。 - Harif87
老旧的HTML4已经不再相关。 - Michael Rogers

35

W3C文档没有使用“错误”和“罪恶”等概念,但使用了“提供手段”,“可能合适”和“不鼓励”等词语。

事实上,在第4节的第二段中,4.01规范将其单词列举如下:

本文件中的关键词“必须(MUST)”、“不得(MUST NOT)”、“要求(REQUIRED)”、“应当(SHALL)”、“不应当(SHALL NOT)”、“应该(SHOULD)”、“不该(SHOULD NOT)”、“建议(RECOMMENDED)”、“可以(MAY)”和“可选(OPTIONAL)”的解释详见[RFC2119]。 但为了易读性,在本规范中这些单词并非全部是大写字母。

有了这个理解,我相信最明确的陈述是在7.5.3块级元素和内联元素中,其中说:

通常,内联元素只能包含数据和其他内联元素。

条件“通常”似乎引入了足够的歧义,以表明HTML 4.01允许内联元素包含块级元素。

当然,CSS2具有显示属性值 inline-block ,这似乎适合您所描述的用途。 我不确定它是否被广泛支持,但似乎有人预料到了那种行为的需要。

DTD 在这里似乎不太容易原谅,但是 DTD 文本 向规范推迟:

HTML 4.01 规范包括不能在 DTD 中表达的附加语法约束。

在另一条评论中,您建议通过将块包装在锚点中使其处于活动状态。我不认为 HTML 禁止这样做,而 CSS 明确允许。因此,回答标题问题——是否正确,我的答案是:有时候是正确的,符合标准。


2
直到你提到 doctype,我才被打乱了。 - Robert Harvey
你可能是对的 - 我应该使用doctype.com。哎呀 - 下次我会记住的。PHP -> SO,HTML -> doctype.com - Tom
我并没有一个强烈的偏好,针对这个问题在哪个论坛提问。不过,我很想知道 Robert Harvey 对 doctype 的看法。 - Ewan Todd
2
我的看法是,没有“应该在doctype.com上关闭”的“投票关闭”选项(也不应该有)。 - Robert Harvey
7
我同意 Rob 的观点 - Stack Overflow 是为编程而设的。在我看来,HTML/CSS 绝对是编程。 - DisgruntledGoat
编写标准似乎是一种锻炼,看看能在单个文档中塞入多少模棱两可的词汇,以及它们可以如何创造性地组合产生最大的歧义。 - Eloff


18

使用HTML5规范...现在可以将块级元素放置在内联元素中。因此,现在将'div'或'h1'放置在'a'元素中是完全合适的。


9
只有在 flow 元素内(默认为 block),或者父元素允许 flow 元素的 transparent 元素(比如 a)内才可以。例如,p 不允许包含 flow 元素(如 div),只能包含 phrasing 元素(默认为 inline),所以在 p 中的 a 不可以包含 div。但是,在 div 中的 a 可以包含 pdiv 或任何其他 flow 元素。 - Patanjali

7

在HTML5中,像<div>这样的块级元素可以被<a>标签包裹。虽然<div>被认为是流内容的容器/包装器, 而<a>被认为是流内容,根据MDN,从语义上讲,创建作为块级元素的内联元素可能更好。


1
由于a元素是透明的,只有当a元素的父元素允许流动(默认为块级元素)时,才能显示。 - Patanjali

5
如果想避免在锚点标签内放置 div 标签所带来的语义问题,只需将锚点标签和 div 标签置于同一级别,用一个 position: relative 的容器将它们全部包裹起来,将锚点标签设为 position: absolute 并扩展至容器大小。另外,如果不是在内容流的末尾,请确保添加 z-index 来使其位于内容之上。
按建议,我已经添加了一个标记代码:
<div class="div__container>
  <div class="div__one>
  </div>
  <div class="div__two">
  </div>
  <a href="#"></a>
</div>

并且 CSS:

.div__container {
  position: relative; 
}
.div__container a {
  position: absolute;
  top: 0;
  bottom: 0;      
  left: 0;
  right: 0;
  z-index: 999;
}

1
虽然你的答案可能是正确的,但如果你用标记说明它会更有帮助。 - datashaman
以上代码可行。我在这个fiddle中测试过:https://jsfiddle.net/h1uvo6nk/ - Éric

5

您不能将<div>放在<a>中,这是不符合(X)HTML规范的。

即使您使用display: block对span进行样式设置,仍然不能在其中放置块级元素:无论CSS如何改变,(X)HTML仍须遵守相应的DTD(无论您使用哪个DTD版本)规定。

浏览器可能会按您的意图显示内容,但这并不代表是正确的。


4
http://www.w3.org/TR/REC-html40/sgml/dtd.html 上有一个 HTML 4 的 DTD。这个 DTD 是规范的机器可处理形式,但是需要注意的是,DTD 管理的是 XML 和 HTML 4,特别是“瞬时”风格允许很多在 XML 中不“合法”的东西。尽管如此,我认为它已经接近于将规范者的意图编码化了。
<!ELEMENT A - - (%inline;)* -(A)       -- anchor -->

<!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;">

<!ENTITY % fontstyle "TT | I | B | BIG | SMALL">

<!ENTITY % phrase "EM | STRONG | DFN | CODE | SAMP | KBD | VAR | CITE | ABBR | ACRONYM" >

<!ENTITY % special "A | IMG | OBJECT | BR | SCRIPT | MAP | Q | SUB | SUP | SPAN | BDO">

<!ENTITY % formctrl "INPUT | SELECT | TEXTAREA | LABEL | BUTTON">

我会将此层级中列出的标签解释为允许使用的标签总数。
尽管规范可能会说“内联元素”,但我相信它并不意味着您可以通过声明块元素的显示类型为内联来绕过意图。无论您如何滥用内联标签,它们都具有不同的语义。
另一方面,我发现包含special似乎允许嵌套A元素。即使它在XML语法上是正确的,规范中可能也有一些强烈的措辞禁止这样做,但我不会进一步追究这个问题,因为这不是问题的主题。

你知道“- -”代表什么吗?我试图找到一个解释,但是没有找到。 - Ewan Todd

2

所有东西都能用……直到你嵌套它们。

你可以嵌入表格、div、鸟和蜜蜂,浏览器会耐心地配合。但是一旦你在其中再放一个<a>标签,它就会打破原有布局,把内部标签放在外部标签的关闭标签之后。值得一试,即使在F12控制台中,当浏览器不喜欢某些内容时,你会惊讶于它可以多么严格。

因此,不存在这样的事情:

<a href="#1">
    <a href="#2"> Now what </a>
</a>

相反,它将变成:
<a href="#1"></a>
<a href="#2"> Now what </a>

同样的问题也发生在<p>等几个标签上;事实上,有一篇Stacko文章讨论了这个问题-Can I nest these tags? -唯一的答案是要看"HTML规范表明"部分的项目列表。最挑剔的标签显然是ap,还有像h1..h6这样的荣誉提名。 (现在说实话:您是否曾经使用过p标签,特别是因为它给了您其他人无法获得的东西?...想到了。我只会放弃它。)

简而言之 - 你不能把a放在a里面。


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