这是寒冬大神提出的一个题目,刚开始看到这题的时候完全不知道从什么地方回答起好,题目内容比较广泛,找不到针对点。后来我觉得这个题目应该能拆成几个点来回答:1、'display'、'position' 和 'float' 的相互关系;2、position跟display、overflow、float下的margin collapse。

一、'display'、'position' 和 'float' 的相互关系
首先我们先来看下这3个属性。
display 属性规定元素应该生成的框的类型。 block 象块类型元素一样显示,none 缺省值。象行内元素类型一样显示, inline-block 象行内元素一样显示,但其内容象块类型元素一样显示,list-item 象块类型元素一样显示,并添加样式列表标记(display 还有很多其他值设置,读者自行查找)。
 position 属性规定元素的定位类型。 absolute表示生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位;fixed(老IE不支持)生成绝对定位的元素,相对于浏览器窗口进行定位;relative生成相对定位的元素,相对于其正常位置进行定位;static  默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right z-index 声明)。
 Float也是是一种布局方式,它定义元素在哪个方向浮动。以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元素都可以浮动。浮动元素会生成一个块级框,而不论它本身是何种元素。 在布局过程中也经常会使用它来达到左右并排布局的效果。

那么这三种布局和框形成的关键特性( 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这些特性相互叠加后会怎么样?的更多相关文章

  1. 由position属性引申的关于css的进阶讨论(包含块、BFC、margin collapse)

    写这篇文章的起因是源于这篇文章:谈谈面试与面试题 中关于position的讨论,文中一开始就说的这句话: 面试的时候问个css的position属性能刷掉一半的人这是啥情况…… 其实这问题我本来打算的 ...

  2. CSS position overflow float 属性 详解

    position  overflow float 几个属性比较容易混淆,写一段代码详解各自具体情况: position在w3school的可能取值: 值 描述 absolute 生成绝对定位的元素,相 ...

  3. 深入理解BFC和Margin Collapse

    深入理解BFC和Margin Collapse   BFC的理解与应用 首先我们来看看w3c规范对BFC的解释,其实对于这种概念的学习上,我们总是建议首先寻找官方的定义,因为原则上来说官方的才是最权威 ...

  4. Python:margin collapse

    margin collapse:边界 折叠/重叠/坍塌 此种现象只会垂直方向并且要满足一定条件时才会出现这种现象. https://tech.youzan.com/css-margin-collaps ...

  5. web前端学习部落22群 明白何谓Margin Collapse

    明白何谓Margin Collapse 不同于其他很多属性,盒模型中垂直方向上的Margin会在相遇时发生崩塌,也就是说当某个元素的底部Margin与另一个元素的顶部Margin相邻时,只有二者中的较 ...

  6. [Web 前端] CSS篇之 4. position 和 display 的取值和各自的意思和用法

    讲一讲CSS的position/float/display都有哪些取值,它们相互叠加时的行为都是什么?  列出display的值,说明他们的作用.position的值, relative和absolu ...

  7. css margin collapse

    css中存在margin collapse,即边界塌陷或边界重叠. http://www.w3cplus.com/css/understanding-bfc-and-margin-collapse.h ...

  8. CSS3——分组和嵌套 尺寸 display显示 position定位 overflow float浮动

    分组和嵌套  分组选择器 ——————>   嵌套选择器 能适用于选择器内部的选择器的样式 p{ }: 为所有 p 元素指定一个样式. .marked{ }: 为所有 class="m ...

  9. jsp学习---css基础知识学习,float,position,padding,div,margin

    1.常用页面布局 效果图: 代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8" ...

随机推荐

  1. rand5()产生rand7()

    http://www.cnblogs.com/dwdxdy/archive/2012/07/28/2613135.html 利用rand5()产生rand7().rand5()产生1到5的整数,ran ...

  2. HDMI介绍与流程

    HDMI接口 http://baike.c114.net/view.asp?id=17671-21565442 DDC(Display Data Channel)通道用于HDMI发送和接收端之间交换一 ...

  3. thinkphp 分组

    分组 配置项: // 开启分组 'APP_GROUP_LIST'=>'Home,Admin', // 默认分组 'DEFAULT_GROUP'=>'Home', 涉及分组: 配置文件分组, ...

  4. DSP6455 DSP/BIOS中断配置问题(是否需要ECM-事件组合以及实例)

    2013-06-20 21:08:48 中断的配置有两种常用的方式: 一是通过CSL提供的API进行配置,这种方法相对DSP/BIOS偏底层,也比较麻烦:这种方法要求对中断系统的工作方式很清楚. 二是 ...

  5. ruby中Block, Proc 和 Lambda 浅析

    Block 与Proc的区别: Block是代码块,Proc是对象: 参数列表中最多只能有一个Block, 但是可以有多个Proc或Lambda; Block可以看成是Proc的一个类实例. Proc ...

  6. 【HDOJ】4601 Letter Tree

    挺有意思的一道题,思路肯定是将图转化为Trie树,这样可以求得字典序.然后,按照trie的层次求解.一直wa的原因在于将树转化为线性数据结构时要从原树遍历,从trie遍历就会wa.不同结点可能映射为t ...

  7. C++ 空类默认产生成员函数

    class Empty { Empty(){...} //默认构造函数 ~Empty(){...} //默认析构函数 Empty(const Empty&){...} //拷贝构造函数 Emp ...

  8. [HDU 1695] GCD

    GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  9. [CF 471C] MUH and House of Cards

    C. MUH and House of Cards   Polar bears Menshykov and Uslada from the zoo of St. Petersburg and elep ...

  10. centos 6.5 32位 编译安装Mysql

    groupadd mysql #添加mysql组 useradd -g mysql mysql -s /bin/false #创建用户mysql并加入到mysql组,不允许mysql用户直接登录系统 ...