從a標籤為什麼不能包含div標籤-瞭解HTML5元素分類與內容模型

Tiny-123456789發表於2017-12-12

我們知道按新的 HTML 規範,已經不按 inline 和 block 來區分元素型別了。所以我們在a標籤裡面使用div標籤時候會發現a標籤並不能通過改變css盒子模型的方式將div元素包含。

元素分類

HTML5中,元素主要分為7類:

Metadata

Flow

Sectioning

Heading

Phrasing

Embedded

Interactive

這些分類集合互相之間也存在一定的交集(一個元素可以同時屬於多個分類),其交集關係呈現為:

從a標籤為什麼不能包含div標籤-瞭解HTML5元素分類與內容模型

需要注意的是,HTML5中的這種元素分類與inline、block沒有任何關係,任何元素都可以在CSS中被定義為display:inline或者display:block。另外,除了這7大分類,還存在一些較小的分類,如Script-Supporting元素等。

Metadata(後設資料元素)

顧名思義,Metadata元素意指那些定義文件後設資料資訊的元素 — 其作用包括:影響文件中其它節點的展現與行為、定義文件與其它外部資源之間的關係等。以下元素屬於Metadata:

base, link, meta, noscript, script, style, template, title

Flow(流式元素)

所有可以放在body標籤內,構成文件內容的元素均屬於Flow元素。因此,除了base, link, meta, style, title等只能放在head標籤內的元素外,剩下的所有元素均屬於Flow元素。

a, abbr, address, area, article, aside, audio, b, bdi, bdo, blockquote, br, button, canvas, cite, code, command, datalist, del, details, dfn, div, dl,em, embed, fieldset, figure, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, hr, i, iframe, img, input, ins, kbd, keygen, label, map, mark, math, menu, meter,nav, noscript, object, ol, output, p, pre, progress, q, ruby, s, samp, script, section, select, small, span, strong, style(如果該元素設定了scoped屬性), sub, sup, svg, table,textarea, time, u, ul, var, video, wbr, text

Sectioning(章節元素)

Sectioning意指定義頁面結構的元素,具體包含以下四個:

article, aside, nav, section

Heading(標題元素)

所有標題元素屬於Heading,也即以下6個元素:

h1, h2, h3, h4, h5, h6

Phrasing(段落元素)

所有可以放在p標籤內,構成段落內容的元素均屬於Phrasing元素。因此,所有Phrasing元素均屬於Flow元素。

對於這一定義,個人認為不應當使用“text”這一容易引起誤解的詞,事實上,一個元素即使不是文字,只要能包含在p標籤中成為段落內容的一部分,就可以稱之為Phrasing元素。

a(如果其只包含段落式元素), abbr, area, audio, b, bdi, bdo, br, button, canvas, cite, code, command, datalist, del(如果其只包含段落式元素), dfn, em, embed, i,iframe, img, input, ins(如果其只包含段落式元素), kbd, keygen, label, map(如果其只包含段落式元素), mark, math, meter, noscript, object, output, progress, q, ruby, s, samp, script,select, small, span, strong, sub, sup, svg, textarea, time, u, var, video, wbr, text

一個不太精確的類比是:HTML5中的Phrasing元素大致就是HTML4中所定義的inline元素。

Phrasing元素內部一般只能包含別的Phrasing元素。

Embedded(嵌入元素)

所有用於在網頁中嵌入外部資源的元素均屬於Embedded元素,具體包含以下9個:

audio, video, img, canvas, svg, iframe, embed, object, math

Interactive(互動元素)

所有與使用者互動有關的元素均屬於Interactive元素。

a, audio(如果設定了controls屬性), button, details, embed, iframe, img(如果設定了usemap屬性), input(如果type屬性不為hidden狀態), keygen, label, menu(如果type屬性為toolbar狀態),object(如果設定了usemap屬性), select, textarea, video(如果設定了controls屬性)

Palpable

所有應當擁有子元素的元素稱之為Palpable元素。比如,br元素因不需要子元素,因此也就不屬於Palpable。

Script-supporting

自身不做任何頁面展現,但與頁面指令碼相關的元素,具體包括2個:

script, template

內容模型(Content Model)

根據以上元素分類,HTML5標準文件定義了任何元素的內容模型 — 對於該元素而言,何種子元素才是合法的。

比如,對於p元素而言,其內容模型為Phrasing, 這意味著p元素只接受Phrasing元素為子元素,而對於像div這樣的非Phrasing元素則並不接受。類似的,li元素的內容模型為Flow,因此任何可以放置在body中的元素都可以作為li元素的子元素。

值得注意的是,HTML5標準文件在定義元素的內容模型時,會使用一類特殊的分類:透明內容模型(transparent) — 對於內容模型為透明(transparent)的元素而言,其子元素的合法性由其父元素所決定;如果其父元素的內容模型仍為透明,則檢視其祖父元素的情況,並依此類推;如果向上推演至body標籤仍未找到任何內容模型非透明的父級元素,則該透明元素內部可包含任何Flow元素。

正確巢狀標籤

元素的巢狀規則和頁面頭部申明的DTD有著千絲萬縷的關係,通過了解HTML5的元素分類與內容模型,我們能更清楚的指導我們元素的巢狀關係。雖然大部分瀏覽器都有容錯機制,寫出來的程式碼在瀏覽器下表現沒有什麼異樣,但作為一個專業開發人員,我們必須對待自己的程式碼應該一絲不苟,即使HTML5的胸襟很寬廣,但我們更應該去遵從W3C,因為只有標準健壯的程式碼,才會有更好的擴充套件與相容。

總結

因此a標籤內是否合可以包含div標籤要看其父元素的 content model 和其內容的 categories。比如我們要看 p > ins > a > div 是否合法,過程是這樣的:p 元素的 content model 是 phrasing content,ins 本身屬於 phrasing content 故可以巢狀;ins 元素的 content model 是 transparent,故在此時裡面是否能有 a 需檢查 p > a 的合法性;a 元素也屬於 phrasing content,故 p > ins > a 合法;a 元素的 content model 也是 transparent,故此時裡面包含 div 的合法性向上傳遞,檢查 ins > div 又向上傳遞,變成檢查 p > div;div 不屬於 phrasing content,所以這個巢狀是不合法的。

相關文章