34. 样式表单

Posted 12/15/2008 - 16:58 by Lewis

作者:Ben Henick · 2008年9月26日

引言

HTML表单一文中介绍了关于表单的创建和样式化的基础内容。本文从该文章停下的地方开始,提供了关于表单元素和样式的更多详细内容,以及在真实的web应用程序设计中表单是如何运用的。

点击此处可下载示例代码,这样你就可以在本机主机上进行练习了。此外,本文中还有许多链接,可以链接到实际运行的例子上。

本文目录如下:

本文中引入的概念

这一部分提供了关于表单实现和界面布局的新信息。

规则和标记超载

大量使用classid标记是违反KISS(保持简洁)准则的(在CSS盒模型与基础布局一文中已经解释过了)。然而,难度大的布局却经常会在级联上遇到很多冲突——这些冲突最简单的解决方法就是在元素中添加标记,以及编写包含若干选择符的样式表规则。

难度最大的布局中到处都是边缘情况,对这些边缘情况最好的处理办法就是给元素赋一个id,来定义一个狭义而唯一的环境。

新表单域元素

通常一个实际的表单所需要的不仅仅是按钮和文本输入区域,因为我们常常会需要按照选项来构建用户响应。HTML为有这种要求的设计人员提供了若干选项。

表单设计原则

对于网站来说,表单常常是用户交互和数据搜集的焦点所在。因此,表单对于一个网站的成功与否是非常关键的,这就要求我们对表单的设计给予高度的关注。

三分法则

最容易吸引网站用户的注意力的是浏览器画布(以及穿过布局的线条)上的四个特定点。本文将向你介绍这种现象,并提供一些建议,告诉你如何通过CSS来最大程度地利用这种现象。

Grids栅格

前面的文章中我们介绍了如何确保排版的一致性以及最大化地利用空白。本文中我们会更进一步地阐述如何利用em单位来实现一定程度的布局一致性,这种一致性只有通过CSS才能实现。

平台支持等级

商业项目中常见的一种要求是,一个被认可的网站设计应当在一种或多种浏览器上渲染效果一致。本文将会对这种要求的原因,效果,以及用于满足这种要求的处理方法进行简要的探讨。

一张简单的联系表单

通过联系表单,网站访客可以直接将e-mail发送到站内信箱中,联系表单的使用是非常普遍的,这是因为:只要用户具有激活的e-mail地址,他就可以使用联系表单,而且联系表单可以很方便地结合到专门的邮件文件夹中。

在前面的表单一文中,所涉及到的标记就是用来创建这样的表单的,我们还对这个表单进行了一些修饰:

标记


<form id="contactForm" method="post" action="/cgi-bin/service_email_script.php">
  <ul>
    <li id="nameField" class="required"><label for="realname">Name:</label><input type="text"
      name="name" value="" class="medium" id="realname" /><span
      class="note">required</span></li>

    <li id="addressField" class="required"><label for="address">Email:</label><input
      type="text" name="email" value="" class="medium" id="address" /><span 
      class="note">required</span></li>
    <li id="subjectField"><label for="natureOfInquiry">General
    subject:</label>

      <select name="subject" class="medium" id="natureOfInquiry">
        <option value="support">Support</option>
        <option value="billing">Accounts & billing</option>
        <option value="press">Press</option>

        <option value="other_q">Other questions</option>
      </select>
    </li>
    <li id="acctTypeField"><label for="acctNone">Account type:</label>

      <fieldset>
        <label for="acctGold">Gold</label><input type="radio" name="acct_type" id="goldAcct"
          class="rInput" />
        <label for="acctSilver">Silver</label><input type="radio" name="acct_type"
          id="acctSilver" class="rInput" />
        <label for="acctBronze">Bronze</label><input type="radio" name="acct_type"
          id="acctBronze" class="rInput" />

        <label for="acctNone">None</label><input type="radio" name="acct_type" id="acctNone"
          class="rInput" checked="checked" />
      </fieldset>
      <span class="note">required</span>
    </li>

    <li id="availabilityField">
      <label for="availability">My account is unavailable:</label><input type="checkbox"
        name="is_down" id="availability" class="rInput" /></li>
    <li id="messageField"><label for="messageBody">Comments:</label><textarea name="comments"
      cols="32" rows="8" class="long" id="messageBody"></textarea></li>

    <li class="submitField"><input type="submit" value="Send" class="submitButton" /></li>
  </ul>
</form>

由之前的表单变化而来

除了包含了几个新元素之外,这段标记之中还添加了许多class和ID,这些class和ID可以在样式表中加以引用。这样就可以对每个表单,表单域/值组,以及表单域分别加以引用,而不用管上下文。

此外,通过新的标志符,设计师就可以将必须填写的表单域和不是必填的表单域区分开来。

