纯CSS无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;
- }
全部代码:
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
- <meta http-equiv="Page-Enter" content="revealTrans(Duration=1.0,Transition=12)"/>
- <meta http-equiv="Page-Exit" content="blendTrans(Duration=0.5)" />
- <title>Heroku和Morph AppSpaces:两个Rails托管的新解决方案</title>
- <style type="text/css">
- #header {
- background:#EBCC67;
- }
- #footer {
- background:#A9EA00;
- }
- #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: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;
- }
- </style>
- </head>
- <body>
- <div id="header">AppEngine在本周引起很大反响,它提供了一个简单易用的方法来运行Python写成的Web应用。但是Ruby社区并不需要看Google的脸色,它已经拥有了关于简单部署的解决方案。我们来看两个新的解决方案,它们均是基于Rails开发者使用的公用基础之上构建的。</div>
- <div id="container3">
- <div id="container2">
- <div id="container1">
- <div id="col1">Column 1<br /><p>Heroku和Morph实验室是Ruby on Rails的托管提供商,提供运行Ruby on Rails应用的整套环境。和传统的托管商相比,他们并不仅仅是提供一个服务器给你,而且提供有趣的工具和接口来帮助你更加容易的工作,使你从繁重的安 装、配置、管理和保证服务器安全中解脱出来。两者皆是使用Amazon的EC2网格计算技术来运行应用,因此你可以毫不担心可伸缩性与性能问题。</p></div>
- <div id="col2">Column 2<br /><p>另一个被Heroku和Morph实验室所推崇的重要特性是无痛部署。部署一个新应用只需要几分钟而已:来看看Heroku的即时部署demo和Morph eXchange的6分钟部署demo,部署是多么简单。</p></div>
- <div id="col3">Column 3<br />两者所带来的是如此的相似。InfoQ采访了这两个项目的相关人员,有更多信息奉上。</div>
- </div>
- </div>
- </div>
- <div id="footer">James Lindenbaum阐述了Heroku的独有特性:
- <blockquote>
- Heroku无疑是Rails应用最简单的部署平台。只是简单的把代码放进去,然后启动、运行,没人会做不到这些。Heroku会处理一切,从版本控制到 自动伸缩的协作(基于Amazon的EC2之上)。我们提供一整套工具来开发和管理应用,不管是通过Web接口还是新的扩展API。
- </blockquote>
- Heroku的一个非常有趣的特性就是基于浏览器的开发环境。它参考了Gyre的开发经验,Gyre的开发者Adam Wiggins也是Heroku背后的一员。因此如果你希望快速修改和追加的话,只需要通过浏览器编辑正在运行的应用的源代码,并在修改后自动部署。当然,使用浏览器IDE并不是唯一访问Heroku服务的方法,还可以来看看Heroku的API和外部Git访问。
- </div>
- </body>
- </html>
运行效果:
纯CSS无hacks的跨游览器多列布局的更多相关文章
- 使用基于关系的选择器和伪类选择器创建纯CSS无JavaScript的鼠标移动到上面即可显示的下拉菜单
html代码: <div class="menu-bar"> <ul> <li> <h3 class="text-warning ...
- 纯css无js实现点击事件
<input id="A" type="checkbox"><label for="A"> <span cla ...
- 利用after和before伪类实现chrome浏览器tab选项卡斜边纯css无图制作笔记
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- html实现时间轴_纯css实现响应式竖着/垂直时间抽布局效果
1.概述 html实现用时间点来展示事件发生点来代替用table展示一条条数据,能够给人清晰.一目了然能够看清事情发生的过程,UI页面也显示的那么清晰.如何用css+html做出时间轴展示事件点的?先 ...
- CSS自学笔记(15):CSS3多列布局
在CSS3中,也新增了一些关于文本布局的几个比较简单的属性.通过这些新增的属性,我们可以对文本进行简单的排版,就想报纸和杂志那样. 新增的部分属性,以及浏览器支持情况: 属性 浏览器支持 column ...
- css 左右固定宽度,中间自适应的三列布局
float——浮动布局: 使用浮动,先渲染左右两个元素,分别让他们左右浮动,然后再渲染中间元素,设置它的margin左右边距分别为左右两个元素的宽度. <!DOCTYPE html> &l ...
- 详解纯css实现瀑布流(multi-column多列及flex布局)
瀑布流的布局自我感觉还是很吸引人的,最近又看到实现瀑布流这个做法,在这里记录下,特别的,感觉flex布局实现瀑布流还是有点懵的样子,不过现在就可以明白它的原理了 1.multi-column多列布局实 ...
- 纯css实现瀑布流(multi-column多列及flex布局)
瀑布流的布局自我感觉还是很吸引人的,最近又看到实现瀑布流这个做法,在这里记录下,特别的,感觉flex布局实现瀑布流还是有点懵的样子,不过现在就可以明白它的原理了 1.multi-column多列布局实 ...
- HTML/CSS学习之 三列布局,其中左侧和右侧的部分宽度固定,中间部分宽度随浏览器宽度的变化而自适应变化
第一种方法:绝对定位 <!DOCTYPE html> <html> <head> <title>三列布局</title> <link ...
随机推荐
- p标签里面不能嵌套div
先申明本人代码水平为零起点,刚开始学习前端,所以就是小白.不过大神也是小白变身的么,所以要专心码代码,潜心钻研,haha~ 今天练习了段代码,发现效果和自己想象的不一样: 想了一下估计是<p&g ...
- HTML (1)href与Action,get post
1. href与Action的区别 href只能get参数,action能get参数又能post参数 href一般用于单个连接,可以带参数(URL重写),是采用get方式请求的,在地址栏中可以看到 ...
- DEDECMS批量修改默认文章和列表命名规则的方法
很多人因为添加分类而苦恼,尤其是批量添加的时候,必须要重新修改一下文章命名规则和列表命名规则,都是为了做SEO.如果进行默认值的修改,就会事半功倍.不多说. 一.DEDE5.5修改默认文章命名规则. ...
- PHP迭代器
在所有语言中,所有迭代器都必须具有如下4想功能: 1.回滚迭代器到第一个元素 2.潜行到下一个元素 3.获取当前元素 4.验证是否到最后一个元素了 在PHP中我我们可以通过实现iterator来实现迭 ...
- javascript定义变量和优先级的问题
本文链接: javascript定义变量和优先级的问题.转载请保留. 看下面的代码: if (!("aa" in window)) { alert('oh my god'); ...
- PHP转换IP地址到真实地址的方法详解
本篇文章是对PHP转换IP地址到真实地址的方法进行了详细的分析介绍,需要的朋友参考下 想要把IPv4地址转为真实的地址,肯定要参考IP数据库,商业的IP数据库存储在关系型数据库中,查询和使用都非常 ...
- [Python笔记]第三篇:深浅拷贝、函数
本篇主要内容:深浅拷贝,自定义函数,三目运算,lambda表达式, 深浅拷贝 一.数字和字符串 对于 数字 和 字符串 而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. import ...
- 多目标遗传算法 ------ NSGA-II (部分源码解析)README 算法的部分英文解释
This is the Readme file for NSGA-II code. About the Algorithm--------------------------------------- ...
- 【问题】tableView的每组的头部不不能滚动的解决方案
group模式的解决方案 - (void)scrollViewDidScroll:(UIScrollView*)scrollView { if (scrollView == self.tableVie ...
- 随机数(random)
在测试你的程序是否超时时,可以随机生成一组大数据,进行一下测试. 当然如果你考场上一道题直接读不懂不会做的时候,可以random一下,拼一下RP嘛.2333. #include<cstdio&g ...