HTML教程XHTML教程:HTML标记嵌套使用技巧
发布时间:2019-04-13浏览次数:836
<p>
</p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"><tbody><tr>
<td style="WORD-WRAP: break-word" bgcolor="#fdfddf">
<font color="#ff0000">网页制作Webjx文章简介:</font><font color="#000000">WEB标准-HTML元素嵌套.</font>
</td>
</tr></tbody></table>
<p>先来看以下这样一段代码:</p>
<div>
<div class="syntaxhighlighter notranslate html ie" id="highlighter_483721">
<table border="0" cellspacing="0" cellpadding="0"><tbody><tr>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><ul> </div>
<div class="line number2 index1 alt1">   <li><h4><a href=""><div></div></a></h4></li> </div>
<div class="line number3 index2 alt2"> </ul></div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<p>当然,我是不会告诉你这段代码来自于FACEBOOK的 ,各位认为以上元素的嵌套有没有问题呢?我们会在后面讨论这个。</p>
<h2>HTML4/XHTML的嵌套规则</h2>
<p>在我们的印象中会有这样的嵌套规则:</p>
<p><img width="510" height="376" class="aligncenter" alt="html4" src="http://www.webjx.com/files/allimg/130722/0946010.png"></p>
<blockquote>
<p><span class="wp_keywordlink_affiliate">内联元素</span>不能嵌套块元素<p>元素和<h1~6>元素不能嵌套块元素</p>
</blockquote>
<p>那么到底什么是<strong>块元素</strong>,什么是<strong><span class="wp_keywordlink_affiliate">内联元素</span></strong>?</p>
<p>以下是W3C CSS2.1规范中对块元素和<span class="wp_keywordlink_affiliate">内联元素</span>的定义:</p>
<blockquote>
<p><strong><dfn>Block-level elements</dfn></strong> are those elements of the source document that are formatted visually as blocks (e.g., paragraphs). The following values of the ‘display’  property make an element block-level: ‘block’, ‘list-item’, and ‘table’.</p>
<p><strong><dfn>Inline-level elements</dfn></strong> are those elements of the source document that do not form new blocks of content; the content is distributed in lines (e.g., emphasized pieces of text within a paragraph, inline images, etc.). The following values of the ‘display’ property make an element inline-level: ‘inline’, ‘inline-table’, and ‘inline-block’. Inline-level elements generate <dfn>inline-level boxes</dfn>, which are boxes that participate in an inline formatting context.</p>
</blockquote>
<p>我们可以这样理解:块元素一般都从新行开始,内联元素在一行内显示,我们也可以通过CSS属性display的’inline’ 或 ‘ block’ 来改变元素为内联元素或块元素,当然这是CSS中对元素的分类,显然用 ‘display’ 的属性值来对html元素进行分类是不严谨的。</p>
<p>如果按照上述规则来讲,那么FACEBOOK的做法就是一种错误的做法,因为他在内联元素<a>元素中嵌套了块元素元素<div>,但是细心的读者应该会发现上述规则是基于HTML4/xHTML1的strict模式,而FACEBOOK现在已经统一使用了html5的doctype,那么这个规则到底还是是否适用?</p>
<h2>HTML5的元素嵌套规则</h2>
<p>元素的嵌套规则和页面头部申明的DTD有着千丝万缕的关系,DTD基础请查看我之前写的文章《DTD详解》,那么在最新的HTML5规范中是否对元素嵌套有着新的规范呢?</p>
<p>让我们先了解下W3C在最新的HTML5规范中对元素的分类方式:</p>
<p><img class="aligncenter" alt="w3c html5 content" src="http://www.webjx.com/files/allimg/130722/0946011.png"></p>
<p>如上图,元素的分类不再是块元素或内联元素这样来分类(其实从来就没有这样分),而是按照如下分类来分:<strong>Flow</strong>(流式元素)、<strong>Heading</strong>(标题元素)、<strong>Sectioning</strong>(章节元素)、<strong>Phrasing</strong>(段落元素)、<strong>Embedded</strong>(嵌入元素)、<strong>Interactive</strong>(交互元素)、<strong>Metadata</strong>(元数据元素)。</p>
<h3>
<strong>Flow</strong>(流式元素)</h3>
<p>在应用程序和文档的主体部分中使用的大部分元素都被分类为<strong id="flow-content">流式元素</strong>。</p>
<blockquote>
<p>a, abbr, address, area(如果它是map元素的后裔), 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</p>
</blockquote>
<h3>
<strong>Heading</strong>(标题元素)</h3>
<p><strong id="heading-content">标题式元素</strong>定义一个区块/章节(section)(无论是明确的使用章节式内容的元素标记,或者标题式内容自身所隐含的)的标题。</p>
<blockquote>
<p>h1, h2, h3, h4, h5, h6, hgroup</p>
</blockquote>
<h3>
<strong>Sectioning</strong>(章节元素)</h3>
<p><strong id="sectioning-content">章节式元素</strong>是用于定义标题及页脚范围的元素。</p>
<blockquote>
<p>article, aside, nav, section</p>
</blockquote>
<h3>
<strong>Phrasing</strong>(段落元素)</h3>
<p><strong id="phrasing-content">段落式元素</strong>是文档中的文本、标记段落级文本的元素。</p>
<blockquote>
<p>a(如果其只包含段落式元素), abbr, area(如果它是map元素的后裔), 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</p>
</blockquote>
<h3>
<strong>Embedded</strong>(嵌入元素)</h3>
<p><strong id="embedded-content">嵌入式元素</strong>是引用或插入到文档中其他资源的元素。</p>
<blockquote>
<p>audio, canvas, embed, iframe, img, math, object, svg, video</p>
</blockquote>
<h3>
<strong>Interactive</strong>(交互元素)</h3>
<p><strong id="interactive-content">交互式元素</strong>是专门用于与用户交互的元素。</p>
<blockquote>
<p>a, audio(如果设置了controls属性), button, details, embed, iframe, img(如果设置了usemap属性), input(如果type属性不为hidden状态), keygen, label, menu(如果type属性为toolbar状态),object(如果设置了usemap属性), select, textarea, video(如果设置了controls属性)</p>
</blockquote>
<h3>
<strong>Metadata</strong>(元数据元素)</h3>
<p><strong>元数据元素</strong>是可以被用于说明其他内容的表现或行为,或者在当前文档和其他文档之间建立联系的元素</p>
<blockquote>
<p>base,command,link,meta,noscript,script,style,title</p>
</blockquote>
<p><em>各分类会有交叉或重叠的现象,这说明在html5中,元素可能属于上述所有分类中的一个或多个。</em></p>
<h3>例子(1):<h1>~<h6>元素:</h3>
<ul>
<li>
<strong>Categories:</strong>
<ul>
<li>Flow content. </li>
<li>Heading content. </li>
<li>Palpable content. </li>
</ul>
</li>
<li>
<strong>Contexts in which this element can be used</strong>:
<ul>
<li>As a child of an hgroup element. </li>
<li>Where flow content is expected. </li>
</ul>
</li>
<li>
<strong>Content model:</strong>
<ul>
<li>Phrasing content. </li>
</ul>
</li>
</ul>
<p>其中的「<strong>Categories</strong>」说明该元素的类别,「<strong>Contexts in which this element can be used</strong>」说明该元素能在何种场景下被使用,也就是它的父元素是什么,「<strong>Content model</strong>」说明该元素可以包含的内容是什么,由于页面中的元素是层层嵌套的,一个元素有可能既是父元素同时也是子元素的角色,所以下面我们以「<strong>Content model</strong>」也就是可包含的子元素做讨论。</p>
<p><strong>那么对于h1~h6元素:</strong></p>
<ul>
<li>它们同时属于<strong>Flow content</strong> 、<strong>Heading content</strong> 和<strong> Palpable content</strong>三个分类 </li>
<li>它们的父元素可以是<hgroup>,同时那些子元素是流式元素的元素也可以作为h1-h6元素的父元素 </li>
<li>它们允许的子元素是段落式元素 </li>
</ul>
<h3>例子(2):<div>元素</h3>
<ul>
<li>
<strong>Categories:</strong>
<ul>
<li>Flow content. </li>
<li>Palpable content. </li>
</ul>
</li>
<li>
<strong>Contexts in which this element can be used:</strong>
<ul>
<li>Where phrasing content is expected. </li>
</ul>
</li>
<li>Content model:
<ul>
<li>Flow content. </li>
</ul>
</li>
</ul>
<p><strong>对于<div>元素:</strong></p>
<ul>
<li>同时属于<strong>Flow content</strong> 、<strong> Palpable content</strong>分类 </li>
<li>父元素必须是那些子元素为段落式元素的元素 </li>
<li>允许的子元素是流式元素 </li>
</ul>
<p><div>元素允许的子元素是流式元素,流式元素基本涵括了页面中的大部分元素,所以我们在用<div>时可以不用担心嵌套错误的问题。</p>
<p>但对于<h1>~<h6>元素,它们允许的子元素为段落式元素,而段落式元素并不包含诸如<div>、<p>、<ul><ol>之类的元素,这就说明按照html5的规范,是不允许在标题元素内部嵌入<div>、<p>、<ul><ol>之类的元素。</p>
<h3>例子(3):<a>元素</h3>
<ul>
<li>
<strong>Categories:</strong>
<ul>
<li>Flow content. </li>
<li>Phrasing content. </li>
<li>Interactive content. </li>
<li>Palpable content. </li>
</ul>
</li>
<li>
<strong>Contexts in which this element can be used:</strong>
<ul>
<li>Where phrasing content is expected. </li>
</ul>
</li>
<li>
<strong>Content model:</strong>
<ul>
<li>Transparent, but there must be no interactive content descendant. </li>
</ul>
</li>
</ul>
<p><strong>对于<a>元素:</strong></p>
<ul>
<li>同时属于<strong>Flow content</strong> 、<strong> Phrasing content</strong>、<strong>Interactive content</strong>、<strong>Palpable content</strong>分类 </li>
<li>父元素必须是那些子元素为段落式元素的元素 </li>
<li>允许的子元素是以它的父元素允许的子元素为准,但不能包含交互式元素 </li>
</ul>
<p>这样看<a>元素还是挺有意思的,允许的子元素要看它的父元素所能包含的子元素。</p>
<h3>再来看文章开头中提到的代码</h3>
<div>
<div class="syntaxhighlighter notranslate xhtml ie" id="highlighter_790149">
<table border="0" cellspacing="0" cellpadding="0"><tbody><tr>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><ul> </div>
<div class="line number2 index1 alt1">  <li><h4><a href=""><div></div></a></h4></li> </div>
<div class="line number3 index2 alt2"></ul></div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<p>这时<a>的父元素为<h4>,对于<h1>~<h6>的标题元素上面已经提过,允许的子元素是段落式元素,那么此时对于<a>允许的子元素即为段落式元素,而段落式元素中是不包含<div>元素的,所以<strong>FCAEBOOK这样的嵌套方法是错误的!</strong></p>
<p>让我们来把代码做一下修改:</p>
<div>
<div class="syntaxhighlighter notranslate html ie" id="highlighter_832947">
<table border="0" cellspacing="0" cellpadding="0"><tbody><tr>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><ul> </div>
<div class="line number2 index1 alt1">   <li><div><a href=""><div></div></a></div></li> </div>
<div class="line number3 index2 alt2"> </ul></div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<p>这时<a>的父元素为<div>,而<div>元素允许的子元素是流式元素,流式元素中包含<div>元素,所以这样的情形下在<a>里面嵌套<div>就是正确的做法!</p>
<h2>嵌套错误可能引起的问题</h2>
<p>上面讲了HTML5对元素新的分类方式和以<h1>~<h6>、<div>、<a>元素举例讲述了各自的嵌套规则,但FACEBOOK即使不按照标准去嵌套也不会有大的错误问题,这就给我们带来了一个思考:嵌套错误到底会不会有问题?</p>
<h3>例子(1):开始与结束标签嵌套错误</h3>
<div>
<div class="syntaxhighlighter notranslate html ie" id="highlighter_237599">
<table border="0" cellspacing="0" cellpadding="0"><tbody><tr>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><div><h2>内容</div></h2></div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<p><strong>测试结果:</strong></p>
<p><img width="513" height="333" class="aligncenter" alt="element11" src="http://www.webjx.com/files/allimg/130722/0946012.png"></p>
<h3>例子(2):<p>元素嵌套<div>元素</h3>
<div>
<div class="syntaxhighlighter notranslate html ie" id="highlighter_515492">
<table border="0" cellspacing="0" cellpadding="0"><tbody><tr>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><p><div>内容</div></p></div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<p><strong>测试结果:</strong></p>
<p><img width="512" height="344" class="aligncenter" alt="element12" src="http://www.webjx.com/files/allimg/130722/0946013.png"></p>
<h3>例子(3):列表元素<li>兄弟元素为<div></h3>
<div>
<div class="syntaxhighlighter notranslate html ie" id="highlighter_147277">
<table border="0" cellspacing="0" cellpadding="0"><tbody><tr>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><ul><li>内容</li><div>内容</div></ul></div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<p><strong>测试结果:</strong></p>
<p><img width="515" height="344" class="aligncenter" alt="element13" src="http://www.webjx.com/files/allimg/130722/0946014.png"></p>
<h3>例子(4):<h2>元素嵌套<div>元素</h3>
<div>
<div class="syntaxhighlighter notranslate html ie" id="highlighter_469667">
<table border="0" cellspacing="0" cellpadding="0"><tbody><tr>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><h2><div>内容</div></h2></div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<p><strong>测试结果:</strong></p>
<p><img width="513" height="314" class="aligncenter" alt="element14" src="http://www.webjx.com/files/allimg/130722/0946015.png"></p>
<h3>例子(5):<a>元素嵌套<a>元素</h3>
<div>
<div class="syntaxhighlighter notranslate html ie" id="highlighter_208225">
<table border="0" cellspacing="0" cellpadding="0"><tbody><tr>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><a href=""><a href="">内容</a></a></div>
</div>
</td>
</tr></tbody></table>
</div>
</div>
<p><strong>测试结果:</strong></p>
<p><img width="513" height="326" class="aligncenter" alt="element15" src="http://www.webjx.com/files/allimg/130722/0946016.png"></p>
<p>通过上述例子,我们总结如下:</p>
<ul>
<li>元素开始与结束标签嵌套错误,页面可以在大部分浏览器被正常解析,IE9会出现解析错误 </li>
<li>在<p>元素内嵌入<div>等元素造成所有浏览器的解析错误 </li>
<li>在<h1>~<h6>元素内嵌入<div>等元素所有浏览器可以解析正常 </li>
<li>在<a>元素内嵌入<a>元素会导致所有浏览器的解析错误 </li>
<li>在列表元素<li><dt><dd>等插入非列表兄弟元素会导致IE6\IE7的解析错误 </li>
</ul>
<p>其实,这里说解析错误并不是很合理,应该是说浏览器解析出来的结果和我们期望的结果不一致,但任何的嵌套错误都不会导致页面呈现有很大的出错。</p>
<p>我们知道JS代码如果写的有语法错误,浏览器的JS解释器就会拒绝执行并且报错,而浏览器在遇到不符合语法规定的HTML代码时则会千方百计将其呈现出来。</p>
<h2>严格嵌套约束、语义嵌套约束</h2>
<p>通过上面的示例我们发现在<p>元素里嵌套<div>元素或者<a>元素里<a>元素会导致所有的浏览器都解析错误,这其实是W3C规范的严格嵌套约束,严格嵌套约束要求必须去遵守,不然就会导致所有浏览器的解析错误。</p>
<p><strong>严格嵌套约束规则:</strong></p>
<ul>
<li>a元素里不可以嵌套交互式元素(<a>、<button>、<select>等) </li>
<li><p>里面不可以嵌套<div>、<h1>~<h6>、<p>、<ul>/<ol>/<li>、<dl>/<dt>/<dd>、<form>等 </li>
<li>暂时没有发现更多,有的欢迎告诉我 </li>
</ul>
<p><strong>语义嵌套约束:</strong></p>
<p>每个元素基本都有自己的嵌套规则(即父元素可以是什么,子元素可以是什么),除了严格嵌套约束之外的一些规则就是语义嵌套约束,对于语义嵌套约束,如果不遵守,页面可能正常,但也可能解析错误,这和下面要讲的<span class="wp_keywordlink_affiliate">容错机制</span>有关。</p>
<h2>浏览器的<span class="wp_keywordlink_affiliate">容错机制</span>
</h2>
<p>并不是每位同学在写完页面后去做合法性检查,因此浏览器厂商不得不让它们的浏览器以尽可能宽松的方式去处理网页,每个浏览器内核中都有相当一部分代码专门用来处理那些含糊不清的html标记及嵌套,并且会去猜测前端们到底想如何呈现网页,这是浏览器的<strong><span class="wp_keywordlink_affiliate">容错机制</span></strong>。</p>
<p>这其实在告诉我们,我们写出来的HTML代码不符合W3C规范可能最终呈现出来没有异样,但那其实是浏览器的一种容错机制,我们没有理由让自己以一个随性的态度去coding,对待自己的代码应该一丝不苟,即使HTML5的胸襟很宽广。</p>
<h2>拥抱WEB标准</h2>
<p>原本我们认为从HTML4到XHTML是一个时代,现在又从XHTML跨到了<strong>HTML5</strong>,新时代新标准的诞生,我们应该敞开胸怀去拥抱,而不是排斥。</p>
<p>你关注或不关注,标准就在那里,只增不减。我们应该感谢W3C这样一个组织,让各个浏览器厂商抛开彼此的敌意共同制定新的标准。不然,也许你会像90年代那样,JS引用一个元素都需要为某个浏览器写一套自己的代码。</p>
<p>WEB标准只会使我们吃饭变得更香,睡眠变得更好,新的技术或标准会推动我们去富有热情的coding,而不是每天在重复劳动。</p>