最后,这段代码中还有一些新的类,用来提示自身所在的表单元素应该显示的信息的数量和类型。通过这些类,就可以将布局细节同时应用到多个任意元素上。

显而易见的缺点

由于该示例表单只具备最基本的内容,我们用标题替换掉了之前文章的表单中的legend元素。

标签是最适合用在fieldset中的,而不是labellabel更多地是与单个控件相关)。在本例中我们完全忽略掉了legend元素,因为它很难样式化。

另外还需要注意的是,在源顺序中,表单域的“required”标签最好是放在表单域自身之前,以满足屏幕阅读器用户的需要。然而,为了对这些项目进行合理安排,position属性(不属于本文的讨论范围)是必需的。因此,“required”标签在源顺序中是放在其相关控件之后的(即使是在同一个上下文中)。

新表单域?什么东西?

文本框和提交控件在前面的文章中已经介绍过了。就如上面所说的,我们会遇到很多实际用例,在这些情况中要让用户能够选择两个或两个以上的选项。下面我们将简要地谈一下涉及这些操作的元素。

选择类型:input type="checkbox"

      …
      <label for="availability">My account is unavailable:</label><input type="checkbox"
        name="is_down" id="availability" class="rInput" />

选择加入或选择退出这类问题通常都是通过这些控件之一来实现的。此外,这类控件还可以用在需要从几若干选项中任选几种的时候,比如说,一张个人爱好清单。

在互斥选项中选择:input type="radio"

      …
      <label for="acctNone">Account type:</label>
      <fieldset>
        <label for="acctGold">Gold</label><input type="radio" name="acct_type" id="goldAcct"
          class="rInput" />
        <label for="acctSilver">Silver</label><input type="radio" name="acct_type"
          id="acctSilver" class="rInput" />

        <label for="acctBronze">Bronze</label><input type="radio" name="acct_type"
          id="acctBronze" class="rInput" />
        <label for="acctNone">None</label><input type="radio" name="acct_type" id="acctNone"
          class="rInput" checked="checked" />
      </fieldset>

通过一组单选框,你可以把若干选项排列在一起,在这些选项中只能选择一个。比如,在1-5或1-10的等级范围内指定一个数值,这个例子直观地阐述了radio控件的使用。

跟其它表单控件不同的是,radio控件不仅是允许,更是要求各个相互关联的控件的name相同。

这些元素的得名是来自于常见的机械式调音的汽车收音机界面。跟那些常见于数字调音收音机的由程序控制的预设不同,机械“预设”按钮只要一按下,就会从一系列波段中将收音机聚焦在要收听的那个波段上。

checkboxradio控件都有checked属性,只要设置了该属性,就会在初次渲染的时候默认激活该控件。

关于是用radio控件,还是checkbox控件的问题,最好是在考虑完各种不同因素后再作决定。如果你想让用户对一项主观性的选择(比如,加入邮件列表)进行确认,那么checkbox控件可能是最好的选择。如果你想让用户在两个客观性的选项(比如说性别)中做出选择的话,就应该用radio控件。

在选项太多的时候:select/option

    …
    <label for="natureOfInquiry">General
    subject:</label>
      <select name="subject" class="medium" id="natureOfInquiry">
        <option value="support">Support</option>
        <option value="billing">Accounts & billing</option>

        <option value="press">Press</option>
        <option value="other_q">Other questions</option>
      </select>

selectoption元素跟一系列radio控件的效果差不多,但占的空间却要少得多。是否用select元素来代替一堆radio控件,这通常是关系到如何使用用户界面空间的问题;对于电子商务网站里的一长串地理区域的列表或部门列表这样的内容,一般都是用select元素比较好,而简短的选项(比如,是/否,真/伪,年龄段,收入范围)则应该用radio控件来排列。

慎密的自测表明,操作select列表所需的运动控制水平是很高的,但随着其包含的option数量的增加,所需的控制水平的增长是很微小的。实际结果就是,简短的互斥选项列表最好是采用带有适当labelradio控件的形式。

将控件系列分组:fieldset

fieldset元素最重要的目的就是为一组紧密相关的控件划分一个单独的语境(比如将一组text控件归为电话号码,将select元素归为日期,等等。)。

从头开始,一步步制作出最终表单效果

既然本文所涉及到的新概念已经概述完了,现在我们就该来看一看实际的应用——下面的十二个示例全面包含了Web表单开发过程中遇到的各种设计概念和样式化问题。

强烈推荐读者将示例材料保存到自己的硬盘上,并对其中的样式表规则进行尝试。

这些示例按照源代码顺序逐渐深入,而不是按照样式表的制作顺序。之所以这样做的原因和含义将在本文后面部分进行讨论。

示例1

