CSS实务排版技巧、秘诀与技术

自从网页标准计划 (The Web Standards Project) 提出浏览器升级方案 (Browser Upgrade Initiative) 后,无数的网站设计师开始采用较为符合标准的网站设计方式:他们用 CSS 来设计版面,以取代传统使用的表格。

"表格已死......"

有些设计师在 Jeffrey Zeldman 的指导下,用撰写教学文件的方式帮助我们解决第一道难题 – 不使用表格,网页会缺乏设计感。起初他们的重心放在撰写几篇以 CSS 的定位能力取代表格的专栏:如此一来,网站设计师就能把网页的架构与内容完整地分离。在 Eric Costello 的 glish 网站及 Rob Chandanais 的 Blue Robot 网站都有许多相关的技术文件。

许多人也一起参与,包括制作 Box lesson 的 Owen Briggs,以及撰写相关讨论的 Eric CostelloTantek ÇelikDotfile、Web Nouveau (译注:已经无法连结) 列举了数百个利用 CSS 设计版面的网站。

"......表格长存"

当大家可以利用这些资源,只靠着 CSS 的定位能力来设计一般性版面时,我们这些设计师却发现有某些实作上的问题,可以用表格轻易解决,而使用 CSS 时则会遇到一些麻烦。像这样的问题都会以 "Tables are dead ... long live tables." 这个标题发表在 Webdesign-L 网站上。

问题

假设你要将一堆缩图连结到较大尺寸的版本 – 这种网页相当常见。除此之外,你希望每张缩图的正下方都有个简短的标题。接着,为了有效利用浏览器窗口的空间,你希望让缩图跟标题成对地排成一列,并会随浏览器窗口宽度自动分行 (wrap,即流动式设计)。随着最后一个要求,我们放弃表格,进入了 CSS 的王国。

一步步来

让我们一步步来。第一个要求是缩图的正下方要有个标题。作法相当直接了当:在你的 HTML 里放上图片,接着一个断行 (BR),再把标题放在一个段落 (P) 里并且置中 (利用 CSS)。

接着我们要让这些缩图跟标题成对地排列在浏览器窗口里。使用表格排版时,这一对对的缩图跟标题会被分别放置在 TD 里。在使用 CSS 排版时,我们要把它们分别放置在 DIV 里。为了让它们能水平排列在窗口上,我们用 CSS 让这些 DIV 往左浮动 (FLOAT)。

这时候 CSS 看起来应该像这样:

div.float {
  float: left;
  }
  
div.float p {
   text-align: center;
   }

而 HTML:

<div class="float">
  <img src="image1.gif" width="100" height="100"
  alt="图 1" /><br />
  <p>标题 1</p>
</div>

<div class="float">
  <img src="image2.gif" width="100" height="100"
  alt="图 2" /><br />
  <p>标题 2</p>
</div>

<div class="float">
  <img src="image3.gif" width="100" height="100"
  alt="图 3" /><br />
  <p>标题 3</p>
</div>

而在浏览器里应该会看到:

图 1

标题 1

图 2

标题 2

图 3

标题 3

 

下一个要求得靠 CSS 解决。我们要让图片跟标题成对地自动换行,以配合浏览窗口的宽度。让 DIV 往左浮动 (FLOAT) 已经解决了这个问题。只要我们多放几张缩图,它们就会在浏览窗口里自动换行 (只要改变浏览窗口的宽度,你就可以看到流动式设计的作用):

图 1

标题 1

图 2

标题 2

图 3

标题 3

图 1

标题 1

图 2

标题 2

图 3

标题 3


现在假设你希望同时在网页上显示好几类的缩图,并利用背景颜色或边界等外观条件帮它们分组。这时候只要用一个容器 (container) DIV 把它们包在一起就好:

div.container {
  border: 2px dashed #333;
  background-color: #ffe;
  }

但这时候麻烦来了。当你在 CSS 里将一个组件浮动 (FLOAT) 以后,它就不再占据任何 "空间",因此背景及边界都会在图片的正下方出现,而不是绕着图片。所以我们必须在容器 DIV 里多放点东西,比方说一个间隔 (spacer) DIV:

div.spacer {
  clear: both;
  }

其次是 HTML (注意在容器 DIV 的上下方都有个间隔 DIV):

<div class="container">
<div class="spacer">
  &nbsp;
</div>

<div class="float">
  <img src="image1.gif" width="100" height="100"
  alt="图 1" /><br />
  <p>标题 1</p>
</div>

<div class="float">
  <img src="image2.gif" width="100" height="100"
  alt="图 2" /><br />
  <p>标题 2</p>
</div>

<div class="float">
  <img src="image3.gif" width="100" height="100"
  alt="图 3" /><br />
  <p>标题 3</p>
</div>

<div class="spacer">
  &nbsp;
</div>

</div>

结果如下:

图 1

标题 1

图 2

标题 2

图 3

标题 3

根据 sam marshall 的原始码制作。

巢状 DIV 与巢状 TABLE 有什么不一样?

好吧,我们有了一堆的巢状 (nested) DIV,这比巢状表格好在哪里?答案是在于这些卷标的设计观点上。DIV 暗示着一种逻辑或结构上的分组,即使它们以巢状表示,仍然具有标记的结构性。在我们的例子里,我们把缩图跟它们的标题分成一组 (第一层),再将这些成对的缩图跟标题依照相似性分组 (第二层)。这些都是利用 DIV 卷标把结构上的分组处理得相当好的范例。

然而表格暗示的是一种行与列的标头 (header) 跟每个字段资料的关系。当我们利用表格设计版面时,我们就丧失了表格结构的意义。让我们回过头来用 HTML 设计版面,巢状表格只会让问题复杂化。

窗体功能

另一个常见的表格排版应用是排列窗体 (FORM) 里的组件与描述。关于这是不是表格的合适应用尚有很多争论,而就像我们即将看到的,CSS 技术对类似的排版需求也很有用。

一个典型的窗体版面里,在左方的是描述,紧靠着右边界,在右方的是组件,紧靠着左边界。一切事物都在中央交会:

姓名:
年龄:
鞋子尺寸:
附注:
 

根据 Eric Meyer 的原始码设计概念制作。

上面这个窗体没有使用到表格。我们又再度使用到浮动 (FLOAT) 来达成定位的工作。戏法是这样的:我们用一个 DIV 模仿表格的列。然后我们创造两个 SPAN,一个给描述、另一个给组件。把描述的 SPAN 往左浮动,组件的 SPAN 往右浮动。让描述 SPAN 里的文字往右靠,让组件 SPAN 里的文字往左靠。

所以 CSS 应该长这样:

div.row {
  clear: both;
  padding-top: 10px;
  }

div.row span.label {
  float: left;
  width: 100px;
  text-align: right;
  }

div.row span.formw {
  float: right;
  width: 235px;
  text-align: left;
  } 

上面的 CSS 也设了 SPAN 的宽度。宽度可以像是范例里的绝对值,或者也可以用百分比表示。百分比最多是到 100% 或少一点点,依照你设的留白跟边界而定 (还有你设计的容器)。在范例里我用另一个 DIV 把窗体包起来,以设定边界与背景。

范例 HTML:

<div style="width: 350px; background-color: #cc9;
border: 1px dotted #333; padding: 5px;
margin: 0px auto";>
  <form>
    <div class="row">
      <span class="label">姓名:</span><span
class="formw"><input type="text" size="25" /></span>
    </div>
    <div class="row">
      <span class="label">年龄:</span><span
class="formw"><input type="text" size="25" /></span>
    </div>
    <div class="row">
      <span class="label">鞋子尺寸:</span><span
class="formw"><input type="text" size="25" /></span>
    </div>
    <div class="row">
      <span class="label">附注:</span><span
class="formw">
        <textarea cols="25" rows="8">
        快! 来写点东西......
        </textarea>
      </span>
    </div>
  <div class="spacer">
  &nbsp;
  </div>
 </form>

</div>

追求卓越

