跳至主要内容

纯CSS无hacks的跨游览器多列布局

翻译自Matthew James Taylor的Equal Height Columns with Cross-Browser CSS and No Hacks,有些部分根据我的理解改了,让一些初心者更好理解。

利用纯CSS创建一个等高多列的布局并不件易事,本教程将着重分析出现在多列布局的多个问题,然后为大家等来一个简单全游览器通吃的解决方法,不使用图片,脚本,CSS hacks并在最严格的XHTML 规范中都能通过验证。

问题的症结所在

可点击放大缩小

如上图所示,由于各列的内容不一致导致其背景的高度也不统一。而背景实质上是内容(标准的盒子模型是由内容区,补白区,边框区与边界区组成,背景存在于前三者中;IE为前两者)的自适应的问题。再转化一下,如何撑大那些较短的列的高度,让所有列的高度等于最高的列的高度?这个,的确很很棘手,因为我们不清楚各列的高度,也无从得知哪一列最高。我们也不能简单地给所有列一个明确的高度,这可能会导致所有列都多出一大片空白,或者很不亏由于高度不足导致某些列的内容无法全部显示出来!现实中,内容的长度是动态的,因此每列的高度也是动态的。我们必须意识到在网络中,不存在"固定"二字,每个人的显示器的分辩率都不尽一样,游览器的字体大小设置也不尽相同,这些都会影响到内容的显示高度。

对内容与背景实行分离

解决等高问题的第一步就是把它拆分为两个较小的,可以单独解决的部分。这样,我们原来是一列对应一个DIV,现在是一列对应一个DIV,一个用来装载内容,一个用来显示背景。这种分离有利于我们对各个元素的掌控和把它们用另一种更有效的方式组合起来,这引起我很快会在下面的章节讲述。

利用浮动嵌套解决最高列的高度的问题。

这是解决多列等高的关键。使一个DIV的高度等于最高列的高度的唯一方法就是让这个DIV包含所有的列。换句话说,通过把所有的列放在一个容器中,容器的高度就是最高列的高度。这是个非常有用的结构。

可点击放大缩小

单行三列的布局的结构层代码。

<div id="container1">
<div id="col1">Column 1</div>
<div id="col2">Column 2</div>
<div id="col3">Column 3</div>
</div>

对应的表现层代码。

#container1 {
float:left;
width:100%;
}
#col1 {
float:left;
width:30%;
background:red;
}
#col2 {
float:left;
width:40%;
background:yellow;
}
#col3 {
float:left;
width:30%;
background:green;
}

为了使用这种结构在所有游览器都正常工作,我们必须让外层容器往左或右浮动,并且其子元素包含每一栏内容的DIV也跟着浮动,哪一个方向都无所谓。浮动会使用它们往上对齐于外围容器的上补白,并且浮动的容器会自动调整自身的高度与宽度以实现对浮动子元素的包含。但是如果容器被定义了高度与宽度,则它不会随子元素的大小而自动调整自身显示区域来适应子元素的显示。但在IE6与低版本的IE中,子浮动元素能撑开外围元素;幸好IE7与IE8已引正了这个不符合标准的做法。

增加用来显示背景的容器

下一步是增加额外的容器,让它们彼此嵌套,并让所有外围的容器数(新增的加上原来的那一个)等于列的总数:3。这三个容器用来显示各列的背景。请注意,我们去掉了原来各列的背景,把它们移至这些容器上。

可点击放大缩小

新的结构层代码,让新增的容器套在原来的外围容器上!

<div id="container3">
<div id="container2">
<div id="container1">
<div id="col1">Column 1</div>
<div id="col2">Column 2</div>
<div id="col3">Column 3</div>
</div>
</div>
</div>

新的表现层代码,新增的容器都是浮动元素!

所有元素左浮动,将容器宽度设为100%,使他们占满页面的宽度。背景色从内容 div 移除并加至容器上。注,原文是所有容器的宽都设为100%,其实根本没有这样的必须,因为在浮动嵌套中,外面的容器必须会被撑大能容得下内部子元素的大小!

#container3 {
float:left;
/*width:100%;*/
background:green;
}
#container2 {
float:left;
/*width:100%;*/
background:yellow;
}
#container1 {
float:left;
width:100%;
background:red;
}
#col1 {
float:left;
width:30%;
}
#col2 {
float:left;
width:40%;
}
#col3 {
float:left;
width:30%;
}

用相对定位来移动容器

