【转】CSS深入理解流体特性和BFC特性下多栏自适应布局
这篇文章发布于 2015年02月12日,星期四,23:36,归类于 css相关。 阅读 30873 次, 今日 63 次
by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=4588
一、开篇之言
要说web上实现两栏自适应布局的方法,一双手都数不过来。不知大家有没有细想过,为什么这些方法可以实现自适应布局呢?
本文就将深入探讨下流体特性和BFC特性下的两栏自适应布局,还是针对传统布局。一些现代布局,如弹性盒子模型布局(Flexbox Layout),格栅布局(Grid Layout)不在本文探讨之类。
有些人看了个标题,以及看了前面一两段,发现,都是我知道的概念嘛,什么流动性,什么BFC~~于是,就悻悻离开了。这就是我们常说的浮躁,保持一颗谦逊的心,细细阅读,你会发现,其中一定有你所没有关注过的地方,所谓三人行必有我师。没错,这句话就是写给你看的,同时也是自我内省与监督。
二、块状元素的流体特性与自适应布局
流体特性
块状水平元素,如div
元素(下同),在默认情况下(非浮动、绝对定位等),水平方向会自动填满外部的容器;如果有margin-left/margin-right
, padding-left/padding-right
, border-left-width/border-right-width
等,实际内容区域会响应变窄。
一图胜千言,一例胜千图。可参考下面例子,感受下div
元素的流体特性:
图片宽度一直width:100%
,依次点击3个按钮,结果随着margin
, padding
, border
的出现,其可用宽度自动跟着减小,形成了自适应效果。就像放在容器中的水流一样,内容区域会随着margin
, padding
, border
的出现自动填满剩余空间,这就是块状元素的流体特性。
流体特性
下面,我们稍微做一个调整,div
距离容器左侧margin
150
像素,里面的图片同样100%
自适应内容区域。HTML如下:
.flow-box {
width: 500px; background-color: #eee; overflow:auto; resize:horizontal;
}
.flow-content {
margin-left: 150px;
}
<div class="flow-box">
<div class="flow-content"><img src="mm1.jpg" width="100%" height="190"></div>
</div>
图片右下角有两道斜杠,我们可以resize拉伸(现代浏览器,且非移动访问),会发现,左侧永远150像素留白,而图片随着容器宽度变化而自适应变化了。
此时,我们需要好好利用左侧150像素的留白间距,岂不是就可以实现两栏自适应效果!?
为了不影响原本的流体特性,我们可以使用破坏性属性,如浮动(float:left),或者绝对定位(position:absolute)。
我们直接HTML如下调整即可:
<div class="flow-box">
<img src="mm1.jpg" width="128" style="float:left;">
<div class="flow-content"><img src="mm1.jpg" width="100%" height="190"></div>
</div>
<div class="flow-box">
<img src="mm1.jpg" width="128" style="position:absolute;">
<div class="flow-content"><img src="mm1.jpg" width="100%" height="190"></div>
</div>
结果分别如下:
当然,你可以左侧有多个浮动,或者左浮动+右浮动。于是,我们不仅可以实现两栏自适应效果,多栏自适应效果也不在话下。
然而,利用块状元素流体特性实现的自适应布局有个不足,就是,我们需要知道浮动或绝对定位内容的尺寸。然后,流体内容才能有对应的margin
或padding
或border
值进行位置修正。于是,问题来了,我们没法单纯使用一个公用的类名,类似.clearfix
这样,整站通用。因为不同自适应场景的留白距离是不一样的。
此时,我们可以利用块状元素的BFC特定实现更强大更智能的多栏自适应布局(本文重点)。
三、元素的BFC特性与自适应布局
1. BFC元素简介与基本表现
BFC全称”Block Formatting Context”, 中文为“块级格式化上下文”。啪啦啪啦特性什么的,一言难尽,大家可以自行去查找,我这里不详述,免得乱了主次,总之,记住这么一句话:BFC元素特性表现原则就是,内部子元素再怎么翻江倒海,翻云覆雨都不会影响外部的元素。所以,避免margin穿透啊,清除浮动什么的也好理解了。
什么时候会触发BFC呢?常见的如下:
float
的值不为none
。overflow
的值为auto
,scroll
或hidden
。display
的值为table-cell
,table-caption
,inline-block
中的任何一个。position
的值不为relative
和static
。
BFC特性很多,而我们这里,只关心一个,和float
元素做相邻兄弟时候的表现。
如果是上面介绍的流体特性div
, 当其和浮动元素当兄弟的时候,是覆盖的关系(可以脑补下文字环绕图片效果)。但是,元素BFC化后,本着“里面惊天抱诈(和谐)炸成鬼,外面依然泰然钓大鱼”的原则,自然是不会与浮动重叠的(你想啊,要是出来个clear:both
还不跟外面浮动干上一架啊),因此,块状相邻,点击下面按钮感受下。
会发现,普通流体元素BFC后,为了和浮动元素不产生任何交集,顺着浮动边缘形成自己的封闭上下文。如下截图:
同时,元素原本的流体特性依然保留了。哈,这个很重要,也就是,虽然不与浮动交集,自动退避浮动元素宽度的距离,但,本身作为普通元素的流动性依然存在,反映在布局上就是自动填满除去浮动内容以外的剩余空间。哟,这不就是自适应布局嘛!!
2. BFC自适应布局模块间的间距
然而,模块过于亲密接触,可能不是我们想要的。一般而言,我们需要一点间距。
说到间距,我们的第一反应就是margin
. 于是,我们给BFC元素增加一个margin-left:20px
, CSS代码如下:
.float-left {
float: left;
}
.follow-content {
margin-left: 20px;
background-color: #cad5eb;
overflow: hidden;
}
结果……纳尼~ 怎么还是像狗屁膏药贴在一起啊??
您可以狠狠地点击这里:BFC元素增加一个margin无效demo
实际上,这里的margin并不是无效,而是值不够大,鞭长莫及啊!
用一个形象的Gif表示就是下面这样:
左侧浮动的图片就好比上面Gif图片中男孩的胳膊,妹子就是BFC元素,结果两人紧密接触。然后,margin-left
就是妹子的胳膊个脚,虽然也甩出去了,可惜长度有限,于是,毫无影响。
如果按照上面的解释,那我们把margin-left:20px
改成margin-left:150px
就应该有间距了? 一试便知!
.float-left {
float: left;
}
.follow-content {
margin-left: 150px;
background-color: #cad5eb;
overflow: hidden;
}
结果,当当当当:
注意:我这里举margin
这个例子,不是让大家这样使用,只是为了让大家可以深入理解BFC元素与浮动元素混排的特性表现。实际开发,我们完全没有必要对BFC元素设置margin
, 因为又回到了流体布局,明明是固定的15像素间距,但是,每个布局都要写一个不同的margin
值,完全没有重用价值。
但是,间距部分的高潮来了!
我们可以使用浮动元素的margin-right
或者padding-right
轻松实现间距效果。间距是20
像素,直接:
.float-left {
float: left;
margin-right: 20px;
}
与浮动元素的宽度是多少没有任何关系。不仅如此,我们还可以使用BFC元素的padding-left
撑开间距(虽然margin-left
作用鸡肋)。
于是,我们可能就会有:
.l { float: left; }
.ovh { overflow: hidden; }
的自适应固定搭配。再配合zxx.lib.cssCSS样式库的margin
和padding
家族,快速布局可谓所向披靡。
3. 与纯流体特性布局的优势
BFC自适应布局优势我总结了下面2点:
- 自适应内容由于封闭,更健壮,容错性强。比方说,内部
clear:both
不会与兄弟float
产生矛盾。而纯流体布局,clear:both
会让后面内容无法和float
元素在一个水平上,产生布局问题。 - 自适应内容自动填满浮动以为区域,无需关心浮动元素宽度,可以整站大规模应用。而纯流体布局,需要大小不确定的
margin
/padding
等值撑开合适间距,无法CSS组件化。
如下效果,图片能大能小,布局依然良好:
而CSS代码就是非常简单的:
.float-left {
float: left; margin-right: 20px;
}
.bfc-content {
overflow: hidden; background-color: #beceeb;
}
可以说,有了BFC自适应布局,基本上没有了纯流体特性布局存在的价值。然而,只是理论上如此。如果,BFC自适应布局真那么吊炸天,那为何并没有口口相传呢?
那我们就得进一步深入理解了。
4. BFC元素家族与自适应布局面面观
理论上,任何BFC元素和浮动搞基的时候,都可以实现自动填充的自适应布局。
但是,由于绝大多数的触发BFC的属性自身有一些古怪的特性,所以,实际操作的时候,能兼顾流体特性和BFC特性来实现无敌自适应布局的属性并不多。下面我们牵驴遛马一个一个瞅瞅(类似行为仅出1个代表示意,你懂的,如float:left/right
):
- float:left 浮动元素本身BFC化,然而浮动元素有破坏性和包裹性,失去了元素本身的流体自适应性,因此,无法用来实现自动填满容器的自适应布局。不过,其因兼容性还算良好,与堆积木这种现实认知匹配,上手简单,因此在旧时代被大肆使用,也就是常说的“浮动布局”,也算阴差阳错开创了自己的一套布局。
- position:absolute 这个脱离文档流有些严重,过于清高,不跟普通小伙伴玩耍,我就不说什么了……
- overflow:hidden 这个超棒的哦!不像浮动和绝对定位,玩得有点过。也就是溢出剪裁什么的,本身还是个很普通的元素。因此,块状元素的流体特性保存相当完好,附上BFC的独立区域特性,可谓如虎添翼,宇宙无敌!哈无诶瓦(However), 就跟清除浮动:
.clearfix { overflow: hidden; _zoom: 1; }
一样。由于很多场景我们是不能
overflow:hidden
的,因此,无法作为一个通用CSS类整站大规模使用。因此,float+overflow
的自适应布局,我们可以在局部(你确定不会有什么被剪裁的情况下)很happy地使用。 - display:inline-block CSS届最伟大的声明之一,但是,在这里,就有些捉襟见肘了。
display:inline-block
会让元素尺寸包裹收缩,完全就不是我们想要的block
水平的流动特性。唉,只能是一声叹气一枪毙掉的命!然而,峰回路转,世事难料。大家应该知道,IE6/IE7浏览器下,block
水平的元素设置display:inline-block
元素还是block
水平,也就是还是会自适应容器的可用宽度显示。于是,我们就阴差阳错得到一个比overflow:hidden
更牛逼的声明,即BFC特性加身,又流体特性保留。.float-left {
float: left;
}
.bfc-content {
display: inline-block;
}当然,
*zoom: 1
也是类似效果,不过只适用于低级的IE浏览器,如IE7~ - display:table-cell 让元素表现得像单元格一样,IE8+以上浏览器才支持。跟
display:inline-block
一样,会跟随内部元素的宽度显示,看样子也是不合适的命。但是,单元格有个非常神奇的特性,就是你宽度值设置地再大,大到西伯利亚,实际宽度也不会超过表格容器的宽度。因此,如果我们把
display:table-cell
这个BFC元素宽度设置很大,比方说3000像素。那其实就跟block
水平元素自动适应容器空间效果一模一样了。除非你的容器宽度超过3000像素,实际上,一般web页面不会有3000像素宽的模块的。所以,要是你实在不放心,设个9999
像素值好了!.float-left {
float: left;
}
.bfc-content {
display: table-cell; width: 9999px;
}看上去,好像还不错。但是,还是有两点制约,一是IE8+以上浏览器兼容,有些苦逼的团队还要管IE6;二是应付连续英文字符换行有些吃力(可以嵌套
table-layout:fixed
解决)。但是,总体来看,适用的场景要比overflow:hidden
广博很多。 - display:table-row 对
width
无感,无法自适应剩余容器空间。 - display:table-caption 一无是处……还有其他声明也都是一无是处,我就不全部展开了……
总结:我们对BFC声明家族大致过了一遍,能担任自适应布局重任的也就是:
overflow:auto/hidden
IE7+display:inline-block
IE6/IE7display:table-cell
IE8+
由于overflow有剪裁和出现滚动条等隐患,不适合作为整站通用类,于是,最后,类似清除浮动的通用类语句:
.clearfix {
*zoom: 1;
}
.clearfix:after {
content: ''; display: table; clear: both;
}
两栏或多栏自适应布局的通用类语句是(block
水平标签,需配合浮动):
.cell {
display: table-cell; width: 9999px;
*display: inline-block; *width: auto;
}
这就是zxx.lib.cssCSS样式库中.cell
的由来!
当然,由于和浮动元素合作,清除浮动还是要的,于是,就有了.fix
+ .l/.r
+ .cell
的无敌组合,可以多栏,也可以无限嵌套。
如果是局部,且确认安全;或有连续英文字符换行的隐患,你也可以使用.fix
+ .l/.r
+ .ovh
的无敌组合,可以多栏,也可以无限嵌套。
四、结束之言
估计本文是春节前的最后一篇文章了,小生在这里提前祝大家「羊年快乐」「万事如意」「事业蒸蒸日上」!
另,本文内容非权威,多个人理解与感悟,仅供参考。欢迎交流,提出您的真知灼见!
感谢阅读!
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:http://www.zhangxinxu.com/wordpress/?p=4588
(本篇完)


