标记语言——精简标签

点击这里返回脚本之家 HTML教程 栏目.
上文:

标记语言——再谈清单


原文出处Chapter 9 精简标签
先前我们不断提到结构化内容能够把结构与设计细节分类并精简标签,该怎么做呢?我们可以使用符合标准的XHTML与CSS代替表格,图片制作我们所需要的版面.
使用标准技术制作网站(特别是十分依赖CSS的网站)的时候,我们常常会养成一个不太好的习惯,就是加上多余的标签和class属性,技术完全不需要它们.
通过在CSS中使用集成选择器(descendant selectors),我们就能消除多余的<div>,<span>与分类属性.精简标签代表页面将能读取得更快,同时更容易维护,在这一章中,我们会讨论几个完成这项任务的简单做法.以标准技术制作网站时,如何精简标签?
精简标签是个值得讨论的重要话题,制作网站时,用合法的XHTML书写,用CSS设定展示效果能得到的巨大好处之一,就是精简标签.简短的代码代表着下载速度加快,对于使用56k拨号上网的用户来说,这绝对是关键,简短的代码也代表服务器空间需求,带宽消耗减少,这能让老板,系统管理者开心.
问题在于,单纯的确定页面符合W3C标准规范并不代表内容所使用的代码会缩短,你当然能为符合标准的标记内容加上各种不需要的标签,没错,他的确符合标准,但可能为了让设计CSS的时候方便一点,加了不少多余的代码.
别怕!这边有些技巧,让你能设计出简洁,有符合标准的标记内容,但也同时保留足够的CSS样式控制能力.接着让我们学习几个精简标签的简单技巧.继承选择器
在这里我们要看看两种在个人网站标记侧边栏(包括信息,链接和其他东西)的做法.把所有好东西塞进一个id是"sidebar"的<div>里,以便稍后把它放到浏览器视窗中的某一处(第二部分将会讨论CSS布局 / 排版功能).方法A:高兴的分类

<div id="sidebar">
<h3 class="sideheading">About This Site</h3>
<p>This is my site.</p>
<h3 class="sideheading">My Links</h3>
<ul class="sidelinks">
<li class="link"><a href="archives.html">Archives</a></li>
<li class="link"><a href="about.html">About Me</a></li>
</ul>
</div>

我在许多网站上看过类似方法A的标记内容,在设计者刚发现CSS的威力的时候,很容易感动过头,为每个想要制定特殊样式的标签指定class.
以前面这个例子来说,或许我们认为<h3>指定class=sideheading是为了帮助它们指定与页面之内其他标题不同的样式;为<ul>和<li>指定class也是为了同样的理由.分类CSS
指定样式时,假设我们想让标题变成橘色,使用serif字体,底部加上浅灰色边线,而"sidelinks"无序清单则要把小圆点符号去掉,清单项目改为粗体.
方法A需要的CSS内容看起来会像这样:

.sideheading {
font-family: Georgia, serif;
color: #c63;
border-bottom: 1px solid #ccc;
}
.sidelinks {
list-style-type: none;
}
.link {
font-weight: bold;
}

我们能参照标记内制定的分类名称(class),为这些标签指定特殊样式,你甚至能想象页面的其他部分也照这个方式组织: 导航条,页尾与内容区,每个标签都加上了杂乱的分类,以便对它们有完全控制权.
没错,它的确能运作,但是有个简单的做法能够节省这些分类属性(class),同时让你的CSS更容易阅读,更具组织性,接着看方法B.方法B:自然的选择

<div id="sidebar">
<h3>About This Site</h3>
<p>This is my site.</p>
<h3>My Links</h3>
<ul>
<li><a href="archives.html">Archives</a></li>
<li><a href="about.html">About Me</a></li>
</ul>
</div>

方法B短小精悍!但是等等,分类都到哪里去了?恩...你很快就会发现我们其实并不是真的需要它们,主要是因为我们把这些标签都塞进一个具有惟一名称(本例是sidebar)的<div>的关系.
这就是发挥继承选择器作用的地方了.我们只需要直接以标签名称指定位于sidebar之内的标签,就能去掉这些多余的分类属性.以内容前后关系指定CSS
让我们看看与方法A相同的样式,但是这次我们用继承选择器指定位于sidebar里的标签.

#sidebar h3

{
font-family: Georgia, serif;
color: #c63;
border-bottom: 1px solid #ccc;
}

#sidebar ul

{
list-style-type: none;
}

#sidebar li