现在是所有容器都完美地累在一起,只显示一种背景颜色,我们必须让其他背景也显示出来。为此我们就得利用相对定位来让这些容器像阶梯一样放置。这个本可以使用负边界技术,但该死的IE5.5的盒子模型与W3C的不一致,为了兼容我们就得使用到CSS hack。由于本文声明是不使用CSS hack,因此放弃。首先让#container2向右移到30%,由于#container2装着#container1,而#container1上装着那三个列,这样一来,最右边的列就被移出游览器的右边了。而最外围最底层的容器#container3则露出来了,露了左边的30%。然后我们再移动最上层的容器#container1,向右边移动40%,于是原来盖住的第二层容器也露出来了,露出其左边的40%,而#container1则只剩下100%-30%-40%=30%;上方的列也只剩下最右边的列,却表现为位于最左边。这样,背景也显示正常了!

可点击放大缩小

对应的表现层代码

#container3 {
float:left;
/*width:100%;*/
/*没有必要的代码被注释掉!*/
background:green;
}
#container2 {
float:left;
/*width:100%;*/
/*没有必要的代码被注释掉!*/
background:yellow;
position:relative;
right:30%;
}
#container1 {
float:left;
width:100%;
background:red;
position:relative;
right:40%;
}
#col1 {
float:left;
width:30%;
}
#col2 {
float:left;
width:40%;
}
#col3 {
float:left;
width:30%;
}

把各列的内容移回原来的位置上

由于最上层的那三列都是被整体往右往到(页面的)70%,我们再把它们都往左移回70%就是!最后,由于我们前两个背景容器都是被向右移动,移出了游览器,它们都与游览器的右边连在一起,我们可以设置最底层的背景容器的overflow来隐藏那些被移出的部分。

#container3 {
float:left;
/*width:100%;*/
/*没有必要的代码被注释掉!*/
background:green;
overflow:hidden;
position:relative;
}
#container2 {
float:left;
/*width:100%;*/
/*没有必要的代码被注释掉!*/
background:yellow;
position:relative;
right:30%;
}
#container1 {
float:left;
width:100%;
background:red;
position:relative;
right:40%;
}
#col1 {
float:left;
width:30%;
position:relative;
left:70%;
}
#col2 {
float:left;
width:40%;
position:relative;
left:70%;
}
#col3 {
float:left;
width:30%;
position:relative;
left:70%;
}

对列添加补白(内边距)

最后,我们对列增加补白,让每列显得大方一些,而不是密密麻麻地塞满一列。但是如果我们增加补白,可能有一些游览器的有病又犯了,在IE6和更低版本的IE中,其怪异的盒子模型,会产生一些我们不愿看到的结果。如,一个 200px 宽 20px 补白的 box 在 IE 中被视为 200px 宽,在其他浏览器中则为正确的 240px。补白应该加在元素的宽度上。

不过放心,我们可以用完全不依赖于 padding 的方法来解决这个问题。相反,我们把列弄窄一点(列宽减去两侧的补白),之后用相对定位把它们移至正确的位置。例如,我们用了 2% 的补白,则 30% 的列将减至 26%,40% 的列减至 36%。用相对定位移回列时需谨记,现在列变窄了,所以当它们一起像最初那样左浮动时,每一个需要比上一个移动更远的距离。

可点击放大缩小

完整的CSS

为了使布局保持在小宽度我在每个内容列增加了overflow:hidden; 这将切去超出列宽的东东,并阻止其干扰其他布局。重申一下,这只是 IE 的问题,其他所有浏览器会保持正确的布局,不管列内是虾米。如果你真想这样做,可以用 IE 条件注释只对 IE 写规则。

#container3 {
float:left;
background:green;
overflow:hidden;
position:relative;
}
#container2 {
float:left;
background:yellow;
position:relative;
right:30%;
}
#container1 {
float:left;
width:100%;
background:red;
position:relative;
right:40%;
}
#col1 {
float:left;
width:26%;
position:relative;
left:72%;
overflow:hidden;
}
#col2 {
float:left;
width:36%;
position:relative;
left:76%;
overflow:hidden;
}
#col3 {
float:left;
width:26%;
position:relative;
left:80%;
overflow:hidden;
}

评论

此博客中的热门博文

