所谓的文档流,指的是元素排版布局过程中,元素会自动从左往右,从上往下的流式排列。并最终窗体自上而下分成一行行, 并在每行中按从左至右的顺序排放元素。脱离文档流即是元素打乱了这个排列,或是从排版中拿走。

  当前所知的脱离文档流的方式有两种:浮动和定位。

  

a.定位属性positon


  先看一下定位。看一段对定位各个字段的描述,有助于理解

描述
absolute

生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。

元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。

fixed

生成绝对定位的元素,相对于浏览器窗口进行定位。

元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。

relative

生成相对定位的元素,相对于其正常位置进行定位。

因此,"left:20" 会向元素的 LEFT 位置添加 20 像素。

static 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。
inherit 规定应该从父元素继承 position 属性的值。

  position的值为absolute、fixed的元素脱离文档流,static、relative没有脱离文档流

  position定位测试例子(为了不影响定位效果,文字都放在了最后)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!--<script type="text/javascript" src='jquery-1.9.1.js'></script>-->
<style>
*{
margin: 0;
padding: 0;
text-align: right;
color: #FFF;
}
#container{
position: absolute;
left: 20px;
margin-top: 10px;
width: 600px;
height: 600px;
background-color: green;
}
#bigest{
position: static;
left: 20px;
margin-top: 20px;
width: 500px;
height: 500px;
background-color: #ab2;
}
#biger{
position: static;
left: 20px;
margin-top: 30px;
width: 400px;
height: 400px;
background-color: #00f;
}
#big{
position: relative;
left: 20px;
margin-top: 40px;
width: 300px;
height: 300px;
background-color: #000;
}
#normal{
position: static;
margin-left: 20px;
margin-top: 50px;
width: 200px;
height: 200px;
background-color: #aaa;
}
#middle{
position: absolute;
left: 20px;
margin-top: 60px;
width: 100px;
height: 100px;
background-color: #aaa;
}
#small{
position: fixed;
left: 20px;
margin-top: 70px;
height: 50px;
width: 50px;
background-color: #f00;
}
</style>
</head>
<body>
<div id="container">
<div id="bigest">
<div id="biger">
<div id="big">
<div id="normal">
<div id="middle">
<div id="small">small
</div>middle
</div>normal
</div>big
</div>biger
</div>bigest
</div>container
</div>
</body>
</html>

  整体效果截图

  

  结论:

  1.static定位不脱离文档流,设置left/top/right/bottom没有作用,对margin/padding敏感。

  【证据:#bigest定位left没有其作用】

  2.父子节点都是没有脱离文档的两种定位(static、relative)的外边距(margin)会合并,显示效果以最大的那个外边距为准。

  【证据:#bigest,#biger,#big,#normal都是非脱离文档的元素且是父子节点关系,他们的marginTop值分别为20px/30px/40px/50px。#bigest和#biger的外边距合并,合并后的top外边距为30px;然后#biger拿先前合并后的结果和#big外边距合并,合并后top的外边距为40px;最后#big拿先前合并的结果和#normal的外边距合并,合并结果为50px。所以最终合并的外边距为50px。显示效果如下如

  

  当然,这是在没有内边距影响的情况下。如果有内边距影响,那么子元素的外边距会基于父元素的内边距来偏移。如我们设置#big{padding-top: 10px;}属性后,#nomal的margin-top是在#big的padding-top开始偏移的,如图

  

  说道这里对于外边距margin:块级元素的垂直相邻外边距会合并,而行内元素实际上不占上下外边距。行内元素的的左右外边距不会合并。同样地,浮动元素的外边距也不会合并。允许指定负的外边距值,不过使用时要小心。例子:

<style>
#bottom10{
margin-bottom: 10px;
height: 100px;
width: 100px;
background: #ff0;
}
#top50{
margin-top: 50px;
height: 100px;
width: 100px;
background: #f00;
}
</style> <div id='bottom10' >margin-bottom 10px</div>
<div id="top50">margin-top 10px</div>

  效果,最终黄块与红块之间的空白间隙为50px。

  

  将#top50的css换成