我们从html { margin: 0; padding: 0; }规则开始,第一步是对包含该表单的页面的body进行配置。

链接:

新样式:

body { 
  margin: 0;
  padding: 1.714em;
  background-image: url(images/bg_grid.gif);
  font-size: 14px;
  font-family: Helvetica,Arial,sans-serif;
  line-height: 1.714em;
}

示例1:背景考虑因素

  • 在XHTML与适当的Content-Type一起提交给能够对其进行正确支持的用户代理的情况下,默认的页面margin和/或padding是在html元素中渲染的。
  • 为了避免上一项中所描述的情况以外的其它情况,应该在该页面周围加上10px的空隙;Opera将这种空隙规定为padding值,而其它主流浏览器将它(有点违反直觉)规定为margin值。本示例中的样式表对最终效果进行了校正。
  • 虽然许多可访问性专家反对14px的字号,对在样式表中其它地方指定的各种边框和字体属性来说,这种字号却是不可分割的一部分,这些属性绝大部分都采用了1em的七分之几。本文末尾附有一张分数到小数的转换表,如果你想要更深入地了解本文中用到的运算的话,可以自行参考。
  • 之所以选择14px的值是因为,要使正文能够被几乎所有矫正视力的人阅读,14px是最小的字号。
  • 由于本文的目的之一是阐述如何实现一致性最好的栅格,本示例的页面采用了网格宽度为24px的栅格背景。

示例2

现在页面容器已经做好了,接下来的几个步骤就是改变或删除用户代理样式。

链接:

新样式:

h3 {
  margin: 0 0 1.2em 0;
  border-bottom: .05em solid rgb(0,96,192);
  font-size: 1.429em;
  line-height: 1.15em;
}

form {
  width: 35.929em;
  margin: 0;
}

ul {
  margin: 0;
  padding: 0;
  list-style-type: none;
}

示例2:背景考虑因素

  • 标题的字号系列因平台而异;然而,默认值始终是与未经样式处理过的段落文本上使用的medium值成比例的,并通过级联而继承。此处设置的值是为了改变默认的比例。
  • 对于页面上的第一个标题来说,用h1是最好的;但此处忽略了该规则,因为在商业环境下,网站的标题常常是页面上的h1,而页面标题在标题层级上就相对要低一些。在许多情况下,这种表单的重要性是与同一文档中其它内容或表单的重要性相同的。
  • h3进行样式化的目标是创建24像素高的内容框,下面要紧跟24像素的空隙,也就是:

    (((14 × 1.429) × 1.15) + (20 × .05)) ≈ 24
    
    14 * 1.429 ≈ 20; 20 * 1.15 == 23; 20 * .05 == 1;
    (20 × 1.2) = 24
  • 如果想对元素进行适当的对齐,而不用依赖定位的话,对form或列表项进行width赋值是必须的。此处设置的值会产生一个503像素的静态值;剩下的一个像素的差距(给定最小栅格单位24像素)是由于取整和反锯齿造成的误差。
  • 列表的默认用户代理样式因浏览器而异。IE为每个列表项设置了一个40像素的左边距,并将项目符号放在边距造成的空隙中,而其它的浏览器将表单内容区块作为一个整体,在其左侧应用填充距。与前面说到的改变body规则中的布局属性一样,此处的规则是特别设计来对跨浏览器的显示进行校正的。

示例3

……现在来为表单元素创建容器。

链接:

新样式:


li {
  clear: both;
  height: 1.714em;
  margin: 0;
}

fieldset {
  height: 1.429em;
  margin: 0 0 -.143em 0;
  border: 0;
}

示例3:背景考虑因素

  • 如果将表单看作是一系列的rowsem,那么对每一个rowsem的高度进行样式化以便维持栅格,这种需要就变得很明显了。为IE着想,也为了便于以后额外增添样式规则,我们将列表项的边距设为零。
  • 由于我们将对表单中的许多元素设置float值,因此这里将包含列表项设为clear: both,以确保每个列表项都会自然地降到前一个列表项之下。
  • 除了删掉了边框(边框是用户代理默认样式的一部分)之外,fieldset的布局属性似乎设置得很武断。事实上,这些属性是在跨浏览器测试之后才设置的,我们还会在示例11的注释中简短地讨论跨浏览器测试。
  • 现在,我们还没有设置displayfloat值,因此fieldset的内容与后面的select控件相冲突了。

创建栅格

良好的平面设计(随之而来的就是良好的界面设计)最大的优点之一就是元素是按照可预测的间距来铺设的。这些间距又称作栅格