面试二代:二逼大猜谜

    Sent to you by Gang.Rock via Google Reader:     面试二代:二逼大猜谜 via 译言-精品外文翻译 by rose-tattoo on 11/29/08 译者: rose-tattoo   几年前,微软发现在资源上出了点乱子,说白了吧,是人力资源上出了乱子。其实是这个样子滴: 招聘的大门常打开,应聘的人也不少来,可是来应聘的人跟岗位怎么看也对不上号啊。于是他们觉得该重新设计面试方法了。          按照老路子,面试就确定俩事儿:一个是这个人能不能胜任工作,二是这个人不能太各色,要能融入组织。微软的面试2。0呢,除了这俩条,还加了一个:冷不丁的给应聘的一个根本不靠谱的问题,甚至是让人摸不找头脑,极其二B的提问,看看他们怎么个反映。         一般来说吧,一个应聘的如果本来就爱玩文字游戏,他(她)在面试的时候也会乐于解答二b问题。换句话说,如果应聘人爱吃烙饼,那他面试的时候也会爱吃。看明白了么?这个大猜谜跟面试程序员跟本他妈的挨不上边儿。       如果你还不知道面试2。0都有什么样的问题,我给你展一眼。   波音747有多重? 有个暗盒子,里面仨灯泡,外面仨开关,线全接好了后盒子只能开一次,你怎么知道那个开关开那个灯? 你和仨人在峡谷里要过一个破桥,你一分钟能过去,另外哪仨人得分别用二,五,十,分钟才能过去。过桥得用手电,你们只有一个,你们怎么才能用最快的时间过去?      其实吧,这样的问题都是扯淡,你要是非用常识和实践方法去解答那就更二了。就拿我来说吧,我肯定过不了这些问题,而且非常有可能答成这个操性:         那我得问问波音公司。。。什么?我不能问他们?啊。。。那我就问图书馆里的人儿,你想啊,他们一天到晚就查书啊,他们就是干这个的啊! 这是谁他妈的弄的破盒子啊?你放心,我肯定能弄好,不过我还没看见这盒子什么样儿呢,你怎么知道我弄不好啊??? 太明显了。我们必须扔...

看看资本主义是如何“充分剥夺”员工的剩余价值的

初中那阵子学的"资本主义如何剥削员工的剩余价值"我一直记忆犹新,老师说:他们通虚伪的福利和看上去不错的工作环境来拉拢员工、掩盖他们的丑陋行为,这 些都是资本家用来更大程度地榨取员工的剩余价值的无耻的方法。当时真是痛恨这些资本家,发誓今后一定要去解放哪些受苦受难的员工,虽然放学回家还不知道有 没有饭吃饱。今天在网上看到一些google的瑞士苏黎世的办公室环境图片,不由得佩服恩师啊,他说得太JB正确了,google就是用如下图的糖衣炮弹 来麻醉他的员工,让员工一辈子被榨取剩余价值。 还是我朝那些在自由落体公司的员工好啊,没有糖衣炮弹的腐蚀、生活在民族大企业的环境里,无论男女都喜欢玩极限运动----自由落体运动。 好了,上图吧!

冉云飞:向成都人推荐本期《亚洲周刊》

作者:冉云飞 | 评论(0) | 标签:环保, 权益, 分子 大地震前的5月,有香江一行,与梁文道兄一起做了一期爱国主义和愤青节目,在独立中文笔会做了个"博客写作和言论自由"的演讲,《亚洲周刊》总编辑邱立本先生邀我到他们刊物去做一个小型的交流。这个交流,后来经马楠女史的录音整理(我还没校过,真是时不我待啊),刊载于敝博,名叫《中国民间维权运动:以成都为例》( http://www.bullog.cn/blogs/ranyunfei/archives/156288.aspx ),大家可以看到。当初讲四川民间维权运动的时候,我还没有讲到现在已在狱中的黄琦先生创办的"六四天网",我也没有讲到在四川组党的刘贤斌、欧阳懿等先生,现在一并作个小补充,算是向他们致敬。以后我用一本书来写我认识的四川牛人、汉子(包括长期在四川生活,或者与四川关系极深者)官方称为"反动分子"的人,书名就叫《四川反动分子》,相当于太史公给诸位写列传。现初步罗列一个名单(挂一漏万,以后会续补):胡平、余杰、王怡、廖亦武、徐友渔、陈奎德、齐家贞、武宜三、廖天琪、谭作人、蔡楚、蔡咏梅、周钰樵、肖雪慧、黄琦、陈云飞、郭发财等。"老一辈反动分子"我会写胡绩伟、谢韬、流沙河、曾伯炎、黄一龙、张和光、张先痴、陆清福、朱国干、郭炎、黄承勋、王建军、杨泽泉等。自由与民主之追求者,岂止川人哉!各地的朋友,都可以写写你们本地的"反动分子",为吾国之终得民主自由做出我们自己的贡献。 为什么想到要写《四川反动分子》一书呢?就是想起一位我认识多年的四川汉子:谭作人。我与老谭交往多年,知道这"老几"(川语,不好翻译,在这里相当于"哥们儿",但这翻译哪能罄其义呢)常年为民主自由做贡献,常从实事做起,从不懈怠。而且最好玩的是,我后来才知道他是我母校的子弟,说起自己的父亲是川大历史系的老师,我马上猜到他父亲是谭英华,真可谓其来有自啊。说起他父亲许多人可能不知晓,但我可以是受惠非浅,早年读关于食货志的书,我可是把《两唐书食货志校读记》当作我读新、旧唐书最重要的参考书来读的啊。能在谭先生身后认识其哲嗣并成为朋友,真是快何如哉!说起四川大学历史系,很多人只知徐中舒、缪彦威(杨联陞先生内兄)二先生,其实川大历...