[补完]More Eric Meyer on CSS Pro…

2005-06-05 19:17 | Nautilus

旁边的信息栏

随着我们的工作的深入,我们该处理包含信息的div元素了.在原有设计中这是一个安放在左边的信息栏,现在我们要在同样的地方安放一个同样的信息栏.之前的原有文档中的这个信息栏是由非常复杂的单元格构成,并被分成了两行.而现在我们只需要对一个div应用样式就可以了.(这便是优点!桀桀!)

为了让这个侧边信息栏被安置在正确的位置上,首先我们要作定位.由于包含这个div的上一级乃至上n级元素都没有被定位,所以这个div的定位要以最基本的元素为参照物(就像那个导航条).我们从左上角开始这个工作,头部的Title的高度是72像素,那么我们只要让侧边栏的位置低于Title就可以了.

#navbar a {text-decoration: none; color: #000;

border-bottom: 1px solid gray;

padding: 0 1em 1px 0;}

#info {position: absolute; top: 73px; left: 0;}

#review h2 {color: #600; font-size: x-large;

margin: 1em 0 0;}

现在,这些改变意味着这个包含信息的div被完全移出了文档流,同时被放在了我们希望它在的位置.距离基本的文档盒的顶部73像素,同时左对齐.这就是说现在这个div是完全重叠在那些Review文字的上面的.事实上,这个侧边栏的宽度是默认100%,如果我们给它一个背景,它就会从文档的一侧延伸到另外一侧去....

Tip:宽度的测量
我们使用了像素作为单位,因为原有文档就是用像素作单位.当然任何单位都是可以使用的.百分比和em都是定位布局中常用的单位.

如果你现在浏览一下你的文档,你就会发现这种情况,当然这个情况不会一直持续下去.我们来添加个背景,同时也定义一个没有歧义的宽度吧,看看图示10就了解了.

图示10:我们已经设定了位置与尺寸,但是还有很多事情要做.

侧边栏盖住了文字!不过我们一会就可以搞定它,先充实一下那个侧边栏吧.我们需要先加上一个边缘,再在内容与边缘之间创建一个分隔.

#info {position: absolute; top: 73px; left: 0; width: 140px;

background: #F0DFB4; padding: 0.75em 0;

border: 1px solid #600; border-width: 2px 1px 2px 0;}

就这样,我们创造出了在原有文档中使用N多单元格才创造出的边缘效果.对内补白我们使用em作为单位,以便在内容文字的尺寸发生变化时内补白也有相应变化,同时也能保证垂直对齐与原有文档的相同.

Tip:左右内补白问题
我们把左右侧的内补白设为了0,这是因为它们会被计入宽度中去.对侧边栏中的元素应用内,外补白比对div本身应用内,外补白来的容易些.

侧边栏里的列表还需要更像原有文档中的那个,我们必须去掉列表前面的那个圆点.我们可以用一条规则做到去掉圆点和让文本缩排与别的地方平衡.

#info {position: absolute; top: 73px; left: 0; width: 140px;

background: #F0DFB4; padding: 0.75em 0;

border: 1px solid #600; border-width: 2px 1px 2px 0;}

#info ul {list-style: none; margin: 1em; padding: 0;}

#review h2 {color: #600; font-size: x-large;

margin: 1em 0 0;}

在为列表设定了一个应用到四面的外补白后,各列表内容之间就拉开了距离,同时从侧边栏的边缘缩进了,而这正是我们想要的效果.现在我们只剩下一件事了,就是保证侧边栏上方的表格的布局正确,我们需要让标注右对齐.现在它们被放在th元素内,因此这很容易:

#info {position: absolute; top: 73px; left: 0; width: 140px;

background: #F0DFB4; padding: 0.75em 0;

border: 1px solid #600; border-width: 2px 1px 2px 0;}

#info th {text-align: right;}

#info ul {list-style: none; margin: 1em; padding: 0;}

Tip:表格!
由于那些信息数据是适合放在表格里的,因此我们就保留了那个表格.我们可以把它转成无表格的结构,但是那需要大量使用漂浮,同时意义也不大.

少量的内补白有助于让内容不至于拥挤在一起,因此我们加入相应的规则:

#info th {text-align: right;}

#info td {padding: 0.125em;}

#info ul {list-style: none; margin: 1em; padding: 0;}

还有一件事要做,我们得调整一下表格中的字体大小,原有文档中的这些字体要比现在的大些,字体种类也不一样.我们直接对表格应用样式,就像图示11里的那样.

图示11:现在侧边栏前所未有的完美,即使它仍然盖住了其他的内容.