{
font-weight: bold;
}

通过参考 #sidebar ID,就能为包含在其中的标签指定特殊样式,举例来说,只有位于<div id="sidebar">之内的<h3>标签会设定上述的CSS规则.
这种根据内容前后关系指定样式的做法是缩短标记内容的关键.通常在为内容设计好语义结构之后,就不必为标签加上分类属性了.不止用在侧边栏
我们只展示了页面的一个段落(就是侧边栏),不过这个做法可以应用到整个页面结构上,只要将标记内容依照逻辑分成几个段落(或许是#nav,#content,#sidebar,#footer),然后以继承选择器为这个段落内的标签分别制定特殊样式就可以了.
举例来说,假设在页面内的#content与#sidebar段落内都用了<h3>标签,并且希望它们都使用serif字体,然而,你希望其中一个段落的<h3>以紫色显示,另一个则是橘色.
这是不需要修改任何标签,加上分类属性.我们可以通过一个全局样式指定所有<h3>标签共用的规则,然后用继承选择器根据标签的位置设定颜色.

h3 {
font-family: Georgia, serif; /* All h3s to be serif */
}
#content h3 {
color: purple;
}
#sidebar h3 {
color: orange;
}

指定所有<h3>标签都使用senif字体,而颜色必须根据内容上下文关系选择使用紫色或是橘色,此时我们不需要重复共享规则(这个例子中是font-family),因此能缩短CSS的内容,同时防止多个声明内出现重复的规则.
我们不仅能减少class属性需要的额外的标记空间,同时CSS结构也变得更具意义,让我们更容易阅读它的内容,更容易依照页面分段进行组织,修改特定的规则也变得很简单,对庞大,复杂的排版来说特别明显,因为这时你可能会同时拥有上百条CSS规则.
举例来说,在这个例子中,如果把共享规则加到每个声明中,而稍后想把所有<h3>换成sans serif字体的话,就得修改三个地方,没办法一次搞定.越少分类越好维护
除了减少需要使用的源代码空间之外,用继承选择器代替多余分类还代表了标记内容未来易于扩展.
举例来说,让我们假设你想让sidebar之内的链接变成红色,而不是像页面的其余部分那样使用蓝色,因此你建立了一个red类,像这样加到锚点标签中:

<div id="sidebar">
<h3>About This Site</h3>
<p>This is my site.</p>
<h3>My Links</h3>
<ul>
<li><a href="archives.html"

class="red"

>Archives</a></li>
<li><a href="about.html"

class="red"

>About Me</a></li>
</ul>
</div>

而把这些链接变成红色(假设预设的链接颜色不是红色)则需要类似这样的CSS:

a:link.red {
color: red;
}

这些动作没什么问题,也完全可以正常运作,但是如果未来你改变心意,想把这些链接换成绿色的话怎么办?或者更实际一点,你的老板偶尔说了"今年红色已经过时了,把这些侧边栏链接换成绿色"!没问题,你只要修改CSS里的red类就搞定了,但是标记内容里的class属性还是red,明显这不完全符合语义,就跟使用其他颜色当作分类名称一样.
这不是个使用显示效果当作分类名称的好地方,但是完全不指定分类的话,我们能省去许多处理分类的精力(以及代码),同时让内容语义更合理,我们倒不如以继承选择器选择这些侧边栏的链接,依照需要指定样式.
标记内容和方法B完全相同,而设定侧边栏的链接所需的CSS将是这样:

#sidebar li a:link

{
color: red;
}

基本上,这代表"只有在<div id="sidebar">之内的<li>标签里的使用了href属性的锚点标签应还显示成红色".
现在,我们维持了简短灵活的标记内容,而未来更新只需要用到CSS,不管想让链接变成红色,绿色,粗体,斜体都没问题.
接着,来看看另一个精简标签的做法:消除不必要的<div>标签,直接取用现有的块级标签.
#p#不必要的<div>
除了减少指定样式所需的分类属性外,还有另一个精简标签的简单方法:那就是当<div>标签里有块级元素时,就把<div>去掉,接下来看看这两个例子.方法A:使用<div>

<div id="nav">


<ul>
<li><a href="archives.html">Archives</a></li>
<li><a href="about.html">About</a></li>
</ul>

</div>


这是个非常小巧的导航条,只以一个无序清单构成,我们为包住整个清单的<div>指定了nav作为id.
但是<ul>和<div>一样是块级元素,为什么不直接为它指定id呢?让我们看看方法B.方法B:去掉<div>