上面已经说过,本示例中的最小栅格单元是24像素的正方形,但比起确保设计元素按照细小而可预测的间距来放置,保证布局的协调性所要考虑的事情更多。真正有效的栅格应当具备如下特性:

  • 整个文档每列之间的空白宽度都是按照一致的网格间距来排列的。
  • 同一文档中的顺序的部分与相邻列中的项目共有上边距。
  • 一个布局中的插图是按照与列和最小栅格间距的宽度有关的尺寸来裁切或铺设的。
  • 即便页面内容是一个单列,中间夹杂着float的元素,这种元素在大小和布局方面也是具有共同特征的。

明显具有这些特征的布局将会更富吸引力,而且更容易理解,因此也将有利于提高网站的可用性。

在布局中创建栅格框架

大多数专业人员用来创建站点布局构图的工具是Adobe Photoshop,它的优点之一就是能轻松使用网格线。为了在Photoshop中显示最小栅格,你可以选择View → Show → Grid,这样就能按照在Guides & Grid Preferences中设置的间距来显示网格了。

通过选择View → Rulers,切换到移动工具,将标尺上的指针往标尺外拖动,就可以对诸如列之类的东西添加定位标记了。

在样式表中实现栅格

正如所指出的那样——示例样式表中的一些规则强化了这个概念——在一个布局中实施最小栅格最好的方法是依靠em单位。然而,仅靠em是不够的;设计师在处理替换字号,空隙,以及边框时还必须保证分数到小数的转换正确。

在示例样式表中还展示了另一种实现栅格的技巧:使用与文档中各种元素和列的大小有关的class标记。如果保持这些标记的一致的话,大部分实施栅格的工作都可以通过它们来完成。

示例4

使元素对齐到栅格就是为标签和表单控件设置布局属性。

链接:

新样式:

label {
  display: block;
  float: left;
  clear: left;
  width: 10.286em;
  overflow: auto;
  padding-right: 1.714em;
  text-align: right;
}

input {
  height: 1.143em;
  border: .071em solid rgb(96,96,96);
  padding: .071em;
  line-height: 1;
}

示例4:背景考虑因素

  • 所有的表单控件,包括文本编辑区和标签,默认情况下都是作为%inline元素渲染的。
  • 为了创建一个对齐的左侧栏,需要给label元素设置width值;在“严格”渲染模式中,padding可以在控件和标签中制造出空隙。
  • 使标签和控件都排齐到一个共同的边距,可以使表单变得容易读懂。这一点将和其它布局要点一起作为三分法则讨论的一部分来进行探讨——见下文。
  • 现在,可以看出该表单存在着明显的问题:
    • 绑定到radiolabel标签都设置了跟表单中其它label同样的displayfloat值。在某些浏览器中,由于已有的heightoverflow值,这些元素会跟它后面的标签-控件组相冲突。
    • 在Safari 3浏览器中,本示例的文本控件的边框会消失。有人怀疑这是一个渲染漏洞。
    • radio控件现在按照它们的源顺序挤成了一堆;之所以出现这样的情况,是因为穿插在其间的label控件现在处在另一个布局环境中了。
  • 另一个需要注意的地方是,我们对标签设置了overflow: auto。我们用在这里的小技巧也可以这样描述:假设一个%block元素嵌套在另一个%block元素中,并假设这两个元素中只有一个元素的height是以静态单位em来设定的,而em单位对像素的换算是已知的,对另一个元素设置overflow: auto——就是没有设置height的元素——将会使其扩展到与那个设置了单独的height值的元素同一高度。这个技巧在示例11中也有用到。

三分法则

An early springtime scene on the north side of Pioneer Square, Portland, Oregon; superimposed with lines dividing the photo into nine more or less equal parts.

图1:俄勒冈州 Portland的早春景色。我们对这幅照片添加了线条,来阐释三分法则;注意看右下方的交叉点和形成该交叉点的线条是如何约束视觉活动的。照片作者版权所有,©2000。

在考虑如何实现优秀的布局的时候,有一个普遍存在的规律:如果你将布局或图片分成三部分,浏览者的注意力就会集中在分隔这些部分的线条(尤其是线条的交点)上。如果没有在设计中运用这个奇异的规律的话,你的布局就会显得不均衡。

对这种现象最简单的解释就是,这四条线与符合黄金比例的栅格非常接近,该比例的值接近六分之一。在各种数学领域和自然世界中经常可以遇到黄金比例的例子。

A screen capture of msnbc.msn.com with the first seven golden rectangles superimposed on the layout.

图2:msnbc.msn.com的屏幕截图,上面加上了七个金色的矩形。挨在一起的第四和第五个矩形整体说明了页面布局栅格的本质。

该示例表单的布局中,表单控件都对齐到一个左边缘,这个左边缘位于从左边到假想的表单右边缘的整个距离的三分之一处,这是经过慎重考虑后出的选择。而表单的垂直布局就更是如此了——将标题考虑在内,文本区域正符合前面所说的那两条规律。就算不将标题考虑在内,必填的表单域也符合最重要的那条规律。