和导航栏一样,对侧边栏的定位向我们展示了极具弹性的布局方式,我们只要替换top的值就可以往上或者往下那么...一点点,还可以让它的宽度扩展或者收缩,乃至修改left或者right属性让它跑到文档的另一侧....同样的,变换边缘的粗细和样式也不过是易如反掌的事情.

Review的样式

侧边栏的样式已经完工了,但是它仍然盖住了Review的内容,这显然不是一个好现象,我们得把Review的文字内容向右拉进来一些.在做这个工作之前,我们先去看看原有文档是个什么样子,有一张宽40像素的gif占位图片被安置在侧边栏和主要文字内容之间,还有一张80像素的占位图片安放在主要内容的右边.我们可以对包含Review文字的div应用简单的规则来一口气搞定两种效果.

#info ul {list-style: none; margin: 1em; padding: 0;}

#review {margin: 0 80px 2em 180px;}

#review h2 {color: #600; font-size: x-large;

margin: 1em 0 0;}

40像素加上侧边栏的宽度140像素,我们要在左边定义180像素的外补白,当然右边的外补白就是80像素咯.底部的2em的外补白是为了在Review的底部创建出一些额外的空间.

解决的覆盖问题后,我们可以把注意力集中在文字本身上面了.如果你仔细的看图示12,你可以发现内容概要的那一行(Bottom Line)与侧边栏里的"Region"并不在同一水平线上.这个对齐效果也是原有文档使用复杂难解的表格嵌套排版的原因.但是在这里只需要调节一下标题上方的外补白.在作了一些尝试后,以下的数值可以得到相当不错的效果.

#review h2 {color: #600; font-size: x-large;

margin: 1em 0 0; padding: 0 0 0.2em; line-height: 1em;}

图示12:栏目变的清晰了.Review文字可读性大大增强.

为什么使用line-leight呢?因为虽然默认值与定义了line-leight后的效果在所有的浏览器里看起来差不多,但是这个默认值是没有任何保证的,有的浏览器或许把默认值设为1.2,另外一个浏览器设为1.25,再来一个浏览器却是1.175....CSS并不需要一个精确值作为默认值,所以浏览器可以把它们认为最好的值作为默认值.我们在这里清楚的定义一个line-leight值后,所有的潜在的错误可能都不复存在.

Tip:跨平台
事实上,以上的说法不完全准确,上面的数值在Windows下可以得到我们想要的效果,但是在Macintosh下的浏览器上还是不能完全对齐.这看起来应当是不同操作系统对字体尺寸单位的解释差异导致的.而且似乎在其他操作系统上也有类似差异.这也就说明了CSS驱动布局的一个缺点:不能指望这种形式的对齐能够在任何情况下都准确.

现在该看看Review的各个段落了,原有文档中使用了字符实体来让除了第一段外的段落首行缩进.我们去掉了这些字符实体,因为它们是不需要的,我们用text-indent就可以解决这个问题.

#review #summary {font-size: small; border-top: 1px dotted #600;

display: inline;}

#review p {text-indent: 2em;}

</style>

这样,Review中所有的p元素的首行都会缩进,包括第一段与标题下面的概要文字(它也是被放在p元素中的哦)幸运的是,我们可以为第一段文字加上一个类.

<p class="lead">

If there's one Asian food we truly love, it's sushi (although

dim sum comes a close second).

我们可以利用这个类与以前我们为概要文字写的规则来为第一段和概要文字关闭首行缩进效果,就像图示13中显示的那样.

#review #summary {font-size: small; border-top: 1px dotted #600;

display: inline; text-indent: 0;}

#review p {text-indent: 2em;}

#review .lead {text-indent: 0;}

</style>

图示13:Review中大部分段落的首行都缩进了.

处理引用,同时改进设计

到了现在,我们差不多完成了.我们真正必须做的事情就是让那个"缩行引用"看起来真的是被引用了的样子.现在,它位于两个段落之间,看起来与其他段落没有什么不一样.幸好,这个工作还是容易的,我们只要把它漂浮到右边,增大字体尺寸与字体的粗细,之后添加一些内补白让它与其他文字不致挨的太近.

#review .lead {text-indent: 0;}

blockquote.pull {float: right; width: 40%;

padding: 1em 0 1em 5%; margin: 0;

font-size: medium; font-weight: bold;}

</style>

如果你把这些样式与原有文档的HTML设计比较一下,你会注意到一些不同.其中一个就是我们把所有的gif占位图片都用1em的内补白代替.我们完全可以用10像素来代替图片,但并不是非要使用像素.为什么不使用更有弹性一些的单位呢?

