互动性一直是互联网的重点,让使用者与网站能够交换信息,彼此沟通.表单使我们能够有组织的,使用同一方式的从使用者那里收集资料,因此在设计网站时总是属于"任何状况都能拿来用"的那一类,举例来说,我们发现大概有10000种标记表单的不同方式.好吧,或许没有那么多,但是我们仍能思考几种状况,让使用者易于使用表单结构,同时也便于让网站所有者进行管理。
记表单的方法
方法A:使用表格
<form action="/path/to/script" method="post">
<table> <tr> <th>Name:</th> <td><input type="text" name="name" /></td> </tr> <tr> <th>Email:</th> <td><input type="text" name="email" /></td> </tr> <tr> <th> </th> <td><input type="submit" value="submit" /></td> </tr> </table> </form> |
长久以来许多人都以表格来标记表单,由于使用频率很高的缘故,我们已经习惯于见到表单以这种方式进行排版:左列是向右对齐的文字说明,右列则是相左对齐的表单元素.使用单纯的两列表格,是完成易用表单排版的简单方法之一.
有些人认为不需要表格,也有其他人认为应该把表单视为表状资料.我们不打算支持任何一种说法,但是在某些情况下,使用表格时达成特定表单排版的最佳方法,特别是包含许多种不同元素的复杂表单(使用了单选框,下拉选框等等的表单).完全依赖CSS处理这种表单的排版可能会让人感到挫折,而且经常需要加上额外的<span>与<div>,会比表格耗上更多的标签.
接着看图5-1,这是一般可视化浏览器显示方法A的效果:
图5-1:浏览器显示的方法A的效果
你会发现,使用表格可以把文字说明表单元素排列的十分整齐.然而,对这样简单的表单来说,或许我会避免选择使用表格,并且换用其他不需要使用这么多标签的方法.除非表单的视觉设计十分需要这种排版,否者未必需要使用表格.同时我们也要考虑几个易用性问题,在研究下面两个方法的时候,我们就会接触到这个部分.
方法B:不用表格,但挤在一起
<form action="/path/to/script" method="post">
<p> Name: <input type="text" name="name" /><br /> Email: <input type="text" name="email" /><br /> <input type="submit" value="submit" /> </p> </form> |
使用单一段落和几个<br />标签隔开所有元素是个可行方法,但视觉上可能会被描绘的有点挤.图5-2十一版浏览器的显示效果:
图5-2:浏览器显示方法B的效果
虽然我们不用表格就能完成排版,但是它看起来有点挤,有点丑.同时我们也遇上表单元素无法完美对齐的问题.
我们能够以CSS为<input>元素加上一个外补丁,以便减轻拥挤的感觉.像是这样:
input{
margin:6px 0; } |
前面这段为每个<input>元素的上下分别加上6像素的外补丁(包含了Name,Email的输入框,以及submit按钮),在元素之间加上额外的空间.就像图5-3一样:
图5-3.方法B在为input元素加上外补丁之后的效果
方法B本身没什么大问题,但是还能进行一些微调,以便把表单做得更好.方法C里头也运用了这些微调技巧,所以一起来看看吧.
方法C:朴素,更容易使用
<form action="/path/to/script" id="thisform" method="post">
<p><label for="name">Name:</label><br /> <input type="text" id="name" name="name" /></p> <p><label for="email">Email:</label><br /> <input type="text" id="email" name="email" /></p> <p><input type="submit" value="submit" /></p> </form> |
我喜欢方法C的几个地方.首先,对于类似本示例的单纯表单来说,我发现把每个说明与表单元素放在单独的段落比较方便,不加上样式显示时,段落之间的预设距离应该足以让你轻松阅读内容.稍后我们还能以CSS为表单内包含的<p>标签设定间隔.
我们甚至更进一步,为表单设定了唯一的id="thisform".因此,刚才我提到的精确间隔大致上可以写成这样:
#thisform p{
margin:6px 0; } |
这代表将这个表单内的<p>标签的上下外补丁设定为6个像素,覆盖浏览器为一般段落选用的预设值.
方法C与前两种方法的另一个不同之处在于:尽管每个群组(说明和输入框)都放在<p>里头,我们仍以<br />把他们放在独立的一行.使用<br />分开每个元素,就能绕过文字长短不一,造成输入项无法完美对齐的问题.
图5-4是一般浏览器显示方法C的效果,这边有使用先前为<p>标签设定的样式.
图5-4.浏览器显示方法C的效果,有对P标签使用CSS
除了方法C的视觉效果之外,最重要的优点:也就是提升易用性的部分.
<label>标签
使用<label>标签提升表单的易用性需要两个步骤,而方法C已经完成这两个步骤了.首先是以<label>将文字说明与相关的表单元素连接在一起,不管是文字输入框(text field),文字区块输入框(text area),单选框(radio),多选框(checkbox)等等都好.方法C在"Name:"与"Email:"标题上使用了<label>标签,把它们与输入资料的元素连接在一起.
第二步则是为<label>标签加上for属性,填上对应输入框的id.
举例来说.在方法C里面,以<label>标签把"Name:"包了起来,并且在for属性里填入与其后面的输入框id相同的值.
<form action="/path/to/script" id="thisform" method="post">
<p><label for="name">Name:</label> <br /> <input type="text" id="name" name="name" /></p> <p><label for="email">Email:</label><br /> <input type="text" id="email" name="email" /></p> <p><input type="submit" value="submit" /></p> </form> |
为什么要用<lable>?
或许听过其他人说你应该在表单内加上<label>标签.而最重要的问题在于为什么应该要用<label>标签.
建立label / ID的关联能让屏幕阅读器为每个表单元素读出正确的标签,而不收版面排列方法的影响,这是件好事.同时,<label>标签正是为了标记表单栏标签而生,使用这个标签的时候,我们就是在为每个元素说明意义,强化表单的结构.
在处理单选,多选框时使用<label>标签还有个额外的好处,那就是大多数浏览器在使用者点击<label>内文字时也会改变元素的值.这样能为输入元素造成更大的点击区域,让行动不便的使用者更容易填写表单(Mark Pilgrim, "Dive Into Accessibility," http://diveintoaccessibility.org/day_28_labeling_form_elements.html).
举例来说,如果为表单加上一个多选框,让使用者能够选择"记下这些信息",那么我们就能像这样的使用<label>标签了:
<form action="/path/to/script" id="thisform" method="post">
<p><label for="name">Name:</label><br /> <input type="text" id="name" name="name" /></p> <p><label for="email">Email:</label><br /> <input type="text" id="email" name="email" /></p> <p><input type="checkbox" id="remember" name="remember" /> <label for="remember">Remember this info?</label></p> <p><input type="submit" value="submit" /></p> </form> |
借着以这种方式标记多选框,可以获得两个好处:屏幕阅读器能读出正确的说明文字(就像这个例子一样,文字出现在输入框之后也行),而且能切换多选框的范围变大了,现在切换范围除了多选框本身之外,文字部分也包含在内(大多数浏览器都支持).
图5-5就是这个表单在浏览器中的显示效果.我们特别标示了加大之后的多选框切换范围:
图5-5.把文字包含在切换范围内的多选框
除了表单与段落之外,最后我还想展示另一个标记表单的方式,使用定义清单.
方法D:定义一个表单
<form action="/path/to/script" id="thisform" method="post">
<dl> <dt><label for="name">Name:</label></dt> <dd><input type="text" id"name" name="name" /></dd> <dt><label for="email">Email:</label></dt> <dd><input type="text" id="email" name="email" /></dd> <dt><label for="remember">Remember this info?</label></dt> <dd><input type="checkbox" id="remember" name="remember" /></dd> <dt><input type="submit" value="submit" /></dt> </dl> </form> |
最后讨论的表单排版方法,是以定义清单定义每一组说明文字与输入框.这是有点争议的方法.我们在定义清单的原始设计目的的边缘游走,不过这是在近期逐渐普及的方法,同时也只得本书一提.
本书稍后在第8章回深入讨论定义清单.事实上,它们能应用的范围远超过大多是设计师的认知:以<dl>排版表单就是个很棒的例子.
你应该发现了这个范围里面的每组表单说明文字都放在定义名词标签<dt>之内,随后跟着放在定义描述标签<dd>中的表单元素.这么做能将说明文字与表单元素对配起来,并且在不使用任何样式时以浏览器显示的效果见图5-6:
图5-6.以清单定义排版表单的显示效果
根据预设值,大多数可视化浏览器会把<dd>缩进显示在单独一行之内.太棒了,因为这样便不必使用任何多余的<p>或<br />标签了就能让不支持CSS的浏览器显示出容易使用的表单排版效果.
定义样式
最简单的样式修改,大概是去掉表单内<dd>元素的预设缩进:
form dd{
margin:0; } |
前面这一小段css会使方法D范例显示成图5-7:
图5-7. 去掉<dd>缩进效果的定义清单式表单排版
方法A的表格效果,也能借着浮动表单内的<dt>元素达成:
form dd {
margin: 0; } form dt { float: left; padding-right: 10px; } |
在把<dt>元素浮动到左边之后,包含在<dd>之内的表单元素就会排列到右侧,像是图5-8这样.你应该已经发现表单元素不会完美的对齐,但这至少说明了使用<dl>标签排版表单时,并不代表必须将每个元素都单独显示在一行里.
图5-8.浮动<dt>元件之后的表单排版
事实上,由于多了<dl><dt>和<dd>元素,再加上表单内原本就具备的<label>与<input>元素,因此在设计CSS时,你拥有更多可以指定样式的对象,而发挥的空间也变大了.
概要
看完四种标记同一个简单表单的不同方法,同时也讨论了彼此的优缺点,要注意的是,我们为方法C与方法D加上了易用性功能,当然也可以加到头两个方法上,在得到这些改进之后,这两个方法当然也会变得更棒.
这几个方法没有哪一个明显比其他方法要好,或者能当作"最佳解决方案".不过多知道几种方法很有价值.而你也以组合这四种方法,在你的项目里做出更棒的表单.
方法A:
以视觉效果来说,是个建立表单元素,说明文字的简介方式,在处理复杂,庞大的表单时尤其好用.
然而,为了这样单纯的表单使用表格,似乎太麻烦了.
方法B:
简单的标记法在文字浏览器,小屏幕设备上的显示效果不错.
以视觉效果来说,只用<br />会让排版变得太拥挤.
方法C:
简单的标记法在文字浏览器,小屏幕设备上显示效果不错.
允许说明文字,表单元素的长度变化,不会有对齐的问题.
包含重要的易用性功能(也能使用在先前的方法内).
方法D:
结构化标记法在文字浏览器,小屏幕设备上显示效果不错.
包含重要的易用性功能(也能应用在先前的方法内).
说明文字与表单元素能以CSS指定要放在同一行之内,或是分行摆放.
当你使用方法A或方法B的时候不必感到内疚,但是学会方法C的优点,并且把它应用到先前的例子里仍然不错.
方法C也有进步的空间,而我们也将在"技巧延伸"这个单元内看到几个我们能加上的额外功能.我们也会讨论一些简单的CSS样式.让我们把表单修饰得更吸引人.
技巧延伸
在这个单元中,我们会先讨论tabindex和accesskey属性,看看它们如何使表单变得更加容易浏览.我们也会研究能帮助组织表单区域的<fieldset>标签,最后,我们会看一些CSS,因为它能把表单外观修饰得更漂亮.
神奇的tabindex:
我们能轻易加上的功能之一是tabindex属性.加上tabindex,为它指定一个数值之后,使用者就能以键盘切换正在使用的表单元素(通常是Tab键).按下Tab就会依照我们所制定的顺序跳到下一个表单元素.根据预设值,每个能互动的元素都隐含有tabindex,但使用tabindex能收回浏览器指派的顺序,让你完全掌握控制权.
举例来说,让我们为先前的示例(方法C)里面的表单元素加上tabindex属性:
<form action="/path/to/script" id="thisform" method="post">
<p><label for="name">Name:</label><br /> <input type="text" id="name" name="name" tabindex="1" /></p> <p><label for="email">Email:</label><br /> <input type="text" id="email" name="email" tabindex="2" /></p> <p><input type="checkbox" id="remember" name="remember" tabindex="3" /> <label for="remember">Remember this info?</label></p> <p><input type="submit" value="submit" tabindex="4" /></p> </form> |
现在,当使用者在表单内切换输入框的时候,我们能确定切换的顺序与我们期望的顺序完全相同:Name,Email,Remenber this info与submit按钮.
在设计复杂,单一行有许多输入框或者其他表单元素的表单时,使用tabindex设定切换顺序的优点就显而易见了.
为何指定切换顺序?
除了在我们表单上实施非常简单之外,还能再次帮助到行动受限的使用者,使其能完全以键盘浏览表单内容.他们不需要抓起鼠标点击每个部分,只需要用Tab键就能依照正确的顺序遍历每个表单元素.请为那些无法同时使用双手浏览网页的人想想,这真的很有帮助.
为频繁使用的表单指定快捷键
与tabindex类似的.accesskey属性是另一个容易加上的功能,不仅能帮助行动受限的使用者,对其他人来说也是方便极了.
举例来说,如果为表单内包围着Name:的<label>标签上加上accesskey属性,那么在使用者按下指定的按键时,光标就会自动跳到与说明文字相关的输入框.
我们来看看达成这个效果所需要的代码:
<form action="/path/to/script" id="thisform" method="post">
<p><label for="name" accesskey="9" >Name:</label><br /> <input type="text" id="name" name="name" tabindex="1" /></p> <p><label for="email">Email:</label><br /> <input type="text" id="email" name="email" tabindex="2" /></p> <p><input type="checkbox" id="remember" name="remember" tabindex="3" /> <label for="remember">Remember this info?</label></p> <p><input type="submit" value="submit" tabindex="4" /></p> </form> |
使用者必须在按下9这个按键的时候同时按下Alt或Ctrl键,根据系统而定,之后光标就会立刻移到Name:的输入框里头.
容易使用的搜索框
在设计会经常使用的表单时(比如搜索框,用户登录等等),加上accesskey属性格外有用,使用者不必伸手去拿鼠标,就能使用键盘立刻切换到适合的位置,开始进行输入.
有件事必须留意,虽然不是所有浏览器都支持accesskey,但是加上这个属性对支持的浏览器使用这很有帮助,举例来说,要是我们加上accesskey="9"的搜索位置时,windows使用者可以按Alt+9,而Mac使用者则能以Command+9直接切换到搜索输入框内了.
为表单加上样式
现在有了结构完善的表单,接着让我们研究一些能够用来自定显示效果的CSS技巧吧!
设定文字输入框的宽度:
处理表单元素需要技巧,因为它们的宽度,高度与浏览器种类有关.在表单示例中,我们没有指定文字输入框的宽度,让浏览器自动使用预设值,一般来说,设计者或许会以size属性为<input>元素指定宽度,像这样:
<input type="text" id="name" name="name" tabindex="1" size="20" /> |
把大小指定为20代表将文字输入框的宽度设置为20字元(而不是像素).根据浏览器的预设表单字体,实际的输入框像素宽度可能会有差异.这使得精确指定表单排版变得有点困难.
如果需要的话,我们能借着CSS以像素为单位控制输入框(以及其他表单元素)的宽度.举例来说,让我们把示例表单中的所有<input>元素宽度设定成200像素,我们会利用为表单指定id属性,在这个示例中是thisform.
#thisform input {
width: 200px; } |
这时,所有在#thisform内的<input>元素都会变成200像素宽.图5-9是可视化浏览器的显示效果.
图5-9 把所有<input>元件宽度设置成200像素之后的效果
哦喔~多选框和submit按钮也是<input>元素,因此得到了相同的设定值,让我们改以id指定Name和Email输入框,而不是一次设定所有的<input>元素的宽度:
#name, #email {
width: 200px; } |
图5-10是以浏览器检查修正后成果的效果,这时只有两个文字输入框是200像素宽的了.
图5-10.只有文字输入框是200像素宽的效果
使用<label>自定字体:
我们有几种不同的方法能够调整表单内文字的大小,字体与色彩,我们再度奉行"利用你使用的标签"哲学,直接以<label>元素为文字设定样式.
我喜欢以<label>元素指定文字样式,主要是因为,在不少情况下,我们都会希望为说明文字指定独特的样式,使它们容易与表单内可能出现的其他文字区分开来,举例来说,我们可以为表单内的所有段落标签制定独特的样式:
#thisform p {
font-family: Verdana, sans-serif; font-size: 12px; font-weight: bold; color: #66000; } |
这会使表单内的所有段落文字使用粗糙,酒红色的Verdana 12像素大小的字体.但是同样的结果也能借着为表单内的<label>元素指定相同样式来达成,像这样:
#thisform label {
font-family: Verdana, sans-serif; font-size: 12px; font-weight: bold; color: #66000; } |
这个样式的显示效果见图5-11.
图5-11.为label指定样式的效果
为什么我比较喜欢这个方法?假设除了说明文字之外,表单还有其他放在<p>当中的指示或文字内容.那么在前一种方法内,这些文字就会使用和<p>相同的样式设定了.
也能先为表单中的所有文字制定一种样式,接着再为<label>特别指定样式,以便做出独特的表单元素显示效果.
使用的CSS大概类似这样:
#thisform {
font-family: Georgia, serif; font-size: 12px; color: #999; } #thisform label { font-family: Verdana, sans-serif; font-weight: bold; color: #660000; } |
不需要多余的代码
或许你或发现,在#thisform label 的定义中没有重复font-size:12px;由于<label>元素包含在#thisform之内,因此他们会继承这个属性.在较高层级设定共享规则,接着在元素树底层覆盖有需要的设定值是个好习惯.这能节省不少代码.除了显而易见好处之外,也能让往后的维护工作轻松不少.如果你想改变整个表单的font-family,那么只需要修改一条规则,而不必修改所有重复设定字体的规则.
想象你设计了一个网站,全部使用了Georgia字体,最初你在20个不同的规则中分别加上相同的font-face:Georgia,serif;规则,过了一星期后,老板跑来找你并且对你说"CEO现在讨厌serif字体了,把网站内容改用Verdana".这时你的钻进这20条规则里,慢慢修改了.
或者是,你也能在更高层级设定一次这条规则,比如说指定在<body>元素里,此时整份文档都汇继承Georgia字体,除非以其他规则指定另外的设定值.现在,当老板要求你进行修改时,你就能回答"没问题,两分钟之后搞定";或者是能把简易性留给自己,告诉他这需要耗上两个小时,然后用这些额外的时间上eBay标东西.
OK,当然,你应该告诉老板真相,他们应该知道你的价值,为公司节省时间并且善用你找到的新解法.
以<fieldset>制作表单元素群组
使用<fieldset>是个为表单元素分组的便利方法.除此之外,加上叙述用的<legend>则会在大多数浏览器内,为你做好的表单元素群组加上一个漂亮的边框.我刚刚有说"漂亮"吗?嗯,我的确喜欢这种边框.而我们只需要用上一点CSS,就能使它变得更加迷人.
首先,来看看建立群组是需要哪些标签.接着为示例表单加上一个群组:
<form action="/path/to/script" id="thisform" method="post">
<fieldset> <legend>Sign In</legend> <p><label for="name" accesskey="9" >Name:</label><br /> <input type="text" id="name" name="name" tabindex="1" /></p> <p><label for="email">Email:</label><br /> <input type="text" id="email" name="email" tabindex="2" /></p> <p><input type="checkbox" id="remember" name="remember" tabindex="3" /> <label for="remember">Remember this info?</label></p> <p><input type="submit" value="submit" tabindex="4" /></p> </fieldset> </form> |
图5-12是浏览器显示这个群组的效果图,包含刚加上的<fieldset>与<legend>标签,以及刚为<label>设定的CSS样式.或许你已发现有条漂亮的边线围绕在<fieldset>里面的所有表单元素之外,同时<legend>的内容断开了左上方的边线.
图5-12.加上<fieldset>与<legend>之后的表单
我说这个效果"漂亮"的原因是:完全不加上CSS,使用它们的预设样式,它的显示效果的确让人相当感动.同时还能加上一些自定属性,使它变得更有趣,我们马上动手.
你应该也能看出<fieldset>在为表单隔出不同区块的时候十分有用,举例来说,如果我们的示例是个大表单的第一部分,那么以<fieldset>从视觉上隔开这些区块的话,不仅语义更清楚,还能使表单结构更明显,更容易阅读使用.
为<fieldset>和<legend>加上样式
我们能使用CSS改写<fieldset>预设边框与<legend>文字的样式,与定义其他元素的样式一样简单,首先,我们来修改边框的颜色和宽度,接着再修改文字本身.
为了使<fieldset>的边线变得更加细致,我们使用以下的CSS:
#thisform {
font-family: Georgia, serif; font-size: 12px; color: #999; } #thisform label { font-family: Verdana, sans-serif; font-weight: bold; color: #660000; } #thisform fieldset { border: 1px solid #ccc; padding: 0 20px; } |
接着为左右两边指定20像素的外补丁,并且去掉上下外补丁,为什么要去掉这些外补丁?因为我们的表单说明文字,表单元素都放在<p>标签内,因此他们在上下方向上已经留足了边界空白.
图5-13是指定这些样式之后的表单显示效果.
图5-13.为<fieldset>指定样式之后的效果
立体的<legend>
最后,为<legend>标签指定一些样式,做出立体的边线效果,让它看起来像是与<fieldset>元素的边线连在一起.
#thisform {
font-family: Georgia, serif; font-size: 12px; color: #999; } #thisform label { font-family: Verdana, sans-serif; font-weight: bold; color: #660000; } #thisform fieldset { border: 1px solid #ccc; padding: 0 20px; } #thisform legend { font-family: arial, sans-serif; font-weight: bold; font-size: 90%; color: #666; background: #eee; border: 1px solid #ccc; border-bottom-color: #999; border-right-color: #999; padding: 4px 8px; } |
如你所见,这里做了几件事,首先,调整了<legend>的字体,粗细与大小,接着产生了立体效果,把背景设为浅灰色,然后在整个<legend>的外面加上配合<fieldset>边线颜色的单像素边线,为了达成阴影效果,我们还把底部与右侧的边线颜色换成深一点的灰色.
字体大小百分比: 由于我们之前为整个#thisform 的字体设置为font-size:12px;因此要缩小<legend>文字时,我们直接用百分比,在较高层级指定字体大小,接着在底层使用百分比,能够减轻未来的维护负担.要调大整个网站的字体大小么?只要修改一个地方,所有百分比都会随之改变.事实上,最理想的状况下,我们可以设定<body>的初始字型大小,然后在其他所有地方使用百分比.然而在这个示例中,我们选择在<form>层级指定字体大小.
然后调整内部定,以便文字与边线之间留下一点空间.就是这样了!图5-14显示的是最后结果,加上本章内的所有CSS代码,同时仍然使用最简洁,灵活的表单结构.
图5-14 完成的表单示例,以CSS设定样式.
结论
标记表单有许多方法,不管你使用表格,定义清单,还是最基本的段落标签进行说明,表单元素的排版,都要记住,本章讨论的易用性功能,可以轻易加到任何方法里面.
像是tabindex与accesskey这种属性可以提升浏览效率,而<label>元素与对应的id属性能确保互助设备可以正确辨识你的表单内容.
基于短小简介的修改,就能得到更好的结果.