对于设计师来说最重要的一点就是,如果在样式表设计一开始的时候就将三分法则和栅格纳入考虑范围的话,样式表的规范化工作就会大大简化。

示例5

为了在水平和垂直方向上维持我们想要的栅格,还需要做一些细节调整。这些调整几乎完全是装饰性的。

链接:

新样式:

textarea {
  height: 4.714em;
  margin-bottom: .286em;
  border: .071em solid rgb(96,96,96);
  padding: 0;
}

select {
  display: block;
  float: left;
  height: 1.571em;
  font-family: Futura,'Century Gothic',sans-serif;
}

option { font-size: 100%; }

示例5:背景考虑因素

  • 在Windows平台下,可以对select控件进行修改,以避免倒角效果,因为倒角效果会让它们看起来与文本控件很相似。
  • 一般的提高表单的易用性的方法是,提供一种方式,使用户能一眼就从表单的各个部分中认出他们的输入区域在哪里,因此表单输入区域的字样应该跟其它部分的字样不同。考虑到这一点,本示例保持文本输入区的字体不变,而改变了其它部分的字体。
  • 在对表单中的文本进行渲染的时候,级联会被忽略,这就是为什么这里的样式表中会有那么显眼的一大串文本/字体值的另一个原因。之所以避免用inherit,完全是出于个人喜好和习惯,而不是为了什么客观的目的。

示例6

前一个示例对字体渲染进行了一些调整;现在我们接着来完成这个工作。

链接:

新样式:

input, textarea {
  display: block;
  float: left;
  overflow: hidden;
  font-family: Futura,'Century Gothic',sans-serif;
  font-size: 1em;
}

input, textarea, select {
  margin-top: 0;
  font-size: 100%;
}

示例6:背景考虑因素

  • 在本示例中,我们可以看到本文中第一次出现的通过复合选择符同时赋值的例子,这些值就是专门留到现在来演示复合选择符同时赋值的。这些规则中没有border值,这是我们在制作过程中特意这么做的,这个表单的实际制作过程跟这些示例的出场顺序不一样——我们后面会详细讨论这一点。
  • 就像上面提到的,表单中的文本和字体值都不会受到级联的影响。上述规则对这个问题进行了处理。因此,现在大多数的表单控件的布局都符合我们的要求了。
  • 出于对IE6的考虑,表单控件的协调是通过将它们的float值设为left而实现的。之所以设置这些值,是出于本人的习惯,这些习惯是由一些(不愉快的)经历所造成的,但这些设置不是必须要用的。
  • 通过对文本控件指定block值,前两个示例中出现的Safari浏览器的渲染问题一下子就被解决掉了。像这样的怪异问题在对表单进行样式化的时候是很常见的。
  • 正如还没有对border值进行适当的校正一样,font-size值也还没有校正;为文本控件设置的1em值,还有为select控件设置的100%值,都是完全出于主观的。

示例7

我们需要将各个文本控件的宽度改变一下,不让它们跟默认值相等。

链接:

新样式:

.medium { width: 11.714em; }

select.medium { width: 12em; }

.long { width: 20.429em; }

.rInput { border: 0; }

示例7:背景考虑因素

  • 重新检查一下标记源代码,你就会发现每个控件都带有一个class——上面的规则中,三个与宽度相关的规则之中有一个是针对文本和控件的,其它的类是针对那些依靠指针/光标输入,而不是依靠键盘输入的控件的。
  • 之所以要为控件设置Class,最大的原因在于IE对高级选择符的支持很有限。使用选择符的时候,rInput class可以很方便地用input[type="radio"], input[type="checkbox"]…来代替,如果当前版本的IE并不支持后面这种表达方式的话。
  • 对三个文本控件的可能值的设置是完全随意的,可以由设计员自行决定。在商业环境中,有些设计员提交的设计在布局方面非常特殊,以至于在这里用到的那些class选择符可能在功能上完全无效。通过对每个标签/控件组合设置一个id,就可以为这个表单中的每个元素提供最简单的引用方式——对那些坚持要全面操控网站布局的方方面面的设计员来说,这对样式化他们自己的设计是很有用的。

示例8

我们这个表单的提交按钮等候处理已经等了很久了……

链接:

新样式:

.submitButton {
  display: block;
  clear: both;
  width: 7.2em;
  height: 2em;
  margin: 0 0 0 16.8em;
  border: 1px solid rgb(128,128,128);
  padding: 0;
  font-size: 10px;
  text-align: center;
}