你也许会注意到,上面容器 DIV 的 STYLE 里有一个属性:margin: 0px auto;。在符合标准的浏览器里,它会让 DIV 往中间对齐。一些浏览器 (如 Windows 底下的 IE5.x) 会忽略这一点,却会错误地让有 text-align: center 的 DIV 往中间对齐。想让 DIV 在这些浏览器往中间对齐的话,你可以用有 text-align: center 的 DIV 把另一个有 margin: 0px auto; 的 DIV 包起来 (里面的 TEXT-ALIGN 是 left,所以文字会正常排列)。详见 Rob Chandanais 在 Layout Reservoir 网站撰写的置中对齐技术(1, 2)。

分隔差异

在处理本质上相对的事物时,也常会用到与前面类似的表格排版设计。这次你不是让它们在中央交会,而是让两个组件摆在浏览器窗口的两侧。这也许是一个你想让商标放在页面右上角,而让导览组件放在页面左上角的案例:

首页 > 产品[商标]

在这里我们使用跟窗体范例里一样的 DIV.ROW,但这次会使用不同的 SPAN。左边的 SPAN 往左浮动,而且文字往左靠。右边的 SPAN 往右浮动,而且文字往右靠。

CSS:

div.row span.left {
  float: left;
  text-align: left;
  font-weight: bold;
  color: #fff;
  width: 49%;
  }

div.row span.right {
  float: right;
  text-align: right;
  font-weight: bold;
  color: #fff;
  width: 49%;
  }

HTML:

<div style= "width: 90%; background-color: #666;
border: 1px solid #333; padding: 0px; margin: 0px auto;">
<div class="spacer"></div>

<div class="row"><span class="left">
首页 > 产品</span>
<span class="right">
[商标]</span></div>

<div class="spacer"></div>

</div>

CSS 求助

ACRONYM 与 ABBR 卷标虽然只在少数情况派上用场,却有不错的实用价值,可以配合着 TITLE 属性来解释头字语或缩写。但即使网页有提供文字来协助网站参观者了解缩写或头字语的意义,现在大部分的浏览器不会为这个卷标作出任何的警示。所以让我们从 CSS 来着手。

你可以在样式表里为这些卷标加上底线,让它们能引起注意。透过浏览器的支持,你也可以用 CSS 把光标换成 "求助" 符号 (通常用问号表示)。当然你也可以不用被 HTML 卷标限制。创造一个叫 .help 的类别,再用 SPAN 来为那些容易让读者混淆的字词添加信息。

CSS 范例:

abbr, acronym, .help {
  border-bottom: 1px dotted #333;
  cursor: help;
  }

这个 CSS 配合缩写或头字语卷标的 TITLE 属性使用,可以产生跟超级链接不一样的底线效果。把光标改成 "求助" 暗示着这些文字是不能按的,而 TITLE 属性则会解释缩写或头字语。我最早是在 Sander Tekelenburg 的网站上看到这种做法。

请三思而后行......

我最先是在 Bos 跟 Lie 的 Cascading Style Sheets 读到关于将串行 (LIST) 改成行内 (inline) 显示的文章。后来我在 Christopher Schmitt 的 BabbleList 网站率先看到了这个技巧的实际应用。这个戏法让串行水平地显示在一行里;也就是说从:

转换成:

如果加上些留白跟边界的效果:

CSS:

li.inline {
  display: inline;
  padding-left: 3px;
  padding-right: 7px;
  border-right: 1px dotted #066;
  }

li.last {
  display: inline;
  padding-left: 3px;
  padding-right: 3px;
  border-right: 0px;
  } 

HTML:

<ul>
<li class="inline">项目一</li>

<li class="inline">项目二</li>

<li class="last">项目三</li>
</ul> 

结束了?或只是刚刚开始......

我希望藉由分享这些技巧、戏法与技术,刺激你在网站上使用更多 CSS 排版技巧,并且继续获得及分享新的技巧、戏法与技术。

—Mark Newhouse

作者

Mark Newhouse国家天文台的网站设计师,他正慢慢地把网站改成 CSS 为基础的设计。