#top50{
top: 50px;
margin-top: 50px;
    padding-bottom: 50px;
height: 100px;
width: 100px;
background: #f00;
display: inline;
}

  效果为

  

  可见行内元素对定位top/right/bottom/left、宽高width/height、外边距margin不敏感,对边框和内边距敏感。

  还有一点:脱离文档流的元素都是块级元素。

#top50{
top: 50px;
margin-top: 50px;
    padding-bottom: 50px;
height: 100px;
width: 100px;
background: #f00;
display: inline;
}

  

  后面两种情况#top50都被作为块级元素来处理了,而非内联元素。

  在使用脱离文档流的定位的时候最好使用 "left", "top", "right" 以及 "bottom" 属性对元素的位置进行规定。否则可能出现不良情况。还是先前的例子  

#top50{
    position:absolute;
top: 50px;
margin-top: 50px;
    padding-bottom: 50px;
height: 100px;
width: 100px;
background: #f00;
display: inline;
}

  设置了top和没有设置top的效果分别如下

       

  设置了top,top相对于body元素定位,可以预期。后面没有设置top,浏览器会将脱离文档流的块(包括外边距)按流式布局排列,给人感觉貌似没有脱离文档流,但是两个块之间的空白有60px高度,这种情况非我们预期。】

  

  3.absolute生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。因为static定位是无法使用left/top/right/bottom设置位置的,static定位的元素应当和他们的父节点的边重合(在不考虑其他因素的情况下,比如外边距margin)。如#middle的父节点#normal就是static定位的元素,再往上找到#big才是非static定位的,所以#middle会相对于#big来定位。

  

  所以上图#middle相对#big左侧的距离是10px。在看#middle的顶边距离#normal的顶边是50px,是#middle:margin-top:50px影响。但是这个外边距偏移是基于normal的还是big的?

  实验1:先前做过的实验拿来用,如我们设置#big{padding-top: 1px;}属性后,#nomal的margin-top是在#big的padding-top开始偏移的,如图

  

  上面这个实验结果看到#middle的margin-top是基于#normal的。

  实验2:如果我们再给#middle 添加一个定位样式top:20px;结果如下

  

  看到没,这个时候#middle的top和margin-top都是基于#big,而非#normal。

  所以absolute定位结果分两种情况来考虑:

  第一种,元素的某条边没有设置定位属性(left/top/right/bottom)的时候(默认值为auto),这一边就会将absolute块(包括外边距)按流式布局来排列(如实验1结果所示),当然这个流式布局就会受到内边距padding的影响了。

  第二种,元素的某条边设置了定位属性(left/top/right/bottom)的时候(默认值是auto),这一边就会被作为脱离文档流的边来处理,会相对于 static 定位以外的第一个父元素(的边框)进行定位,如果这时候设置了外边距,那么这一边相对于基准元素的偏移=定位值(left/top/right/bottom)+ 外边距。效果如实验2所示。作为脱离文档流来处理的边是基于那个基准元素的边框来定位的,当然不受内边距padding的影响。

  

  4.fix定位可以看成一种特殊的绝对定位,absolute的基准元素是 static 定位以外的第一个父元素,而fix的基准元素是浏览器窗口。absolute定位结果分两种情况对于fix来说同样适用。看下面的图:第一幅没有设置top,后一幅设置了top:10px。

  

  5.因为absolute相对于 static 定位以外的第一个父元素进行定位,所以一般要对某个元素absolute定位,则设置其父元素为relative即可。避免无法预知的基准元素。

  6.强烈建议脱离文档流的定位absolute的元素内部不要在其内部包含有脱离文档流的元素存在。举一个例子,某个iframe中内容会不断增高或缩小,但是iframe不能有自己的滚动条,需要同步增高或减少父窗口和iframe的高度使得滚动父窗口滚动条滚动显示iframe的内容。这个时候,需要计算iframe中body内容真实的高度(这个高度不能使用$(document).height()来获得,看这篇文章最后总结中document总结的IE部分,获取的不一定是body内容的真实高度可能是窗口的高度),对于脱离文档流的元素需要自己计算高度,而脱离文档流的元素a中还包含脱离a的元素b,咋搞哦。所以才有这里的建议。

  

  7. 对使用absolute脱离文档流的的元素如果做到让absolute元素后面的元素自适应布局?一般使用margin定位后面的元素来处理。举个例子

  

  左边的灰块是绝对定位absolute元素,右边黄色部分文字自适应到绿色边框的右边自动换行。这个是怎么实现的看源码

    <style>