示例8:背景考虑因素

  • 在对提交按钮进行样式化的时候所面对的最大问题就是如何让它们精确地排列成我们想要的效果。在常见的做法中,只有通过多次对布局和line-height属性进行微调,才能实现想要的外观效果;一些开发人员可能会觉得用图像替代(参见参考书目)或input type="image"要更节省时间一些。
  • 乍一看,对提交按钮设置display: block有点多余——确实也是如此,如果我们仅仅只考虑单个页面上的单张表单的话。然而,在整个网站中,这种设置可能就不是多余的了;许多网站和应用程序在同一份文档中会有多个表单,而且其display值各不相同。

示例9

把“required”标签放到它该去的地方。

链接:

新样式:

li.required span.note {
  display: block;
  width: auto;
  float: right;
  color: rgb(128,128,128);
  font-size: .714em;
  line-height: 2.4em;
  font-style: italic;
}

示例9:背景考虑因素

  • 在当前状态下,包含radio控件的fieldset仍然是区块元素,所以它一直伸展到表单的右边距处。因此,与该控件集相关的标签被往下推到该fieldset的底部去了。
  • 我们将“required”标签的width值设置成了auto,从而规定了这些标签的宽度不能超过自身内容的宽度。
  • 仔细看看“required”标签的排版所用到的运算的话,就会发现一个10像素的字号设置,以及24像素的行间距(等于我们所用到的栅格的最小单元)。
  • 用来指示必填区域的结构是出于用户交互性的考虑而创建的;通过在该表单中应用的若干类,我们就可以用JavaScript来使用户输入生效,还可以对那些用户不能正确使用的标示,区域,和/或标示/控件集上的标签的式样进行修改。

示例10

终于该来解决radio控件的冲突问题了,也就是说这些控件跟源顺序中位于它们之下的表单域之间的冲突问题。

链接:

新样式:

fieldset label {
  margin-right: .25em;
  padding-right: 0;
  line-height: 1;
}

fieldset .rInput { margin-right: .75em; }

fieldset label, fieldset .rInput {
  width: auto;
  display: inline;
  float: none;
  font-size: .857em;
}

li.required fieldset {
  width: 18.857em;
  float: left;
}

示例10:背景考虑因素

  • 上述规则的主要效果除了进行装饰性的调整之外,还有将radiocheckbox控件的display值改回inline。这样做的目的是为了避免这些控件像表单中其余的input元素一样浮动而带来的麻烦。
  • 尽管我们为这些相关联的控件设置了display: inline,它们仍然还是“被替换的”元素:在启动时(比如说,在浏览器实际开始对内容进行渲染之前)具有已知的静态尺寸的内联元素。因此我们可以对这些元素应用边距。
  • fieldset元素的特殊性质——也就是,它们是专门用在表单中的唯一的%block元素——规定了所有的包含了用户必须填写的控件的fieldset必须应用单独的宽度值。(参见上面的对“required”标签布局属性值的讨论)。

示例11

我们来做最后一步,将剩下的一点小小的参差对齐,让整个表单井井有条…

链接:

新样式:

#acctTypeField fieldset {
  padding: .286em 0 0 0;
  line-height: normal;
}

#acctTypeField .rInput { margin-top: .167em; }

#availabilityField label {
  height: 3.143em;
  padding-top: .286em;
  line-height: normal;
}

#availabilityField .rInput { margin-top: .286em; }

#availabilityField, #messageField {
  height: 1%;
  overflow: auto;
}

示例11:背景考虑因素

  • 在示例4里面用到过的overflow的小技巧在这里又出现了;我们对#availabilityFieldlabelheight设置了一个具体数值,而#messageField中的textarea也是这样。
  • 为了改变其所包含的fieldsetpadding值,我们用到了#acctTypeField标记,这种方法很可能是太不灵活了。然而,在编写某些非常容易受到相邻元素样式规则的影响的样式规则时,进行一些微妙的处理是必需的。
  • 在这个样式表代码块中的其它规则都是对布局做微细调整用的,所有这些规则都是在测试的过程中确定的。可惜的是,长达数小时的测试和微调却没能找到在Safari 3和Firefox 3浏览器中对radio控件实现同样的排版的方法。其结果只是为Firefox3下不协调的radio控件的label添加了一条基线。总的来说,对checkboxradio控件进行样式化在某种意义上可以说是一种黑色艺术。

示例12

前面所有的样式规则都是针对Opera或Safari的(随你挑,这两种浏览器都表现得相当好)。下面的这些样式规则是专门针对IE的,我们通过CSS文件中的link条件注释代码块来指定它只针对IE。

链接:

新样式:

h3 { margin-bottom: 1.2em; }
li { margin: 0 0 -.214em 0; }

select { height: 1.429em; }

textarea { height: 4.571em; }

fieldset {
  height: 1.583em;
  padding-top: .417em;
}

.medium { width: 13.429em; }

select.medium { width: 13.714em; }

.long { width: 20.286em; }

fieldset .rInput { border: 0 !important; }