<ul id="nav">


<li><a href="archives.html">Archives</a></li>
<li><a href="about.html">About</a></li>

</ul>


方法B显示能直接使用ul,扔掉多余的<div>,任何定位,内外补丁之类的样式设定同样能指定给<ul>,就像指定给<div>一样简单.因此转而扔掉外包标签,所见一部分标记源码.
有个重点必须留意,那就是这个做法只在nav不包含<ul>以外的标签时才适用,举例来说,里面不能有多余的段落,<blockquote>或者<form>.由于这些标签通常不适合放在<ul>中,因此以<div>作为外包标签应该更有道理.然而,对于方法A,方法B所举的例子来说,无序清单是唯一内涵的标签,因此扔掉<div>就说得通,事实上,考虑所有外包标签的存在意义十分重要,它真的需要放在哪里吗?有没有现存的块级元素可以使用?简洁的标记代码不难办到.其他例子
另一个可以扔掉<div>的情形是外包<form>的情况,举例来说,如果原本是这样的话:

<div id="myform">


<form>
... form elements here ...
</form>

</div>


其实能用更简单的写法:

<form id="myform">


... form elements here ...

</form>


同样的,如果网站的页尾只包含单一段落,除了这样写之外:

<div id="footer">


<p>Copyright 1999-2004 Dan Cederholm</p>

</div>


也能写成这样:

<p id="footer">Copyright 1999-2004 Dan Cederholm</p>


当然只有在页尾只包含一个段落的时候才能如此修改.
#p#归纳
看了两种精简标签代码的简单方法,首先是节制的使用分类属性,并且以继承选择器设定样式;再来是直接为现存的单一块级元素指定id,而不用多余的<div>外包它们.
这些方法看起来只能节省无关紧要的一点大小,但是当开始为整个网站实施这些方法之后,精简,结构化的代码就会逐渐明朗,也会写出更灵活,符合语义,未来更容易维护的内容.
在"技巧延伸"中,让我们看看如何进一步发挥继承选择器的威力,为嵌套状清单指定样式,并且把它做成网站地图.技巧延伸
在这个单元里,一起来探讨怎么以继承选择器为一组嵌套状清单的不同级别分别制定特殊样式.我们所制作的是个小网站地图的一部分.我们将发现保留十分基本的标记代码,不需要加上额外的分类属性也能为每一层级分别指定样式.
首先,一起来看看标记代码.原始的标记
嵌套,未指定样式的清单能为大纲之类的提供最基本的层级结构(当然也十分适用这个例子中的网站地图).由于使用了嵌套清单,因此我们能确信所有浏览器,设备都能正确显示它的结构,同时稍后也能轻易使用CSS指定样式.
小网站地图的标记代码也许像这样,三个顶层项目,还有几个嵌套项目.

<ul>
<li>Weblog</li>
<li>Articles
<ul>
<li>How to Beat the Red Sox</li>
<li>Pitching Past the 7th Inning
<ul>
<li>Part I</li>
<li>Part II</li>
</ul>
</li>
<li>Eighty-Five Years Isnt All That Long, Really</li>
</ul>
</li>
<li>About</li>
</ul>

图9-1是大多数浏览器显示这个例子的效果,你能发现,只要使用预设值,我们追求的结构就已大致成型.就算不指定样式,结构仍然十分明显,虽然他的确有点无聊,所以接着就开始加上一些CSS.

图9-1 尚未设定样式的嵌套状清单加上样式
假设我们想为网站地图的某一层加上一些样式定义,我们需要对标记代码新增一些东西,其实也就只是一个id,这样我们才能为这个清单指定与页面上其他部分的清单不同的样式,而不需要加上任何其他的标记内容.

<ul

id="sitemap"

>
<li>Weblog</li>
<li>Articles
<ul>
<li>How to Beat the Red Sox</li>
<li>Pitching Past the 7th Inning
<ul>
<li>Part I</li>
<li>Part II</li>
</ul>
</li>
<li>Eighty-Five Years Isnt All That Long, Really</li>
</ul>
</li>
<li>About</li>
</ul>

使用继承选择器,就能为清单每一层分别制定独特的样式.举例来说:如果想让最外层的字体方法,粗体,使用橘色,而内层逐渐缩小的话,可以先为整个清单指定大小,粗细和颜色.

#sitemap {
font-size: 140%;
font-weight: bold;
color: #f63;
}

