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

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

  

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. 【Win10 UWP】QQ SDK(二):SDK的回调处理

    上一讲,我们介绍了QQ SDK的使用方法,请看<[Win10 UWP]QQ SDK(一):SDK基本使用方法> 一. 回调的基本形式 从前面的介绍中我们知道,我们的应用和QQ客户端之间需要 ...

  2. C#函数式编程之可选值

    在我们的实际开发中已经会遇到可空类型,而在C#中自从2.0之后就提供了可空类型(Nullable<T>),普通的值类型是不可以赋值为NULL,但是在类型的后面加上问号就变成了可空类型,这样 ...

  3. GitHub的多人协同开发配置

    GitHub For Windows 下载地址:https://windows.github.com/ 基本的注册登录就不细讲了. 在源代码管理上,最重要的就是仓库了.仓库这一概念很容易理解,所谓仓库 ...

  4. 可在广域网部署运行的QQ高仿版 -- GG叽叽V3.0,完善基础功能(源码)

    (前段时间封闭式开发完了一个项目,最近才有时间继续更新GG的后续版本,对那些关注GG的朋友来说,真的是很抱歉.)GG的前面几个版本开发了一些比较高级的功能,像视频聊天.远程桌面.文件传送.远程磁盘等, ...

  5. Nim教程【七】

    这是国内第一个关于Nim的系列教程 先说废话 很开心,在今天凌晨快一点多的时候拿到了 nim-lang.com:nim-lang.cn:nim-lang.net 这三个域名,到不是为了投资,准备用ni ...

  6. Ubuntu下安装 jdk6

    Ubuntu下安装 jdk6 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循“署名-非商业用途-保持一致”创作公用协议   1,下载最新的 jdk6 版本,目前最 ...

  7. 解决SQLSERVER数据库表被琐死!

    ) )     BEGIN   Exec (@spId)   FETCH NEXT FROM TmpCursor INTO @spId   END     CLOSE TmpCursor DEALLO ...

  8. 使用后缀数组寻找最长公共子字符串JavaScript版

    后缀数组很久很久以前就出现了,具体的概念读者自行搜索,小菜仅略知一二,不便讨论. 本文通过寻找两个字符串的最长公共子字符串,演示了后缀数组的经典应用. 首先需要说明,小菜实现的这个后缀数组算法,并非标 ...

  9. 使用后台服务数据更新UI

    https://www.websmithing.com/2011/02/01/how-to-update-the-ui-in-an-android-activity-using-data-from-a ...

  10. 实现基于Task的异步模式

    返回该系列目录<基于Task的异步模式--全面介绍> 生成方法 编译器生成 在.NET Framework 4.5中,C#编译器实现了TAP.任何标有async关键字的方法都是异步方法,编 ...