#subjectField { margin-bottom: -.214em; }

#availabilityField .rInput { margin-top: .286em; }

#messageField { padding-bottom: .286em; }

input.submitButton { margin-top: .15em; }

* html input, * html textarea { float: left; }

* html select { font-size: .643em; }

* html select.medium { width: 21.364em; }

* html textarea { height: 4.643em; }

* html #subjectField {
  margin-top: .071em;
  margin-bottom: 0;
}

* html #availabilityField label { padding-top: 0; }

* html input.submitButton { margin: .1em 0 0 7em; }

示例12:背景考虑因素

  • 如你所见,上面的所有样式规则都说明了IE中字号和布局盒模型的级联方式与其它浏览器有着些微不同。
  • 另一个值得一提的事情就是* html选择符。只有IE5和IE6能识别这种选择符,因此对于专门针对这两种浏览器的样式表规则来说,这个选择符是很有效的低通过滤器。

建立平台支持等级

本文示例的最后一部分展示了单独为IE6和IE7编写的样式表,而尽职的网站设计团队如何针对各种不同的浏览器进行处理,还需要更多的讨论。

Web的现实情况是,用户们在形形色色的环境下使用着五花八门的浏览器。有的浏览器是老式的,而有的却是最前沿的。有的浏览器是在配置齐全的计算机上运行的,而有的却是在电话之类的移动设备上运行。所有浏览器都是在特定的操作系统上开发的,然后再移植到其它的标准支持程度不同的操作系统上去。除了Opera,所有的浏览器发行商所发布的浏览器都被设计成要跟一系列产品中的其它类型的产品搭配使用——这种设计要求增加了这些浏览器的复杂度,而这种复杂度对于浏览网页这样的简单任务来说是不必要的。

多种多样的浏览器优缺点已经够设计员们琢磨的了,然而现实中却还存在着漏洞的问题——安全漏洞,组件漏洞,尤其是还有渲染漏洞。Safari 3.x的用户们发现,这些演示文档揭示出他们自己的浏览器在某些地方存在着令人郁闷的渲染漏洞。

解决这些问题最好的办法就是定义支持等级。这种做法,又叫做“分等级浏览器支持”,最先是由Yahoo!的界面开发团队宣传开来的。

大体上说来,支持等级分成四个大类:

  1. 在浏览器的性能范围之内,网站的渲染与原本的布局一致,而且其所有站点特性都是完全支持的。这种开发平台的定义有时又叫做“A+”等级。
  2. 网页显示明显偏离了原来的布局,甚至可能偏离程度非常显著;不过,网站仍然是可用的,而且即使不是全部特性都得到支持,大多数的站点特性是得到了支持的。
  3. 对使用这一等级的浏览器的用户来说,网站勉强可以使用,不至于砸了网站所有者的招牌,而且站点特性完全不可用。这一等级的浏览器的安装基础相当小,而且被认为是过时的。
  4. 文件说明书中将这一级别称作“X 等级”支持,这一级别的支持是专供那些未经测试的平台之用的——最具代表性的就是新出现的安装基础很小的浏览器(当然了,在大多数情况下是Opera)。一旦通过测试,这类的浏览器就会升入更高的等级。

至于形成该支持等级定义的要求收集过程以及将浏览器归类至各个等级之下的详情,实在是又长又乏味,由于本文已经够长了,这些内容就略去不谈了。

实际中(…而不是理论)的复杂表单布局

在上述的背景说明中,我们将示例的出场顺序按照样式表源顺序来安排,而不是按照样式表中实际的规则添加顺序来安排。之所以这么做,原因包括:

  • 为了显示出基于时序的演示系列,记日志是必需的(或者将样式表储存在版本划分系统中)——这个措施从来没有被执行过。等到疏忽被觉察到的时候,本文已经走得太远了,早就不能再修改了。
  • 按照源顺序来安排,大大方便了演示文档的制作——这是理想和现实之间的又一个妥协。
  • 由于原来的示例样式表在编写的同时对规范化和源顺序给予了相当多(如果不是完全的话)的关注——就像所有样式表所应该的那样——按照源顺序来组织示例能保证那些希望“查看来源”的学生们在弄明白到底在实现些什么效果的时候可以轻松得多。

Opera 9.6 的 OS X版是开发用的用户代理;除了这个附加说明和在上面提到过的其它说明之外,下面是对该样式表进行修改和增添的一般顺序:

  1. 文档(比如,body)样式的应用
  2. 列表,表单,以及fieldset默认值的重设
  3. 排版的指定
  4. 列表项的约束和clear
  5. label的整体安排
  6. 表单控件布局(尤其是大小)的指定和规范化
  7. 提交按钮的布局
  8. 边缘情况的应用
  9. Safari和Firefox的测试以及样式表值的修改,以达到折衷(在可能范围内)
  10. IE6和IE7的测试,以及条件样式表中属性/值的调整