#panel{
width: 500px;
height: 100px;
border: green solid 1px;
}
#left{
position:absolute;
height: 100px;
width: 100px;
background: #000;
opacity: 0.5;
color: #fff;
}
#right{
margin-left: 110px;

background: #ff0;
}
</style>
<div id="panel">
<div id="left">这个东东是position:absolute</div>
<div id='right' >这个东东是position:absolute后面的元素这个东东是position:absolute后面的元素这个东东是position:absolute后面的元素这个东东是position:absolute后面的元素</div>
</div>

  #left绝对定位宽度是100,那么只要使#right margin-left: 110px;这样空出#left的显示空间即可。#right的自适应照常使用。

  8. relative没有脱离文档流。如果原来不明白为什么,就有必要看这个例子。relative:相对定位,参造物是其本身,并不脱离文档流,不管你怎么移动,它原有的位置还是会留着。不仅如此,脱离文档流的元素相当于自身生成了一个新的文档流,父容器对其没有布局上的影响(最多是定位的影响)。但是relative却不是,父容器对其布局影响照旧。举例(还是上面的例子,我们把#right替换为如下):

    #right{
margin-left: 110px;
background: #ff0;
position: relative;
}

  

  效果依旧,自适应依然以绿色边框的父容器为边界。我们如果将#right换成span标签,#right依然以span内联标签的方式显示。

  如果我将#right换成

    #right{
margin-left: 110px;
background: #ff0;
position: absolute;
}

  

  上图效果图右边还有部分没有截完。可以看出父容器对#right已经无法限制其边界了。#right真正的是自成一家了。

  不过有一点:relative在堆叠优先级上和fixed、absolute一样,要比兄弟节点中staic节点要高。举例

    <style>
#panel{
width: 500px;
height: 100px;
border: green solid 1px;
}
#left{
position:absolute;
left: 50px;

height: 100px;
width: 100px;
background: #000;
opacity: 0.5;
color: #fff;
}
#right{
margin-left: 110px;
background: #ff0;
position: static;

}
</style> <div id="panel">
<div id="left">这个东东是position:absolute</div>
<div id='right' >这个东东是position:absolute后面的元素这个东东是position:absolute后面的元素这个东东是position:absolute后面的元素这个东东是position:absolute后面的元素</div>
</div>

  

  虽然#right写的顺序在#left后面,但是#left依然堆叠在#right上面。可以动手试一下,relative、absolute、fixed等级是一样的,static比另外三个低一级。

  

b. 浮动属性float


  float 属性定义元素在哪个方向浮动。以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元素都可以浮动。浮动元素会生成一个块级框,而不论它本身是何种元素。如果浮动非替换元素,则要指定一个明确的宽度;否则,它们会尽可能地窄。

  注释:假如在一行之上只有极少的空间可供浮动元素,那么这个元素会跳至下一行,这个过程会持续到某一行拥有足够的空间为止。

  为什么说浮动元素是脱离文档流的。

  脱离文档流的元素有个标志:没有实际高度。比如例子

    <style>
