Web 标准实践系列(二)——豆瓣的首页
发表于 2007年01月30日 12:19 AM @ 分类:Web Standards
题外话:不好意思在第一篇的三周之后才交作业。本想继续写 Google 的搜索结果页的,看到豆瓣上有朋友留言说想学习豆瓣首页的写法,我看了一下,有写头。起初以为比较简单的,最后花了不少时间。但还是有疏漏或者不合理的地方,请直接指出,谢谢。
最后更新:2007-01-30
前言
- 下文中的例子以豆瓣用户登录后的页面为基础,各人显示的内容可能有所差别;
- 这次并不强求像素级的一致,特别是行距、间距部分可能有细微出入;
- 理解本文需要你对 HTML 和 CSS 有所了解,最好能够手写 HTML 和 CSS 代码;
- 详细阅读本文可能会花上你 15 分钟以上时间;
- 本文遵循 Code for the best, fix for the rest 原则。
一、分析结构
布局难点
豆瓣的首页是典型的三行两栏的布局,不过有特殊之处。除去头尾,中间的两栏,左栏是自适应,右栏是固定宽度(350px)。这样的布局,如果不考虑先加载哪部分内容(及语义),有相当简便的写法。另外如果两栏都是百分比宽度,那么也好处理。不过事实是右栏的宽度是固定的(并且我计划让左栏先加载)。固定宽度(或高度)是一件很危险的事,除非你也固定了文字大小,不然当文字被放大显示后,很容易出错(不过用表格的话就不用考虑这么多)。
其他难点
- 左栏的新评论列表
- 我觉得那是一个有序列表(Ordered List),所以在代码中用
<ol>标签;也可以用<dl>或者直接写<div> - 列表左侧的图片,是用户的头像而不是书的封面。所以我把
<img>和用户名那一行写在一起。
- 我觉得那是一个有序列表(Ordered List),所以在代码中用
- 右栏的豆瓣推荐和友邻的样式
- 我们常见的是固定高度的块依次浮动排列,但是这里书名的长度不一、图片大小不一且底部对齐,浮动块的高度未知,我没办法,只能暂时限定高度。谁有办法请不吝告知。
在分析结构的时候,我们一定要知道,我们需要先写什么,然后再写什么。这直接影响到后面样式表的写法。并且我的建议是,当结构确定下来之后,不要轻易改动。
二、基本布局代码
参照 Yahoo! UI Lib Grids,我把上中下三行分别命名为 #hd、#bd、#ft,是 #header、#body 和 #footer 的缩写。关于 id 和 class 的命名,各自有各自的习惯。在 CSS 里面,一般习惯用中划线法(如 comment-list)、下划线法(如 comment_list)、骆驼命名法(如 commentList)和帕斯卡命名法(如 CommentList),我个人比较倾向于使用下划线法。
中间的两栏我命名为 #main 和 #sidebar。哪部分先显示呢?我想左侧的新评论先显示可能更好一些,毕竟在大部分情况下它的宽度都大于右侧。于是在 HTML 里面 #main 要写在 #sidebar 前面,如下:
- <div id="hd"></div>
- <div id="bd">
- <div id="main"></div>
- <div id="sidebar"></div>
- </div>
- <div id="ft"></div>
样式表怎么写呢?#hd、#ft可以先不管,#bd 因为其内部有浮动,不能自适应高度,所以需要清除浮动,方法有很多。如果不清除浮动,那么 #ft 的内容就会“见缝插针”的显示在你不想见到它的地方。本文的例子,可以给 #ft 设定 clear: both;,或者为 #bd 进行 easy clearing(参考 P.I.E. 上的文章)。
因为 #main 的宽度是自适应的,#sidebar 的宽度又固定为 350px,在 HTML 里面又是 #main 在前,所以不能用简单的浮动(浮动的元素必须设定宽度,否则会根据内容取宽度),也不能用绝对定位,因为你不知道两者的高度。根据屏幕宽度不同,有时候是 #sidebar 比较高,有时候是 #main 比较高,使用绝对定位的话,下面的 #ft 显示就会有问题。所以我用了一种不常用的办法(我不太喜欢这种负值 margin 的写法),如下:
- #bd{
- padding-right: 410px; /* 因为有 padding 所以 clear float 不能简单地将 #bd 设置为浮动 */
- }
- #main{
- width: 100%;
- float: left;
- }
- #sidebar{
- width: 350px;
- float: left; /* 如果float right,在 IE 下有问题,这里 fix 一下 */
- margin-left: 60px; /* 栏间距,即 gutter */
- margin-right: -410px; /* 这一句很重要 */
- }
如果我们在 HTML 里面先写固定宽度的 #sidebar,那么 CSS 相当简单了,只需将 #sidebar 浮动到右边,然后 #main 再 margin-right: 410px; 就可以了,很 solid。这样 #main 的宽度也自适应了。CSS 如下(实际项目中我会采用这种写法,本例不是):
- #sidebar{
- float: right; /* 注意在 HTML 里面 #sidebar 写在 #main 前面 */
- width: 350px;
- }
- #main{
- margin-right: 410px;
- }
三、左栏新评论列表
刚才说了,这里可以用 <dl>、<ul>、<ol> 或者 <div>,用什么是个人习惯或者根据需要。我在这里用 <ol>,其他的写法都可以由此扩展。HTML 结构代码如下:
- <ol>
- <li>
- <h3>这里是评论的标题</h3> <!-- Logo 和各部分的大标题已经使用了 h1 和 h2 -->
- <p>评论的作者头像<img>和其他信息</p>
- <p>评论的摘要</p>
- </li>
- ...
- </ol>
这里的图片是用户的头像,所以我觉得应该和用户名放在一起。那么这种写法,用绝对定位简便一些。再提一下,如果使用浮动,必须给浮动的对象设置宽度,不然其宽度就会根据内容计算,这里的 <h3> 就不大方便用反向浮动的方法,因为它需要自适应宽度(如果用反向浮动的方法,可以参考上面布局的 CSS 写法)。
好了,基本问题解释清楚,我们开始写这里的样式(注意要清除 <ol> 的 margin):
- .comment{
- list-style: none;
- position: relative; /* 给头像的绝对定位一个参照 */
- width: 100%; /* 如果不设置宽度,在 IE 下有定位问题;参考 On Having Layout 一文 */
- }
- .comment h3{
- background: #EFE;
- margin-left: 75px;
- }
- .comment p{
- margin-left: 75px;
- }
- .comment .avatar{ /* 头像 <img> 的 class */
- position: absolute;
- top: 0;
- left: 0;
- }
如果我们把头像 <img> 单独提出来,不和用户名写在一起,那么可以不用绝对定位。不过在自适应的布局里,使用 float 来定位也是相当麻烦的一件事情。
四、右栏豆瓣推荐
最大的难点。因为书名长短不一致,导致浮动的块高度并不能够统一(如果不设置的话),这样对于第二排的浮动就会有影响。我没想出有什么好的办法可以解决这个问题,所以只能给一个不完美的写法(但这很常用):
- <ul>
- <li>
- <div><img src="..." alt="..." /></div>
- <p>书或其他 item 的名字</p>
- </li>
- ...
- </ul>
在图片周围增加一个 <div> 方便控制(看下面的 CSS)。豆瓣上的图片是大小不一的(真是灾难),本例简化为图片大小相同,这样不会耽误太多时间。
我把图片周围的 <div> 高度和 <p> 的高度分开,这样在放大文字的时候,可以保持相对良好的可读性(但还是有不足的地方)。样式表如下:
- .itemlst{
- width: 350px;
- margin: 0;
- padding: 0;
- }
- .itemlst li{
- width: 100px;
- padding: 0 8px; /* 使用 margin 在 IE 下会有 double margin 的 Bug */
- float: left;
- text-align: center;
- list-style: none;
- }
- .itemlst li img{
- padding: 10px;
- }
- .itemlst li div{
- width: 100%;
- height: 120px; /* 这样把图像所处的块高度统一在 120px */
- }
- .itemlst li p{
- float: left;
- height: 6em; /* 最多显示四行文字,再放大就不行了 */
- line-height: 1.5em;
- }
五、其他
- 因为 FF 和 IE 对于
border: 1px dotted #DDD显示的效果不一致。所以一般我会用背景代替(本例没有这么做)。 - 文字大小的控制,在
body中设置基准值small,然后使用百分比控制其他所有的文字大小。具体可以参考Bulletproof Web Design,中文版图书也已经上市。另,这只是习惯而已,在国内制作网页请根据实际情况量力而为。 - 关于第四部分的写法,在另外的文章内有说明。
- 在 CSS 的一开始,设定
*{margin: 0;padding: 0},统一各个浏览器的细微的差别。 - 最后设置各部分的字体和元素间的间距,完成整个页面的制作。
查看最终效果(通过 Strict 验证,不过没什么意思 -_-)
IE 下会有些局部的差异,大家有兴趣的话,可以研究一下,这里仅为 Firefox 服务。
六、我们学到了什么
- 利用
float进行布局,特别是第二部分里面的第二种写法很常用; - 利用
position: absolute;和position: relative;进行局部定位; - 列表项(
<li>)的浮动块状显示; - 在制作符合标准的页面时,需要考虑 resizing window 和 change font size 的问题。

