在现实世界中,防弹衣并不能100%保证您不受伤害,但人们总是在不断地争取提升其防弹性能。毕竟,穿了防弹衣总是比不穿好。
这样的规则同样适用于Web设计。通过增加网页的灵活性,以及采用必要的步骤来保证它在尽可能多的场景中都具备可读性,我们就给自己的作品赋予了一些与众不同的特色。这是一个循序渐进的过程,并且当采用HTML和CSS后,将能够更加容易构建出赏心悦目并且具有良好适应能力的设计方案。
本文将讨论如何创建流动布局和弹性布局——为我们无懈可击的设计方案增添一个工具。掌握如何恰当地使用它们,将给网页设计增加更多的灵活性。流动布局并不是只能由CSS实现的,它也可以通过表格来实现。文中您将会发现,把布局的细节放在样式表中实现,还有许多其他好处。弹性布局中的列使用em作为长度单位,基于em的布局会随着字体大小的变化而放大或缩小。
为什么这样设计不是无懈可击的?
一、常见的方法
多列布局并不是只能由CSS实现,也可以使用表格同样实现能够根据浏览器窗口的大小而自由缩放的(流动)布局。以前,设计者会考虑到使用列来实现,每一列都由一系列表格单元格来构造。
图中显示了一个常用的布局结构,有一个页头横跨顶部、两列内容以及一个横跨底部的页脚。
常会看到与此类似的一种两列的布局结构
以前,我们似乎很自然地会使用表格来构建这种结构,用colspan这个特性使页头和页脚横跨于内容列的上方与下方。大致的 HTML代码如下所示:
<table>
<tr>
<tdcolspan="2">header</td>
</tr>
<tr>
<td>content</td>
<td>sidebar</td>
</tr>
<tr>
<td colspan="2">footer</td>
</tr>
</table>
但大多数的设计者和开发者不会就此罢休。构造好了基础结构以后,会在这个结构中的每一个单元格中再嵌入表格,为布局创建边界和像素级别精度的间距。最终,为了使构造的结构和页面的样式能够更加变化灵活,会添加很多HTML代码。
为了达到流动可变性,可将表单元格的宽度设成百分比形式,这使得布局可以完全扩展而不需要考虑浏览器窗口的大小。
<tablewidth="100%">
<tr>
<td colspan="2">header</td>
</tr>
<tr>
<tdwidth="70%">content</td>
<tdwidth="30%">sidebar</td>
</tr>
<tr>
<tdcolspan="2">footer</td>
</tr>
</table>
整个表格被设置成100%的宽度,列可以根据任意需要的宽度进行拆分。如图所示:左边是一个宽一些的内容栏,右边是一个窄一些的侧边栏。当浏览器窗口扩展或收缩而使布局的大小发生变化时,各列宽度的比例将保持不变。
这表明了表格能够用来构造布局,同时也表明了表格能够用来构造随浏览器窗口变化的流动布局。然而,还可以采用其他更完美的办法做到这一点。
二、值得思考的问题:为什么这样设计不是无懈可击的?
表格布局最主要的问题之一,就是表示内容与外观的 HTML 代码混在一起了。换句话说,边框、空白GIF和图片所用的代码都嵌入在表示重要内容的代码中。这意味着只典型的桌面浏览器才能够顺利地阅读这样的网页。而使用屏幕阅读软件、文本浏览器或在移动设备上阅读软件时,就可能遇到困难。
1. 大量的代码
内容与外观的缠结还意味着代码量的增大。使用嵌套表格来构造布局,所需要的代码量有时候是相当惊人的。许多额外的表单元格被用来构造栏间空白、边框和其他页面视觉效果。如果使用 CSS,HTML 代码就能够减少到只保留它最本质的部分,对外观的设定可以移到样式表中。这样,网页在非传统浏览设备和浏览软件中的可读性就立刻提高了,对搜索引擎也更加友好(这是一个额外的、免费的好处)。
2. 噩梦般的维护工作
因为大量的嵌套表格造成纠缠在一起的大量代码,这只能增加维护的工作量。对于基于表格布局的网页,要改造它们的外观,需要花费更大的力气——检查大量的单元格和额外的 H T M L 代码。在这样的情形下,修改的工作量会大得令人发狂,还不如推倒重来。
3. 并非最佳的内容顺序
使用基于表格的布局还存在一个缺点,即文本浏览器和屏幕阅读器上所呈现出来的内容有顺序问题。例如,有一个三列的布局,我们知道,HTML 中的顺序总是左列、中间列,然后右列。这是操作的表格方式。
基于表格的内容通常的顺序是左列、中间列、右列
在那些基于文本的浏览器或屏幕阅读器中,通常只能按上面的这种顺序对内容进行解析。但最主要的内容往往并不放在左列,而是放在中间列,这样,它很有可能被埋没在页面代码中。使用表格构造布局时,想要安排重要的内容在其他浏览器或软件中先被读到是不可能实现的。对于所有浏览设备都只有一种顺序,迫使用户在使用文本和屏幕阅读器时,想要得到重要内容之前,就要先艰难地穿过那些无关紧要的代码。
幸运的是,基于CSS的布局允许对内容顺序进行重排,这样,可以使用 HTML ,采用最优化的顺序来编写文件的源代码,而以其他的样式进行呈现。而且,所需的代码量大大地减少了,还将内容从表示层分离出来。那么,下面让我们开始使用CSS来构建流动的多列布局吧!
为什么这样设计是无懈可击的?
一、无懈可击的方法:
虽然在本文的无懈可击例子中重点介绍的是如何创建灵活可变的布局,但还是应该注意到,固定宽度的基于CSS的布局也具有无宽度限制的布局的很多优点。它们的主要区别是,可变的布局能够随着浏览器窗口的大小而伸缩,能够给用户更多的掌控能力。当屏幕尺寸可能存在明显差别(例如移动设备)时,这种方法的效果更好。
我们将介绍利用CSS创建流动布局的必要步骤及其原理。现在让我们从最简单的两栏布局(具有页头和页脚) 开始创建。
1.HTML 代码结构
我们不再使用表格单元格来构造页面的列结构,而使用简单的<div>和其他HTML 5语
义元素将内容划分成块。还要时刻记住,要使内容有最佳的排列顺序。
一个最基本的简单两栏布局可以用如下 HTML 代码编写:
<divid="wrap">
<header role="banner">
<h1>Header Goes Here</h1>
</header>
<div id="content"role="main">
... content goes here ...
</div>
<div id="sidebar"role="complementary">
... sidebar goes here ...
</div>
<footer role="contentinfo">
... footer goes here ...
</footer>
</div> <!-- end #wrap-->
代码结构就应该这样,很难再简化了。这种排序方式最为合理:页头、内容、侧栏和页脚。这是考虑了在没有CSS的情况下页面的布局。就这一点来说,到目前为止,一切都还不错。
我在整个布局之外增加了一个<div>容器。<div>通常可以在各种目的的设计中派上用场。所以,每当使用CSS来构建布局时,都会从<div> 开始。
2.创建栏:浮动与定位
用CSS创建栏的方法之一就是绝对定位(absolute positioning),所谓绝对定位,就是使用屏幕上的X和Y坐标将组件定位在特定的位置。但使用绝对定位最大的缺点是,不能使页脚准确地定位于所有栏的下方。
在构建多列布局时,方法的不灵活导致CSS设计者通常使用 fl oat 属性。因为浮动元素是可以被清除的,所以它是我们用来控制分栏布局的最好工具。CSS 3提供了创建模块化布局的新语法,但是这些语法还没有得到浏览器的广泛支持。而没有这些支持,是无法完成布局设计这类比较关键的任务的。因此我们仍然沿用float属性。
3.应用样式
选择用浮动作为创建栏的方法之后,我们再用百分比将网页分为内容栏和侧边栏两部分。在本例中,比例为 7:3(70% 内容栏,30% 侧边栏)。
第一步,要给页头、侧边栏和页脚加上背景色,以便区分我们所要处理的这几个部分。
header[role="banner"]{
background: #666;
}
#sidebar {
background: #999;
}
footer[role="contentinfo"]{
background: #DDD;
}
然后做两件事。首先,设置内容栏的宽度为70%,侧边栏的宽度为 30%。然后,使内容栏浮动在左边,侧边栏浮动在右边。这使得两个栏的位置相对。
header[role="banner"]{
background: #666;
}
#content {
float: left;
width: 70%;
}
#sidebar {
float: right;
width: 30%;
background: #999;
}
footer[role="contentinfo"]{
background: #DDD;
}
4.Gutter
“gutter”这个术语已经沿用了很多年了,指文本栏之间的间距。在处理流动布局的栏宽时,gutter 的设置就会变得非常困难。在一个固定栏宽的设计中,我们可将预计的宽度设置成像素大小,这样就可以很容易地连同栏宽一并考虑 gutter的宽度。
但对于流动的栏宽,我们有两种选择:将gutter宽度设成百分比的形式,栏宽也如此;或者,添加一个额外的<div>元素来设定和栏宽分离的外边距和内边距。后一种方法从 HTML 代码的角度来看不是最佳的,但它确实提高了控制水平,这在复杂的设计中是必不可少的。稍后将再次讨论这个问题。
为内容栏与侧边栏之间的gutter设置百分比宽度,一种方法就是给内容栏指定一个右外边距,然后从内容栏的宽度里减去它的值。当然百分比值的总和应该是100%
header[role="banner"]{
background: #666;
}
#content {
float: left;
width: 65%;
margin-right: 5%;
}
#sidebar {
float: right;
width: 30%;
background: #999;
}
footer[role="contentinfo"]{
clear: both;
background: #DDD;
}
通过上面的设置,我们把内容栏的宽度减少了5%,同时给内容栏的右外边距增加了同样的宽度来设置栏间的 gutter。显示结果,在内容栏和侧边栏之间多了一条白 色的间隔。
要记住,当给gutter赋百分比值时,栏间的间隔也会随着窗口的宽度而改变。在窄的窗口中会更小,在宽的窗口中则会更大。对于某些设计需求,这或许是个问题。例如,往往要求栏的边线或背景图片在栏之间有一个固定的间隔。在这些情况下,给容器加上第二层<div>容器是最佳选择了,这一点将在本章中继续讨论。但如果追求简单化,那么给外边距指定一个百分比值是最简单的选择。
5. 栏的内边距
如果栏的宽度设置使用百分比的方式,那么在指定其内边距时,也会出现相似的问题。这是内边距的计算方式造成的(在已声明元素的宽度上为“增加”)。如果使用除百分比之外的值来设定栏的内边距,那么最后的总宽度很容易超过或小于预期的值。这会让您轻易地放弃选择用浮动来控制页面布局。
例如,我们给侧边栏的内边距增加20个像素,使其显得更宽松一些。
header[role="banner"]{
background: #666;
}
#content {
float: left;
width: 65%;
margin-right: 5%;
}
#sidebar {
float: right;
width: 30%;
padding: 20px;
background: #999;
}
footer[role="contentinfo"]{
clear: both;
background: #DDD;
}
在宽度固定的布局中,可以很容易地将列两边定义的宽度各减去20像素的内边距。但在流动宽度布局中,是使用百分比来定义宽度的,根本无法设定一个30%的宽度减去40像素的宽度。这会使侧边栏的宽度变得大于30%,无法再与内容栏<div>并列,会被迫挤到
内容栏下边去。这可不是我们所希望的效果。
那么在这种情况下会有哪些解决方案可供选择呢?
■ 将内边距也设置为百分比,然后从列宽中减去它的值(就像前面我们增加一个 5%
的列间 gutter 时所做的一样)。
■ 只在侧边栏内部的元素中应用内边距。
■ 增加一个额外的<div> ,可以使用任意值来分别为它们的内边距赋值。
■ 使用中新增的极为方便的box-sizing属性,可以改变浏览器计算方框尺寸的方式(例如,在对象内部应用内边距)。
6.设置宽度的最大值和最小值
构建流动布局时,设计者常常要面对的一个障碍就是行的长度。能够随心所欲地伸展布局,对用户而言非常有益。但到了一定程度时,行的长度可能长到使内容难以阅读,也可能窄到破坏页面上其他部分的外观。
在这里,CSS的max-width和min-width属性就派上用场了。给流动布局设置最大和最小宽度,可以防止栏被无限制地伸长或收缩。很遗憾,IE6 不支持这种功能。但对支持这种功能的浏览器来说,它会带来很大的提高,而且添加起来十分便捷。
7. 滑动人造栏
如果您重新观察这一整章中我们一直在用的两栏布局,就会注意到,虽然我们给侧边栏设置了绿色的背景色,但这个背景只会往下扩展到刚好满足所需的位置。所以,根据栏中所容纳的内容,侧栏的高度与内容栏会有所不同。
通常,人们希望所看到的栏的外观是等高的,而且定义了一致的背景和边框。但使用流动布局时,无法使一个栏的高与另一栏相一致。
使用这种技术,平铺的图片位于栏的后面,造成一种错觉让人以为两栏一样高。这种方法可以使背景色、样式和边框都位于布局的后边,并一直延伸到页面底部。然而,这种技术只能应用于宽度固定的布局,其中列宽预先确定好,然后被内置到平铺的图片中。
DouglasBowman(www.stopdesign.com/log/2004/09/03/liquid-bleach.html)和EricMeyer(www.meyerweb.com/eric/thoughts/2004/09/03/sliding-faux-columns/)使这种思想更推进了一步,他们提出了“Sliding Faux Columns(滑动人造栏) ”方法,这样,平铺的图片就可以在流动布局的后面滑动,既可以实现栏等高的效果,同时也保留了灵活性。
二、再次探讨:为什么这样设计是无懈可击的?
第一个理由,代码量更少。不必再用嵌套的表格在 HTML 代码中实现边框、背景和间隔,我们只要用几个简单的<div>,而不必再用CSS为每栏设置位置与样式,就可以轻松地构造出一个多栏布局。即使在设计固定宽度的 gutter 和“滑动人造栏”(Sliding Faux Columns)时添加了额外(然而是必需)的<div>,HTML代码量还是远远少于使用嵌套表格时的情形。
第二,有了更易于维护的基本代码。因为外观的细节都在样式表中定义,HTML代码变得更容易阅读,要更改布局的外观,只需更新几个样式规则即可。使用CSS的float属性,在多栏布局中,可以给内容安排最佳的顺序,最重要的内容可以安排在 HTML 代码的最前面。这给使用屏幕阅读器、文本浏览器和不支持CSS的其他设备进行浏览的用户带来了好处。
最后,当实现了一个灵活的、流动的布局时,就会赋予用户一种控制能力。使他们能够随心所欲地扩展布局,也能在使用小屏幕时使窗口变窄。这种更高层次的控制能力,是证明设计方案无懈可击的另外一种方式,使设计方案能适应尽可能多的环境。
固定布局、流动布局和弹性布局,哪种方法更好呢?在选择采用何种布局时,需要记住最重要的一点是,每种方法都有它合适的位置。要通过试验来搞清楚它们是如何运作的,以及在每个解决方案中它们的优缺点。
One point:选择讨论流动布局和弹性布局,不是因为我觉得它们在任何时候都优于固定宽度的布局。更恰当地说,每种布局都有它自己适合的场合,这主要取决于设计需求,因为对网页设计者来说,设计需求并不总是能够由自己作出决定的。
这就是说,如果您的设计方案中能加上流动布局或者弹性布局,那么就请为用户能从中获益而感到高兴吧。流动边距也为适应性Web设计(Responsive Web Design,RWD)打下了基础,适应性Web设计是一种根据网格布局所在的浏览环境使它们进一步调整并适应环境的方法。
PS:小提示
当构建流动布局时,应当记住以下几点:
■ 使用 fl oat 属性来构建多栏布局,可以清除掉浮动对象对页脚所产生的影响。
■ 从列宽中减去 gutter 的百分比宽度值,或者增加一个额外的<div>在列宽以外单独设置内边距的值。
■ 使用CSS 3的box-sizing:border-box;,在基于百分比的元素声明的宽度内设置内边距和边框。这种方法不需要使用额外的<div>来控制gutter,但是需要注意,并不是所有的浏览器都支持box-sizing。
■ 为流动布局设置min-width和max-width,防止布局尺寸过大或过小。不必在意IE6不支持这种功能。
■ 尝试用“滑动人造栏”(Sliding Faux Columns)的方法,通过使边框和背景一直延伸到页脚,来实现等高栏(但很灵活)。
■ 基于em的布局能提供另外一种灵活性。要记住,当把浏览器中的字体增大到某个值时,整个设计中的一部分就只能通过水平滚动条才看到(除非对布局设定了max-width)。
至此已经介绍了创建一个灵活、流动、基于CSS的布局的基础知识,接下来将把这本书中迄今讨论过的方方面面综合起来,从而构建一个完整的、单页的无懈可击的设计方案。
样章试读:http://product.china-pub.com/199780