#panel{
width: 500px;
border: green solid 1px;
}
#left{
float:left;

left: 0px;
height: 100px;
width: 100px;
background: #000;
opacity: 0.5;
color: #fff;
}
</style>
<div id="panel">
<div id="left">这个东东是position:absolute</div>
</div>

  

  #left没有把#panel给撑开,#panel的高度为0。

  对于浮动属性来说,位置属性(left/top/right/bottom)是没有用的。

  但是在内部显示的时候,#left的兄弟节点会在#left占有的地盘之外显示。比如,我们新增#right,html代码变为

    <style>
#panel{
width: 500px;
border: green solid 1px;
}
#left{
float:left;
left: 0px;
height: 100px;
width: 100px;
background: #000;
opacity: 0.5;
color: #fff;
}
#right{
background: #ff0;
position: relative;
}
</style>
<div id="panel">
<div id="left">这个东东是position:absolute</div>
<span id='right' >这个东东是position:absolute后面的元素这个东东是position:absolute后面的元素这个东东是position:absolute后面的元素这个东东是position:absolute后面的元素的元素这个东东是position:absolute后面的元素的元素这个东东是position:absolute后面的元素的元素这个东东是position:absolute后面的元素的元素这个东东是position:absolute后面的元素</span>
</div>

  

  文字环绕#left。#panel被#right给撑开了。

  浮动有点像玩俄罗斯方块。向左浮动,方块从右往左滑过来,如果某一行空间不够(基于父容器的宽度),那么这个块会沿着最右边的块的下边沿水平划过来,最后看卡到哪里就停止。举例

    <style>
#panel{
width: 200px;
height: 200px;
border: green solid 1px;
}
#left1{
float:left;
height: 100px;
width: 100px;
background: #000;
color: #ffa;
}
#left2{
float:left;
height: 50px;
width: 50px;
background: #bba;
}
#left3{
float:left;
height: 30px;
width: 30px;
background: #a3a;
}
#left4{
float:left;
height: 60px;
width: 60px;
background: #a92;
}
#right1{
float:right;
height: 30px;
width: 30px;
background: #ff0;
}
#right2{
float:right;
height: 60px;
width: 70px;
background: #8f0;
}
</style>
<div id="panel">
<div id="left1">left1</div>
<div id="left2">left2</div>
<div id="left3">left3</div>
<div id="left4">left4</div>
<div id="right1">right1</div>
<div id="right2">right2</div>
</div>

  

  #left4在第一行left3后面宽度不够,换行成第二行。在left2后面宽度不够,只能在left1后面。#right1自然是从第二行开始查找位置,很幸运第二行现在唯一的元素#left4右面空间足够,放置即可。#right2在第二行中没有足够的位置,换行成第三行,找到空余位置插入。

  可以看到互动元素之间连接的部分是没有空隙的。这是一个很好的特性,可以用来做排列,精确到1px。

  浮动元素不占据高度,如果某个元素内部全是浮动元素,最后该元素也没有高度,如果想要父元素内的浮动元素占有原来的高度,在父元素内部最后一个元素加上css属性为clear:both的块状元素即可。如

  #panel{
width: 200px;
border: green solid 1px;
}
  <div id="panel">
<div id="left1">left1</div>
<div id="left2">left2</div>
<div id="left3">left3</div>
<div id="left4">left4</div>
<div id="right1">right1</div>
<div id="right2">right2</div>
<div style="clear:both"></div>
</div>

  

  有时也会在父元素后面加,不过该父元素不会获取到高度,但是父元素的后面的兄弟节点会认为其占用了位置。实例

