position跟display、margin collapse、overflow、float这些特性相互叠加后会怎么样?
这是寒冬大神提出的一个题目,刚开始看到这题的时候完全不知道从什么地方回答起好,题目内容比较广泛,找不到针对点。后来我觉得这个题目应该能拆成几个点来回答:1、'display'、'position' 和 'float' 的相互关系;2、position跟display、overflow、float下的margin collapse。
那么这三种布局和框形成的关键特性( display )之间有什么关系呢,请看下面流程图:
转换对应表:
设定值 | 计算值 |
---|---|
inline-table | table |
inline, run-in, table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, table-caption, inline-block |
block |
其他 | 同设定值 |
总的来说,可以把它看作是一个类似优先级的机制, "position:absolute" 和 "position:fixed" 优先级最高,有它存在的时候,浮动不起作用,'display' 的值也需要调整; 其次,元素的 'float' 特性的值不是 "none" 的时候或者它是根元素的时候,调整 'display' 的值; 最后,非根元素,并且非浮动元素,并且非绝对定位的元素,'display' 特性值同设置值。
这从另一个侧面说明了一个问题:浮动或绝对定位的元素,只能是块元素或表格。
1. 'display' 的值为 'none'
如果 'display' 的值为 'none',那么 'position' 和 'float' 不起作用。在这种情况下,元素不产生框。因此浮动和定位无效。
2. 'position' 的值是 'absolute' 或 'fixed'
否则,如果 'position' 的值是 'absolute' 或 'fixed',框就是绝对定位的,'float' 计算后的值应该是 'none',并且,'display' 会被按照上表设置。 框的位置将由 'top','right','bottom' 和 'left' 属性和该框的包含块确定。
也就是说,当元素是绝对定位时,浮动失效,'display' 会被按规则重置。
示例代码:

<script type="text/javascript">
function getStyle(obj, style) {
var _style = (style == "float") ? "styleFloat" : style;
return document.defaultView ? document.defaultView.getComputedStyle(obj, null).getPropertyValue(style) : obj.currentStyle[_style.replace(/-[a-z]/g, function() {
return arguments[0].charAt(1).toUpperCase();
})];
}
window.onload = function() {
document.getElementById("info").innerHTML = "float : " + getStyle(document.getElementById("test"), "float") +
"<br/>display : " + getStyle(document.getElementById("test"), "display");
}
</script>
<div id="test" style="position:absolute; float:left;display:inline;"></div>
<div id="info"></div>

上面代码中有一个既是绝对定位又是浮动的元素,以上代码可取出其 'display' 和 'float' 的计算值。
IE 中,'float' 值和 'display' 的特性值未发生变化,还是 "float: left; display: inline"。
其他浏览器中计算后的结果是:"float: none; display: block"。
3. 'float' 的值不是 "none"
如果 'float' 的值不是 "none",该框浮动并且 'display' 会被按照转换对应表设置。

<!DOCTYPE html>
<script type="text/javascript">
function getStyle(obj, style) {
var _style = (style == "float") ? "styleFloat" : style;
return document.defaultView ? document.defaultView.getComputedStyle(obj, null).getPropertyValue(style) : obj.currentStyle[_style.replace(/-[a-z]/g, function() {
return arguments[0].charAt(1).toUpperCase();
})];
}
window.onload = function() {
document.getElementById("info").innerHTML = "display : " + getStyle(document.getElementById("test"), "display");
}
</script>
<span id="test" style="width:100px; height:100px; border:1px solid red;float:left;">float span</span>
<div id="info"></div>

按照规则,SPAN 是行内元素,因此不能够设置其宽度和高度。但是浮动后,'display' 值按照转换对应表设置后,成为块级元素。
IE 中截图:
其他浏览器中:
4. 元素是根元素
如果元素是根元素,'display' 的值按照转换对应表设置。
5. 否则,应用指定的 'display' 特性值。
二、position跟display、overflow、float下的margin collapse。
margin collapse我觉得这里的意思应该是Collapsing margins,即外边距折叠,指的是毗邻的两个或多个外边距 (margin) 会合并成一个外边距。
其中所说的 margin 毗邻,可以归结为以下两点:
- 这两个或多个外边距没有被非空内容、padding、border 或 clear 分隔开。
- 这些 margin 都处于普通流中。
1.两个或多个毗邻的普通流中的块元素垂直方向上的 margin 会折叠。
注意一点,在没有被分隔开的情况下,一个元素的 margin-top 会和它普通流中的第一个子元素(非浮动元素等)的 margin-top 相邻; 只有在一个元素的 height 是 "auto" 的情况下,它的 margin-bottom 才会和它普通流中的最后一个子元素(非浮动元素等)的 margin-bottom 相邻。
示例代码:

<div style="border:1px solid red; width:100px;">
<div style="margin:50px 0; height:50px; width:50px;">
<div style="margin:20px 0;">
<div style="margin:100px 0;">B</div>
</div>
</div>
</div>

效果图:
以上代码中,margin 会把 B 的包含块撑开。
如果一个元素的 height 特性的值不是 auto,那么它的 margin-bottom 和它子元素的 margin-bottom 不算相邻,因此,不会发生折叠。 margin-top 没有此限制,所以是 100px,margin-bottom 没有折叠,只有 50px。
垂直方向
是指具体的方位,只有垂直方向的 margin 才会折叠,也就是说,水平方向的 margin 不会发生折叠的现象。
折叠后 margin 的计算
1). 参与折叠的 margin 都是正值
例子:
<div style="height:50px; margin-bottom:50px;width:50px; ">A</div>
<div style="height:50px;margin-top:100px; width:50px; ">B</div>
示意图:
在 margin 都是正数的情况下,取其中 margin 较大的值为最终 margin 值。
2). 参与折叠的 margin 都是负值
当 margin 都是负值的时候,取的是其中绝对值较大的,然后,从 0 位置,负向位移。
示例代码:
<div style="height:100px; margin-bottom:-75px;width:100px; ">A</div>
<div style="height:100px;margin-top:-50px; margin-left:50px; width:100px; ">B</div>
示意图:
3). 参与折叠的 margin 中有正值,有负值
如果,毗邻的 margin 中有正值,同时存在负值会怎样呢?有正有负,先取出负 margin 中绝对值中最大的,然后,和正 margin 值中最大的 margin 相加。
示例代码:
<div style="height:50px; margin-bottom:-50px;width:50px; ">A</div>
<div style="height:50px;margin-top:100px; width:50px; ">B</div>
示意图:
上面的例子最终的 margin 应该是 100 + (-50) = 50px。
4). 相邻的 margin 要一起参与计算,不得分步计算
要注意,相邻的元素不一定非要是兄弟节点,父子节点也可以,即使不是兄弟父子节点也可以相邻。
而且,在计算时,相邻的 margin 要一起参与计算,不得分步计算。
一个复杂的实例:

<div style="margin:50px 0; width:50px;">
<div style="margin:-60px 0;">
<div style="margin:150px 0;">A</div>
</div>
</div>
<div style="margin:-100px 0; width:50px;">
<div style="margin:-120px 0;>
<div style="margin:200px 0;">B</div>
</div>
</div>