这样会让整个清单变成大字,换成橘色粗体.接着为任一层嵌套结构内的<li>标签缩小字体,改变颜色.

#sitemap {
font-size: 140%;
font-weight: bold;
color: #f63;
}

#sitemap li ul {


font-size: 90%;


color: #000;


}


前面这段CSS会使所有顶层项目以大字,橘色粗体显示,而内层嵌套中的清单则是以黑色,90%字体(在这里是140%的90%)显示,结果见图9-2.

图9-2 为顶层清单项目指定样式
我们不需要为第三层指定更小的字体,因为他会自动使用90%的90%(有点让人困惑,但是真的能运作!)
现在清单的每一层有自动缩小的font-size了,接着加上一些圆点符号.自定义圆点符号
去掉预设的样式,并且使用background属性为第三层项目加上装饰性的圆点符号.首先为所有<li>标签去掉预设的清单样式,接着再为第三层项目指定内镜图片.为了进一步区别,也将为第三层设定font-weight:normal -- 覆盖掉清单的bold设定值.

#sitemap {
font-size: 140%;
font-weight: bold;
color: #f63;
}

#sitemap li {


list-style: none; /* turns off bullets */


}


#sitemap li ul {
font-size: 90%;
color: #000;
}

/* 第三层 */



#sitemap li ul li ul li {


font-weight: normal;


padding-left: 16px;


background: url(bullet.gif) no-repeat 0 50%;


}


图9-3是完成的网站地图,在第三层<li>标签上使用了自定义圆点符号,普通字体.在左边加上了16像素的内补丁,以便留下装饰用圆点图片的显示位置(同时也多留了一些空白).也告诉浏览器从左边0像素,上方50%开始显示图片,这基本上会使图片左侧对齐,并对齐文字中线.虽然我们能在此以像素指定垂直对齐,但是以百分比制定的话,在文字大小改变时,圆点图片仍能维持正确的排列效果.

图9-3 第三层项目加上自定义圆点小图片加上边框
接着在第二层清单的左边加上点状边框,完成我们的网站地图,这能进一步提示读者顶层项目有属于它的子项目.
为了只在第二层清单达成这个效果,将加上这些规则:

#sitemap {
font-size: 140%;
font-weight: bold;
color: #f63;
}
#sitemap li {
list-style: none; /* turns off bullets */
}
#sitemap li ul {

margin: 6px 15px;


padding: 0 15px;


font-size: 90%;
color: #000;

border-left: 1px dotted #999;


}
/* for third-level */

#sitemap li ul li ul {


border: none;


}


#sitemap li ul li ul li {
font-weight: normal;
padding-left: 16px;
background: url(bullet.gif) no-repeat 0 50%;
}

我们稍微调整了第二层的外补丁,并且加上了点状边线,在这个规则之后,再使用border:none;来去掉第三层的边框.
图9-4是改好字体,边框与图片的清单效果.

图9-4 完成的清单样式,第二层加上点状边线
在设计大纲之类的清单时,嵌套<ul>是个结构恰当,容易指定样式的解决方法.为顶层<ul>指定独特的id滞后,我们能把分别制定每层样式的任务交给CSS进行,而不需要加上多余的显示效果标签.而设计样式的可能性也远超出这个简单的示例.
图9-5是相同的CSS应用在稍大型网站地图上的效果,由于CSS根据层级指定样式,因此标签内容的写法完全相同,项目会随着嵌套状层级不同而自动选用适当的样式.

图9-5 以CSS与嵌套状清单制作的网站地图扩充版结论
在本章开头,我们探索了两个精简标签源代码的做法,一个是使用继承选择器,另一个是扔掉多余的<div>标签.
集成选择器不必使用多余,容易让标记源代码变得难以阅读的分类属性,同时移除直接内涵唯一性块级元素的<div>标签能让我们尽可能的节省字节,还能让构建复杂版面的源代码更加简单.
使用这些做法看起来只能省下几个字节,但是开始对整个网站应用这些做法之后,节省的成果就开始积累,你可以把它当成另一种编写灵活,结构化标记的好工具.
除了精简标签源代码外,我们还看了继承选择器如何为使用嵌套状清单的网站地图指定样式,你能为每一层级大纲指定独特的样式,而不必使用额外的分类属性,再次节省几个字节,同时让未来更新,重新设计样式的工作更加轻松.
精简标签代码万岁!
本书 "part I 从标记语法谈起" 全部结束了,希望这些简单的陈述,能带给你某些启发

标记语言——精简标签