<!DOCTYPE html>
<html lang="ch-cn">
<head>
<meta charset="utf-8">
<title>chua</title>
<style>
#panel{
width: 200px;
border: green solid 1px;
}
#left1{
float:left;
height: 100px;
width: 100px;
background: #000;
color: #ffa;
}
#left2{
float:left;
height: 50px;
width: 50px;
background: #bba;
}
#left3{
float:left;
height: 30px;
width: 30px;
background: #a3a;
}
#left4{
float:left;
height: 60px;
width: 60px;
background: #a92;
}
#right1{
float:right;
height: 30px;
width: 30px;
background: #ff0;
}
#right2{
float:right;
height: 60px;
width: 70px;
background: #8f0;
}
#panel2{
width: 200px;
height: 100px;
border: green solid 1px;
}
</style>
</head>
<body>
<div id="panel">
<div id="left1">left1</div>
<div id="left2">left2</div>
<div id="left3">left3</div>
<div id="left4">left4</div>
<div id="right1">right1</div>
<div id="right2">right2</div>
</div>
<div style="clear:both;"></div>
<div id="panel2">panel2</div>
</body>
</html>

  

  对于浮动与定位的位置优先级:

  (fixed == absolute) > float > relative > static。理解为同时设置了position:absolute和float:right。忽略float:right。

  

  堆叠优先级:

  定位元素z-index>=0时为(fixed == absolute == relative)  > static,z-index < 0时(fixed == absolute == relative)  < static。理解为兄弟元素一个设置了position:relative,另一个设置了position:static,当relative元素z-index为>=0时,无论static元素设置多少都在relative下面。如果relative设置z-index<0,则论static取什么值relative都会在static下面。

  定位元素z-index>=0时(fixed == absolute == relative)  > float,z-index < 0时(fixed == absolute == relative)  < float。理解为兄弟元素一个设置了position:relative,另一个设置了float:left,当relative元素z-index为>=0时,无论float元素设置多少都在relative下面。如果relative设置z-index<0,则无论float的z-index设置多少relative都会在float下面。

  float > static始终成立。因为z-index只有在定位元素上才起作用,定位元素包括fixed、absolute、relative。

  fixed == absolute == relative,比较堆叠顺序直接比较z-index大小即可。

  如果觉得本文不错,请点击右下方【推荐】!