左边的内补白只有5%,这相对原有文档中15%的占位单元格而言,看起来是那么的微不足道.因为这个缘故,原有文档中的表格宽度为45%,它的实际宽度在CSS规则中只写40%就足够了.

区别就在自然表格与用CSS样式修饰后的元素上.当我们创建一个宽度为15%的单元格时,它的宽度是包含它的表格宽度的15%,而这个表格的宽度又是包含这个表格的单元格的宽度的45%(真是麻烦的表格嵌套啊_ _).而内补白的百分比宽度(外补白和宽度也是一样)是以应用它们的元素的宽度为基准计算的.这样我们就需要算上一算,宽度40%加上5%的左侧内补白等于总共宽度45%.结果如图示14:

图示14:对缩行引用的内容应用漂浮与样式以模拟原有文档.

回到我们开始的地方吧,让我们来再对这个设计进行一些改进吧.那些细小的文字字包含了大量的内容,但是这也令文档难以阅读.在HTML设计中,你其实做不了什么,但是在CSS中,把扩大各个行的间距是很easy的事情,只消替换line-height的值就可以了.

#review p {text-indent: 2em; line-height: 1.3;}(花花:要用美丽的1.618!!)

不过,这样有可能又让标题下面的概要文字的布局发生变化,因此我们要重新设定概要文字的布局,就一点点....

#review #summary {font-size: small; border-top: 1px dotted #600;

display: inline; text-indent: 0; line-height: normal;}

为了有一点互动的感觉,我们来为导航条定义鼠标指针经过的效果吧.我们将要为这个效果定义一个起点,任何导航条上的超链接都在鼠标指针经过的情况下显示为白文字深蓝背景(为了配合顶部的masthead上的文字颜色)同时底部的边缘变宽.

#navbar a {text-decoration: none; color: #000;

border-bottom: 1px solid gray;

padding: 2px 1em 1px 0;}

#navbar a:hover {color: white; background: #336;

border-bottom-width: 3px;}

#info {position: absolute; top: 73px; left: 0; width: 140px;

background: #F0DFB4; padding: 0.75em 0;

border: 1px solid #600; border-width: 2px 1px 2px 0;}

Tip:失去的效果
IE/Win经常阻止元素的边缘超出其上一级元素的边界,因此这个3像素宽的边缘的效果无法显示出来.但是由于这个技术是一个很好的设计范例,同时在一些兼容性不很好的浏览器上也可以正常工作(其他兼容性强的高级的浏览器的效果会更好),所以这个技术仍然被提出来了.

上面的工作会显示出在导航栏的基本样式中的一点微小的不平衡.以前为超链接定义的样式中,内补白为右侧1em,左侧0.这就意味着鼠标指针经过的效果会相对连接文字偏移.我们需要平衡这些偏移以便令文字处于超链接区域的正中央.就像图示15那样.

#navbar a {text-decoration: none; color: #000;

border-bottom: 1px solid gray;

padding: 2px 0.5em 1px;}

图示15:平铺文字,调整超链接.

再访Masthead

OK,我们已经重新创建了布局,同时相比原有文档还改进了那么一点点.但是Masthead呢?它仍然"坐落"于3个单元格里,而且图片仍然是切片拼合的.我们来看看能否改进一下.

我们可以把这3张图片切片拼合成为1张完整的.但是把厨师和文档大标题合并为一张图片,同时把副标题("A Guide to Fine Northeast Ohio Dining")单独保留为另一张图片,这样处理要更灵活些.把副标题分离出来后,通过定位我们可以随意的把摆放到任何位置.因此我们把图片像图示16那样做了处理.

图示16:合并厨师和大标题,分离副标题后,我们就有了更多的布局方式可以选择.

现在我们只要重写这里的html,以让图片仍然正常显示,但是代码就简洁的多了.只要把它们放入一个div再为加上合适的id属性就可以满足要求.

<body>

<div id="masthead">

<img src="masthead.gif" alt="Cleveland Eats">

<img src="subhead.gif" alt="A Guide to Fine Northeast Ohio Dining" id="subhead">

</div>

<div id="navbar">

第一条规则是把副标题放到它应该在的位置.计算原有文档中的像素数以确定正确的位置很容易.

th, td {padding: 0;}

#subhead {position: absolute; top: 46px; left: 151px;}

#navbar {position: absolute; top: 44px; right: 0;

padding: 2px 0 2px 32px; white-space: nowrap;

background: #F0DFB4 url(tab-curve.gif) bottom left no-repeat;}

这就把副标题放到了文档上方偏左的位置,当然,如果我们觉得应当再移动一点点.....向左1到2像素..可以修改top和left的值来达到目的.这样,我们可以随心所欲的移动它..也许右上角,也许紧帖导航栏..现在我们先不做这样的操作,你可以以后自己实验...