上述的过程以最宽泛的规则开始,逐渐变得越来越具特异性,直到个别浏览器的特定缺陷被囊括其中……与样式表自身的源顺序非常相似。然而,它们的结果并不完全相关。这是因为,浏览器渲染引擎的多样性以及像float语境之类的东西的特性,在混合进多种样式的时候导致了不可意料的结果,因此实际的处理比起折返,调整,以及再考虑要更复杂。

总结

本文提供了一个关于表单样式化和布局的构思慎密的基础,但在此基础之上还可以进行更加深入的研究。如果设计师需要创建一个向标准靠拢的web表单,由操作系统(创建Web表单控件时借用了其组件)造成的麻烦,以及浏览器渲染引擎之间的差异会使得摆在他面前的任务更具有挑战性。本文对那些有关于这种任务的浏览器缺陷进行了初步的实验,并说明了如何达到对web开发中较难的一个方面的熟练掌握。

练习题

  • 接受用户输入的表单控件的浮动类型是什么,是哪两个特征使得它们对于布局来说非常重要?
  • 除了valuedisabled之外,还有哪两个属性可以在用户交互之前控制表单控件设置,它们是用在哪些元素上的?
  • 本文的演示文档规定了必填的表单域。写出至少一条样式规则,可以用来对含有用户输入错误或疏漏的表单域的外观进行一次改变。
  • 分别描述出select元素,checkbox控件和radio控件的使用案例。说明你的选择与其它可能的选择相比有哪些优点。
  • 从你的指导者所选中的在线咨询网站中,找出并简短描述input type="submit"的替代方式。
  • 通过追加select属性/值组来创建一个允许选择多个optionmultiple="multiple"元素。对该元素的行为方式进行检查之后,说明为什么在网站创建过程中很少用到它。

表:分数对小数转换表

在下面的表格中,括号内加了星号的数字表示它们是无限循环小数;比如0.2(6*)就等于0.266666666666666…(6是无限循环的)。

因为表格是从左到右阅读的,表格的左边是最接近于零的数值,并且越往右越大。

x 1/x 2/x 3/x 4/x 5/x 6/x 7/x 8/x 9/x 10/x 11/x 12/x 13/x 14/x 15/x
2 .5 - - - - - - - - - - - - - -
3 .(3*) .(6*) - - - - - - - - - - - - -
4 .25 .5 .75 - - - - - - - - - - - -
5 .2 .4 .6 .8 - - - - - - - - - - -
6 .1(6*) .(3*) .5 .(6*) .8(3*) - - - - - - - - - -
7 .(142857*) .(285714*) .(428571*) .(571428*) .(714285*) .(857142*) - - - - - - - - -
8 .125 .25 .375 .5 .625 .75 .875 - - - - - - - -
9 .(1*) .(2*) .(3*) .(4*) .(5*) .(6*) .(7*) .(8*) - - - - - - -
10 .1 .2 .3 .4 .5 .6 .7 .8 .9 - - - - - -
11 .(09*) .(18*) .(27*) .(36*) .(45*) .(54*) .(63*) .(72*) .(81*) .(90*) - - - - -
12 .08(3*) .1(6*) .25 .(3*) .41(6*) .5 .58(3*) .(6*) .75 .8(3*) .91(6*) - - - -
13 .(076923*) .(153846*) .(230769*) .(307692*) .(384615*) .(461538*) .(538461*) .(615383*) .(692307*) .(769230*) .(846153*) .(923076*) - - -
14 .0(714285*) .(142857*) .2(142857*) .(285714*) .3(571428*) .(428571*) .5 .5(714285*) .6(428571*) .(714285*) .7(857142*) .(857142*) .9(285714*) - -
15 .0(6*) .1(3*) .2 .2(6*) .(3*) .4 .4(6*) .5(3*) .6 .(6*) .7(3*) 8 .8(6*) .9(3*) -
16 .0625 .125 .1875 .25 .3125 .375 .4375 .5 .5625 .625 .6875 .75 .8125 .875 .9375

参考书目

作者简介

Picture of the article author Ben Henick

Ben Henick 从1995年9月就开始以各种身份参与创建网站了,那时他以一个学术志愿者的身份进行了他的第一个 Web 项目。从那时开始,他的大多数工作都是以自由工作者的形式完成的。

Ben是一个多面手。他的技能触及了网站设计和开发的几乎每一个方面,从 CSS 到 HTML,再到设计和文案撰写,再到 PHP/MySQL 和 JavaScript/Ajax。

他生活在堪萨斯州的 Lawrence,有三台电脑,却没有电视机。你可以在 henick.net上 读到更多关于他和他工作的内容。