错误的计算方式:算 A 和 B 之间的 margin,分别算 A 和其父元素的折叠,然后与其父元素的父元素的折叠,这个值算出来之后,应该是 90px。依此法算出 B 的为 80px;然后,A和B折叠,margin 为 90px。
请注意,多个 margin 相邻折叠成一个 margin,所以计算的时候,应该取所有相关的值一起计算,而不能分开分步来算。
以上例子中,A 和 B 之间的 margin 折叠产生的 margin,是6个相邻 margin 折叠的结果。将其 margin 值分为两组:
- 正值:50px,150px,200px
- 负值:-60px,-100px,-120px
根据有正有负时的计算规则,正值的最大值为 200px,负值中绝对值最大的是 -120px,所以,最终折叠后的 margin 应该是 200 + (-120) = 80px。
2.浮动元素、inline-block 元素、绝对定位元素的 margin 不会和垂直方向上其他元素的 margin 折叠
浮动元素的 margin 在垂直方向上也不会发生 margin 折叠,即使和它相邻的子元素也不会。
<div style="margin-bottom:50px;width:50px; height:50px; ">A</div>
<div style="margin-top:50px; width:100px; height:100px; float:left;">
<div style="margin-top:50px;">B</div>
</div>
示意图:
两个绿色的块儿之间,相距100px,而若 B 和它的浮动包含块发生 margin 折叠的话,金色的条应该位于绿色块的最上方,显然,没有发生折叠。inline-block 元素、绝对定位元素的 margin同样如此, 不会和垂直方向上其他元素的 margin 折叠。
3.创建了块级格式化上下文的元素,不和它的子元素发生 margin 折叠
以 “overflow : hidden” 的元素为例:
<div style="margin-top:50px; width:100px; height:100px; overflow:hidden;">
<div style="margin-top:50px; ">B</div>
</div>
若 B 和它的 "overflow:hidden" 包含块发生 margin 折叠的话,金色的条应该位于绿色块的最上方,否则,没有发生。
示意图:
4.元素自身的 margin-bottom 和 margin-top 相邻时也会折叠
自身 margin-bottom 和 margin-top 相邻,只能是自身内容为空,垂直方向上 border、padding 为 0。
示例:
<div style="border:1px solid red; width:100px;">
<div style="margin-top: 100px;margin-bottom: 50px;></div>
</div>
以上代码运行后,我们讲得到的是红色边框的正方形,方框的宽高都应该是 100px,高度不应该是 150px。
示意图:
position跟display、margin collapse、overflow、float这些特性相互叠加后会怎么样?的更多相关文章
- 由position属性引申的关于css的进阶讨论(包含块、BFC、margin collapse)
写这篇文章的起因是源于这篇文章:谈谈面试与面试题 中关于position的讨论,文中一开始就说的这句话: 面试的时候问个css的position属性能刷掉一半的人这是啥情况…… 其实这问题我本来打算的 ...
- CSS position overflow float 属性 详解
position overflow float 几个属性比较容易混淆,写一段代码详解各自具体情况: position在w3school的可能取值: 值 描述 absolute 生成绝对定位的元素,相 ...
- 深入理解BFC和Margin Collapse
深入理解BFC和Margin Collapse BFC的理解与应用 首先我们来看看w3c规范对BFC的解释,其实对于这种概念的学习上,我们总是建议首先寻找官方的定义,因为原则上来说官方的才是最权威 ...
- Python:margin collapse
margin collapse:边界 折叠/重叠/坍塌 此种现象只会垂直方向并且要满足一定条件时才会出现这种现象. https://tech.youzan.com/css-margin-collaps ...
- web前端学习部落22群 明白何谓Margin Collapse
明白何谓Margin Collapse 不同于其他很多属性,盒模型中垂直方向上的Margin会在相遇时发生崩塌,也就是说当某个元素的底部Margin与另一个元素的顶部Margin相邻时,只有二者中的较 ...
- [Web 前端] CSS篇之 4. position 和 display 的取值和各自的意思和用法
讲一讲CSS的position/float/display都有哪些取值,它们相互叠加时的行为都是什么? 列出display的值,说明他们的作用.position的值, relative和absolu ...
- css margin collapse
css中存在margin collapse,即边界塌陷或边界重叠. http://www.w3cplus.com/css/understanding-bfc-and-margin-collapse.h ...
- CSS3——分组和嵌套 尺寸 display显示 position定位 overflow float浮动
分组和嵌套 分组选择器 ——————> 嵌套选择器 能适用于选择器内部的选择器的样式 p{ }: 为所有 p 元素指定一个样式. .marked{ }: 为所有 class="m ...
- jsp学习---css基础知识学习,float,position,padding,div,margin
1.常用页面布局 效果图: 代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...
随机推荐
- CVE爬虫抓取漏洞URL
String url1="http://www.cnnvd.org.cn/vulnerability/index/vulcode2/tomcat/vulcode/tomcat/cnnvdid ...
- win8 hyper-v 禁用不必卸载虚拟机
转载:http://tylzwp.blogbus.com/logs/232938121.html 禁用hyperv的目的是使用之前在用的VMware的虚拟机,不必重新处理一遍. 具体操作: 1确报之前 ...
- “WIZnet杯”以太网技术竞赛即将开始!
- [置顶] Maven多模块项目 eclipse热部署 Maven项目实现 tomcat热部署 二
最近看到有好多童鞋比较热衷热部署,特别是多模块的项目,其实这热部署如果多模块比较大资源,容易内存溢出或者电脑卡住,并不建议这么做. 不过了解下也没有关系,这里我就在说说热部署的另外一种方法,因为我之前 ...
- C# 自定义光标 WaitCursor
一种: 把图像文件放到项目的文件夹中 1 如果图像文件是.cur格式: Cursor cur=new Cursor(文件名); this.cursor=cur; 两句话 就完事 2 如果图像文件是其他 ...
- 14条建议,使你的IT职业生涯更上一层楼
摘要:升值为企业IT部门的领导者,是大部分IT技术人员职业生涯的最终追求.但从一般大众中脱颖而出,并非易事.仅仅把本职工作干好远远不够,还需要IT技术人员展示出投身于技术发展的奉献精神及伴随技术发展而 ...
- zoj 3351 Bloodsucker(概率 dp)
题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4530 dp[i]表示现在存在i个吸血鬼要达成目标(全为吸血鬼)天数的数学 ...
- linux aio
前几天nginx的0.8.x正式成为stable,然后看了下代码,发现0.8加入了linux native aio的支持,我们知道在linux下有两种aio,一种是glibc实现的aio,这个比较烂, ...
- Java中的字符串驻留(String Interning)
1. 首先String不属于8种基本数据类型,String是一个对象. 因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. ne ...
- 【原创】batch-GD, SGD, Mini-batch-GD, Stochastic GD, Online-GD -- 大数据背景下的梯度训练算法
机器学习中梯度下降(Gradient Descent, GD)算法只需要计算损失函数的一阶导数,计算代价小,非常适合训练数据非常大的应用. 梯度下降法的物理意义很好理解,就是沿着当前点的梯度方向进行线 ...