html/css基础篇——DOM中关于脱离文档流的几种情况分析的更多相关文章

  1. html/css 关于脱离文档流的几种情况

    所谓的文档流 顾名思义就是按照顺序流下来,指的是html元素从上往下 从左往右的流式排列, 比如说写了5个Div,正常的文档流是依次显示这5个div块: 脱离文档流就是指它所显示的位置和文档代码就不一 ...

  2. HTML元素脱离文档流的三种方法

    一.什么是文档流? 将窗体自上而下分成一行一行,并在每行中按从左至右依次排放元素,称为文档流,也称为普通流. 这个应该不难理解,HTML中全部元素都是盒模型,盒模型占用一定的空间,依次排放在HTML中 ...

  3. 【H5疑难杂症】脱离文档流时的渲染BUG

    BUG重现 最近机票团队在一个页面布局复杂的地方发现一个BUG,非常奇怪并且不好定位,这类问题一般最后都会到我这里,这个问题是,改变dom结构,页面却不渲染!!! 如图所示,我动态的改变了dom结构, ...

  4. HTML文档流和脱离文档流

    文档流:也就是我们通常看到的由左到右.由上而下的元素排列形式,在网页中每个元素都是默认按照这个顺序进行排序和显示的. 脱离文档流:元素脱离文档流之后,将不再在文档流中占据空间,而是处于浮动状态(可以理 ...

  5. CSS中脱离文档流是什么意思?

    如果一个元素脱离文档流了,是不是只是显示上脱离而已?在html中是否也会脱离?我用js取这个元素的父节点的childNodes还能否取到这个元素:同时,这个元素的parentNode还是不是html中 ...

  6. HTML+CSS基础 块级元素div分析 文档流 脱离文档流的方法

    块级元素div分析 1.外边距  margin 2.内边距 padding 3.边框  border Div的真实宽度=width+margin-left+margin-right+border*2+ ...

  7. css中哪些属性会脱离文档流

    一共有三个属性会使元素脱离文档流: (1)浮动 (2)绝对定位 (3)固定定位 元素脱离文档流会导致父元素高度塌陷,要修复高度塌陷问题,可以将子元素与父元素放在同一个BFC中

  8. 23----2013.07.01---Div和Span区别,Css常用属性,选择器,使用css的方式,脱离文档流,div+css布局,盒子模型,框架,js基本介绍

    01 复习内容 复习之前的知识点 02演示VS创建元素 03div和span区别 通过display属性进行DIV与Span之间的转换.div->span 设置display:inline   ...

  9. css脱离文档流

    作者:张秋怡链接:http://www.zhihu.com/question/24529373/answer/29135021来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...

随机推荐

  1. ASP.NET 4.5.256 has not been registered on the Web server. You need to manually configure your Web server for ASP.NET 4.5.256 in order for your site to run correctly

    Microsoft .NET Framework 4.6安装后,用户可能会在使用Microsoft Visual Studio 创建(或打开现有项目时)网站.或Windows Azure项目时遇到下面 ...

  2. ios设备mdm的实现过程

    一)配置IIS加密连接,ios系统升级7.1后已经无法使用http进行企业内部署,为了满足mdm的加密需求以及大厅的初始化安装需要进行生成自签名证书 1)配置MIMEcer application/x ...

  3. svn patch用法

    最近遇到了一个patch的使用场景: 有一个同事对源码做了一些修改,但是又不想将源码提交到SVN服务器,而我又想得到他所做的修改. patch的使用方法: 创建patch 在要导出“修改”的目录中,单 ...

  4. 在Linux上用自己编译出来的coreclr与donet cli运行asp.net core程序

    先在 github 上签出 coreclr 的源代码,运行 ./build.sh 命令进行编译,编译结果在 coreclr/bin/Product/Linux.x64.Debug/ 文件夹中. 接着签 ...

  5. 将Win8.1/WP8.1应用迁移到Universal Windows Platform

    在上一篇在VS2015 RC打开CTP中创建的工程,我们介绍了怎么在RC中打开CTP中创建的Universal 工程,这一篇我们来讲下怎么将Windows 8.1/WP8.1的应用迁移到Univers ...

  6. Java多线程19:定时器Timer

    前言 定时/计划功能在Java应用的各个领域都使用得非常多,比方说Web层面,可能一个项目要定时采集话单.定时更新某些缓存.定时清理一批不活跃用户等等.定时计划任务功能在Java中主要使用的就是Tim ...

  7. 人人都是 DBA(II)SQL Server 元数据

    SQL Server 中维护了一组表用于存储 SQL Server 中所有的对象.数据类型.约束条件.配置选项.可用资源等信息,这些信息称为元数据信息(Metadata),而这些表称为系统基础表(Sy ...

  8. 如何捕获和分析 JavaScript Error

    前端工程师都知道 JavaScript 有基本的异常处理能力.我们可以 throw new Error(),浏览器也会在我们调用 API 出错时抛出异常.但估计绝大多数前端工程师都没考虑过收集这些异常 ...

  9. Window Ghosting

    最近工作中遇到Window Ghosting这个问题, 感觉挺有意思,这里简单记录下. 在XP时代我们的程序没有响应后只能通过任务管理器强制杀掉,但是Vista之后情况变了, 我们仍然可以拖动失去响应 ...

  10. 如何为编程爱好者设计一款好玩的智能硬件(七)——LCD1602点阵字符型液晶显示模块驱动封装(上)

    当前进展: 一.我的构想:如何为编程爱好者设计一款好玩的智能硬件(一)——即插即用.积木化.功能重组的智能硬件模块构想 二.别人家的孩子:如何为编程爱好者设计一款好玩的智能硬件(二)——别人是如何设计 ...