到这里我们还令Masthead区域的图片创建块级盒,这样做的目的是排除在使用Gecko内核的浏览器(比如Mozilla,这些浏览器处理图片的时候比较的严格)上出现布局变化的可能.具有块级盒后,出现变化的可能性被排除,同时带给我们图示17那样的效果.

图示17:副标题像它以前那样被安放到它应该在的位置,但是移动它只是一瞬间的事情.

Tip:绝对块级化....
使用绝对定位的副标题图片本身已经创建了一个块级盒.任何使用绝对定位的元素都是这样,不管它们在被定位之前曾经创建过一个怎样的盒.

th, td {padding: 0;}

#masthead img {display: block;}

#subhead {position: absolute; top: 46px; left: 151px;}

还有一样东西忘记了:那条邪恶的分隔线.我们知道它应该距离Masthead顶部43像素.这就给了我们一个诱惑:理论上我们要对Masthead这个div定义一个清楚的的高:43像素,同时令masthead.gif溢出它所在的div元素.为了达到我们的目的,CSS可以这样写:

#masthead {height: 42px; border-bottom: 1px solid #666;}

如果我们这样做,我们就需要调整"Review"的样式..为什么呢?因为Masthead现在高44像素(高加上边缘宽度)而不是原来的73像素,这样"Review"就将向上移动29像素.解决这个问题其实有够简单:一个29像素的上方的内补白可以抵消这个变化.

不幸的是,妨碍我们使用这种精确技术的是Internet Explorer/Windows,它会无视以上定义并在显示时扩展Masthead的高以使div的尺寸与图片的尺寸相符合.
因此我们有2个选择:第一个是为masthead.gif定位,把它从文档流中取出,令IE对div的高度解释正确.达到这些目的的CSS如下:

#masthead {height: 43px; border-bottom: 1px solid #666;}

#masthead img {position: absolute; top: 0; left: 0;}

#masthead #subhead {top: 46px; left: 151px;}

#review {margin: 0 80px 2em 180px; padding-top: 30px;}

另外一个可能的选择是保留图示17中的样式,然后把一个宽高1像素的图片放到Masthead的背景中去并让它在水平方向上重复显示.就像这样:

#masthead {background: white url(stripe.gif) 0 43px repeat-x;}

这样做的好处在于只需要增加1条规则就可以得到水平分隔线,同时任何可以水平重复的图案都可以使用.同时,它的缺点就是需要读入额外的图片以显示结果.到底要怎样做则要由你来决定咯.效果见图示18:

图示18:完全重构后的Mastheas,没有表格了!

当New Riders出版社在漂亮沉重的纸张和彩色墨水上大把投入的时候,我们将要列出刚才我们写出的CSS(使用背景图片作出水平分隔线的版本).因为它比另外一个要短一些....

Tip:告诉我有什么不同.
图示18使用的是上述2种技术中的哪一种?这并不是个重要的问题,如果你很想知道,就看看ch0118.html吧.

列表 1.2. CSS - 使用背景图片的版本

body {font: x-small Verdana, Arial, Helvetica, sans-serif;

margin: 0; padding: 0;}

table {width: 100%;}

th, td {padding: 0;}

#masthead {background: white url(stripe.gif) 0 43px repeat-x;}

#masthead img {display: block;}

#subhead {position: absolute; top: 46px; left: 151px;}

#navbar {position: absolute; top: 44px; right: 0;

padding: 2px 0 2px 32px; white-space: nowrap;

background: #F0DFB4 url(tab-curve.gif) bottom left no-repeat;}

#navbar b {display: none;}

#navbar a {text-decoration: none; color: #000;

border-bottom: 1px solid gray;

padding: 2px 0.5em 1px;}

#navbar a:hover {color: white; background: #336;

border-bottom-width: 3px;}

#info {position: absolute; top: 73px; left: 0; width: 140px;

background: #F0DFB4; padding: 0.75em 0;

border: 1px solid #600; border-width: 2px 1px 2px 0;}

#info table {font: small Arial, Verdana, Helvetica, sans-serif;}

#info th {text-align: right;}

#info td {padding: 0.125em;}

#info ul {list-style: none; margin: 1em; padding: 0;}

#review {margin: 0 80px 2em 180px;}

#review h2 {color: #600; font-size: x-large;

margin: 1em 0 0; padding: 0 0 0.2em; line-height: 1em;}

#review #summary {font-size: small; border-top: 1px dotted #600;

display: inline; text-indent: 0; line-height: normal;}