评论
其实我很想知道,为什么google,百度甚至网易的有道这些搜索引擎的首页不用标准布局,而用表格来布局呢?
是为了兼容所有浏览器?但是现在以标准来做也很容易啊。
为了兼容其他非支持css的浏览器?保持页面的完整性?
但是为什么live.com和search.yahoo.com又用标准来布局呢?
能否解答一下这个问题呢?谢谢您了!
2007年01月30日 09:28
border和margin在ie6\7\FF下面让我的工作量至少提高了一倍。极度郁闷。
背景图!听起来不错……
2007年01月30日 10:02
我个人认为GG和baidu是因为之前大量的部署了table布局,而公司中心并不在Front-end,导致现在不方便革新吧?
而且,对于GG和baidu而言,本身自己就是信息的收集发布者,他们对于信息架构的要求也许并不像其他信息媒体平台那样重要。也就是说,Google和baidu没有必要SEO,至少他们自己的搜索页面,没有这个必要。
2007年01月30日 10:04
目前看来有一个问题,就是如果窗口缩得很窄,文字会挤在一列里面显示,看上去非常不方便(甚至和右栏重叠了……),如果在ff可以用min-width,而ie就比较麻烦了。我搜了一下,有篇文章(http://www.cnblogs.com/goodspeed/archive/2005/12/29/307529.html)提到可以用border-left:300px;margin-left:-300px的方法来限定最小宽度,至少保留数列,看上去可能更舒服一点?
----
google和baidu也有可能是为了在更多的设备和浏览器上面都能顺利访问,加上考虑到页面大小(对于超高访问量的网站些微的流量增加都要考虑),所以没有用标准化重构。(例如用 而不用css)
2007年01月30日 18:14
太专业了...junchen,我对你的景仰之情如涛涛江水连绵不绝。。
2007年01月30日 20:01
楼上两位,很感谢您们能解答我的问题,但是好像还没完全回答:
首先关于页面大小,两位认为用xhtml+css布局的页面的体积会比table布局的体积大吗?
第二个问题,为什么yahoo的搜索页面和live的搜索页面要用xhtml+css来布局呢?而不跟google和baidu一样采用table布局呢?
第三个问题,如果有个项目摆在你面前,类似搜索引擎的首页,您们会采用什么方法做呢?
2007年01月30日 20:03
…………居然有人比我先提交留言,
第三个问题再加多个:“为什么?”
2007年01月30日 20:06
to ivane: 我只谈 Google 以及 Yahoo
1、XHTML 页面一般来说会比 Table 的小。可是如果 5K:10K 和 50K:100K,前者区别不大,后者区别更明显。
2、我倾向于同意 xw 的意见。另,对于搜索引擎首页来说,访问速度瓶颈不在于 HTML 文件的大小,而是服务器带宽和响应速度。Google 首页大小不超过 7K(除了 Logo 那个图片文件),即使是 Modem 访问,也可以在 1s 内下载完。至于 Yahoo 为什么要搞标准,我觉得和公司策略有关,比如 Yahoo 还开源了他的 Yahoo! UI Lib。
3、看实际情况。有很多原因。
关于所谓的标准化兼容各个浏览器,甚至支持手持设备和 Accessibility 设备,这些很理想化。实际操作,我相信 Google 会安排另外的团队,根据不同的 User Agent 推送不同的内容给用户。比如 Google 的一些手机产品。没必要用同一个 HTML 文件推送到所有平台上。
而且真正可以低成本做到全浏览器制霸的,是<table>。
2007年01月30日 21:05
哈哈!谢谢JunChen的回复,您的回复至少证明了我的想法,不过有些支持Web标准的朋友看到你的回复可能就会抓毛了!
对于其他页面,我会义无反顾的用标准来制作,但是对于搜索引擎的首页,确实有点迷失方向~
再次谢谢JunChen的解答!谢谢您!
2007年01月31日 11:52
网上声讨GOOGLE不标准化的声音其实很多(google 里搜索:google web standards),无论是否标准化,但标准化以后肯定是必然趋势,但在现阶段如JunChen说的,一是公司策略,二是table的兼容性,三是资金……
2007年01月31日 13:39