- 我所知道的几种display:table-cell的应用 (0.291)
- display:inline-block/text-align:justify下列表的两端对齐布局 (0.255)
- display:table-cell自适应布局下连续单词字符换行 (0.240)
- border-collapse与table td边框opacity透明度诡异解析 (0.240)
- 大小不固定的图片、多行文字的水平垂直居中 (0.236)
- CSS样式分离之再分离 (0.236)
- 对overflow与zoom"清除浮动"的一些认识 (0.200)
- 纯CSS实现侧边栏/分栏高度自动相等 (0.200)
- css margin的相关属性,问题及应用 (0.180)
- 页面重构“鑫三无准则” 之“无宽度”准则 (0.180)
- 折腾:瀑布流布局(基于多栏列表流体布局实现) (RANDOM - 0.055)
标签: BFC, display:inline-block, display:table-cell, inline-block, overflow:hidden, table-cell, 布局, 流动性布局, 自适应布局
发表评论(目前29 条评论)
名称 (必须)
邮件地址(不会被公开) (必须)
网站
为什么不直接用table表局?说道:
一直有个疑惑没理解,为什么很多时候选择设置display:table-cell而不直接用table.
张兄在这一篇博文中所说的,如果我不考虑语义问题,比如我做企业内部专用的系统,我直接表格布局不是能更直接的解决么,难道仅是因为直接用table布局显得很low!!!-
-
Tab说道:
个人理解为何BFC元素margin-left:10px,是相对容器最左边缘的。
根据float特性,它完全脱离normal flow,对normal flow中的块级无影响,但是对块级元素行盒宽度有影响:缩小宽度
懒惰的丑子说道:
张大大 我有个问题的:
当.float-left 这个元素高度高于 .follow-content 这个元素的的时候,因为.float-left脱离了文档流这时这个元素底部就会超出包裹他的盒子外边,
我想的解决办法是给.follow-content这个BFC元素设置个最小高度,但是不是很满意,有木有一种方法就是.float-left和.follow-content哪个元素的高度高 我们包裹的盒子就跟随高度最高的那个盒子而撑开
懒惰的丑子说道:
张大大,你的博客是我的乐园,第一次来是解决自适应来的,把代码copy了一份,当时 你的博客走马观花的看了下,(怪自己当初没有深入了解,走了很多弯路,)后来在做自适应布局这块老出问题我就想自己是不是遗漏了什么,在网上搜又看到了你的博客,从此一发不可收拾,没事就是看你的博客,干货好多,自己成长了很多很多!
———————-非常感谢张大大的分享,让我这颗浮躁的心,静了又静,也觉得我这个菜鸟的路还很长,鼓励自己像张大大看齐!
小刘(前端爱好者)说道:
有两个问题。
当你使用bfc 布局时候。
右面不用 overflow ,使用 inline-block。
1. 文字只有几个的时候,为何是 居中显示,不是 靠左显示?
2.文字很多的时候,为何会被挤下去?而不是像 overflow的展现一样?啊,,,,还有个问题。
为撒 bfc 后 就不会被覆盖重叠呢?
讲的不是很清楚。
说它忽略了那个 float吧,可是表现的确实是没重叠,没忽略。
说没忽略吧,可是 margin-left 又像是忽略了。Spear说道:
1、右侧的不知道你有没有添加宽高、若没有的话、文字的大小应该就是盒子的大小
2、 更改为inline-block;(内联块)当字体多到大于右侧剩余的宽度时、自然换行了。把display: inline-block;更改问float: left;结果是一样的。BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
因此, 当BFC外部存在浮动时,它不影响BFC内部Box的布局,BFC会通过变窄,而不与浮动有重叠。
lee说道:
有些人看了个标题,以及看了前面一两段,发现,都是我知道的概念嘛,什么流动性,什么BFC~~于是,就悻悻离开了。这就是我们常说的浮躁,保持一颗谦逊的心,细细阅读,你会发现,其中一定有你所没有关注过的地方,所谓三人行必有我师。没错,这句话就是写给你看的,同时也是自我内省与监督。
赞-
websir说道:
function time(date){
return date.getFullYear()+”年”+ (date.getMonth()+1)+”月”+date.getDate()+”日 星期”+(date.getDay()?0:”日”)+ date.getHours()+”:”+ date.getMinutes()+”:”+ date.getSeconds()+”:”+date.getMilliseconds()
}
setInterval(function(){document.write(time(new Date())+””)},1000)这段代码毫秒会有延迟,不知道是不是和机器的运算效率有关系?或者是不是能通过这种方式模糊的检测一下客户端机器的性能
-
IntPtr说道:
table-cell 的话一般用 width: 100%; 或者 width: 1%; 或者两者配合使用什么的, bootstrap 就这么用的.
ideazhao说道:
张老师再出杰作啊,不浮躁,多思考,多尝试总是有好处的。
【转】CSS深入理解流体特性和BFC特性下多栏自适应布局的更多相关文章
- CSS深入理解流体特性和BFC特性下多栏自适应布局
一.块状元素的流体特性与自适应布局 块状元素像放在容器中的水流一样,内容区域会随着margin, padding, border的出现自动填满剩余空间,这就是块状元素的流体特性. 来一个小实验: di ...
- BFC特性下多栏自适应布局
BFC 已经是一个耳听熟闻的词语了,网上有许多关于 BFC 的文章,介绍了如何触发 BFC 以及 BFC 的一些用处(如清浮动,防止 margin 重叠等).虽然我知道如何利用 BFC 解决这些问题, ...
- css多栏自适应布局
css多栏自适应布局还是需要总结一下的,都是基本功. 一般使用position属性布局,或者用float属性布局,也可以使用display属性. 看资料说position适合首页布局,因为首页内容往往 ...
- css 多栏自适应布局
在页面重构中,我们经常会需要实现多栏布局,例如n栏固定宽度 + m栏自适应宽度的组合,绝对布局+padding+百分比宽度是容易想到的比较暴力的解决方法,但是作为未来的"工程师", ...
- 你知道BFC、IFC、FFC、GFC及多栏自适应布局吗?
FC(Formatting Context)格式化内容,常见的FC有BFC.IFC.FFC.GFC四种类型,BFC和IFC是W3C CSS2.1规范提出的概念,FFC和GFC是W3C CSS3规范提出 ...
- css实现等高布局 两栏自适应布局 三栏自适应布局
等高布局: HTML结构如下: <div class="wrapper"> <div class="box"> <h1>.. ...
- 使用CSS实现三栏自适应布局(两边宽度固定,中间自适应)
来源:http://blog.csdn.net/cinderella_hou/article/details/52156333 所谓三列自适应布局指的是两边定宽,中间block宽度自适应.这道题在今年 ...
- css布局 - 两栏自适应布局的几种实现方法汇总
这种两列布局的样式是我们在平时工作中非常常见的设计,同时也是面试中要求实现的高频题.很有必要掌握以备不时之需: 整理了几种实现方法,当然,风骚的代码不止这几种能实现,欢迎各位的补充. 方法汇总目录 简 ...
- css实现三栏自适应布局(两边固定,中间自适应)以及优缺点
方法一:绝对定位(absolute + margin) 原理:给左右两边的元素设置absolute,这样左右两边的元素脱离标准文档流的控制,中间的元素自然会上来,然后给中间的元素设置margin留出左 ...
随机推荐
- Windows Store App 用户库文件分组
在Windows应用商店应用程序中浏览用户库中的文件时,可以将文件或者文件夹分组显示,以便于进行分类浏览,这类似于音乐库中的文件可以按照艺术家名称.创建日期或者评级等多种方式进行分类.本节内容将会介绍 ...
- 请尝试使用 Console.Read。错误原因
当出现错误: 如果应用程序没有控制台或控制台输入已通过文件进行了重定向,则无法读取键.请尝试使用 Console.Read. 一定是在非控制台应用程序中用了Console.ReadKey(); Con ...
- hdu 1047 (big integer sum, fgets or scanf, make you func return useful infos) 分类: hdoj 2015-06-18 08:21 39人阅读 评论(0) 收藏
errors made, boundary conditions, <= vs < , decreasing vs increasing , ++, –, '0'/'1' vs 0/1 p ...
- SQL Server2012关于表内事项出现次数降序排列(存储过程)
USE [growup] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[S_GetRanking ...
- 常用排序算法的Java实现 - 1
学习编程语言时, 我们会接触到许多排序算法, 这里总结了一下常见的排序算法. 不定期更新. * 其实在Java中存在如Collections.sort()这样的方法来自动为我们排序, 不过学习排序算法 ...
- MySQL数据库1 - 基本概念及安装
一.数据管理技术的产生和发展: 1.人工管理阶段 - 效率低,成本高(文字) 2.文件系统阶段 - 易于存储,处理速度快,数据形式丰富(文字,声音,图片...磁带,磁盘) 3.数据库系统阶段 - 易于 ...
- C++指针比较的问题
在C++里面,指针的比较是要保障type-safe的,也就是说,这两个指针必须是convertible的:从一个指针能够直接转换到另一个指针(有中间路径不算,不然都往void*转没完没了),顺序不限 ...
- c++嵌套类-内存分配
首先看下列代码:int main(){ double *p; printf("sizeof(int):%d\nsizeof(double):%d\nsizeof(ptr):%d\ ...
- Python KNN算法
机器学习新手,接触的是<机器学习实战>这本书,感觉书中描述简单易懂,但对于python语言不熟悉的我,也有很大的空间.今天学习的是k-近邻算法. 1. 简述机器学习 在日常生活中,人们很难 ...
- 2.b统计字符串长度
import java.util.*;public class Main { public static void main(String args[]){ String a; Sc ...