#review p {text-indent: 2em; line-height: 1.3;}

#review .lead {text-indent: 0;}

blockquote.pull {float: right; width: 40%;

padding: 1em 0 1em 5%; margin: 0;

font-size: medium; font-weight: bold;}

 

评估

在描述完一个转换操作后-就像刚才我们动手做过的那个一样-你也许会遇到一些疑难."为什么要这么麻烦,表格不是工作的很好吗?"就是一个常见问题,对这个问题有2个很好的理由:

首先:文档的结构变的非常清晰,从而易于编辑与维护.我们设想一下,假如你有某个标签没有关闭,而导致了布局上的混乱,你是愿意到蜘蛛网般密集的表格中去一个个标签的过滤,还是愿意到我们刚刚完成的,文档结构关系清晰简洁的页面中去轻易解决呢?大概会是后者吧....

然后:文件的大小变化是显而易见的,表1比较了三种方式的文件大小,元素数量,服务器响应次数.三种方式分别是完全的HTML布局设计,HTML+嵌入CSS,HTML+引入CSS

Tip:响应次数范围
有一些服务器响应次数的值是以范围形式给出的,这样做是因为考虑到重复使用的图片.以完全HTML设计为例,它包含18个占位图片,大部分浏览器会只下载1个到缓存,之后重复使用;但是没有或者不使用缓存的浏览器就需要下载18个占位图片了,相应的有多少图片,服务器就要响应多少次.

方式文件尺寸*字符数量服务器响应次数图片数量表格数量Font标签数量
All Html100%89946-2322(18重复)720
Html+CSS75.4%67855410
Html+linked CSS59.8%5375+14355-6410
*相对完全的HTML设计

即使在文档中嵌入CSS样式,文档尺寸差不多也能减少25%.如果把CSS单独存为一个文件,这个优势就更加惊人,文件尺寸下降到原有文档的60%左右,不管是上面两种方式的哪一种,文档的下载都会更快,也节省了了网络带宽占用.

在59.8%这里需要一点简短的说明,这59.8%没有把CSS计算在内,这是因为浏览器通常会把CSS文件缓存到本地供下次访问时调用.这样,第一次访问时,速度与带宽占用与在文档中嵌入CSS的形式差不多,有25%的节省.之后CSS文件就不需要再下载了.

还需要增加一点说明,使用定位方法的CSS版本会比使用背景图片CSS的版本更容易替换样式,比如变换侧变栏的宽度,移动副标题的位置,甚至彻底重新定义基本布局都只是简单快速的编辑操作.它们就像我们已经做过的那些一样值得拿来研究.

一个忠告

关于这种布局方式,有一个警告.如果Review部分的高度比侧边栏要低,就可能发生一些怪事.在表格中,在同一行中的单元格都是一样的高度,如果我们把侧边栏放在一个单元格里,而把Review放在另一个单元格中,这两个单元格的高度都会和两者中高度高的那个一样.

在CSS定位法中,我们无法把两个元素像两个单元格那样联系起来.一旦你把一个元素从文档流中取出,它的高度只取决于它的内容以及应用的样式规则,它不能影响到别的元素,也不能被别的元素所影响.因此,当两个栏目必须在视觉上一样高,或者有另外的一些内容需要跟在两个栏目后面时,如果你不知道哪一个栏目在实际上会高一些,CSS定位就不是个好主意.但这不是说CSS定位没有用处.越来越多的活跃网站,包括在线新闻站,Sprint PCS, 还有 Quark 都在使用CSS定位布局.你只需要知道CSS定位的好处与它的缺点,这样你就可以在布局时做出正确恰当的选择.

扩展练习

以我们在这个工程中创建的CSS为基础,在不修改文档结构的前提下达到下面图中的效果.体会一下这样的修改相比重写表格是怎样的简单.

1把导航条移动到右上的角落里,然后把副标题移动到导航条的下面,分隔线的上面.Masthead的下面空出来一些空间后,把Review部分的文字向上移动,不要浪费屏幕空间哦.

2.翻转布局,让侧边栏位于右边而Review文字位于左边.注意那个厨师图片的底部原本是侧边栏的上边缘,因此这里需要一条边缘线,样式随意.另外,把概要文字上方的边缘扩展开与侧边栏的顶部接触并平齐.同时Review中不能有任何文字与侧边栏间的距离少于40像素.



-

Asimov’s Three Laws of Robotics:



  1. A robot may not injure a human being or, through inaction, allow a human being to come to harm.

  2. A robot must obey orders given to it by human beings except where such orders would conflict with the First Law.

  3. A robot must protect its own existence as long as such protection does not conflict with the First or the Second Law.