CSS定位与布局属于CSS的基础,也是CSS布局影响很大的一部分,具体主要包括三种定位与布局机制( Positioning schemes):普通流,浮动,绝对定位。
其实除了这三种之外,还有一些定位机制,但是这三种可以说在网站的应用是最多的,随便打开一个网站搜索一下这些属性,少则出现几十次,多则上百,官方文档也有对这三个属性的辨析<Comparison of normal flow, floats, and absolute positioning>,这篇博文很多内容是受 葵中剑@剑空 前辈的博文 CSS定位机制之一:普通流 的启发,在此感谢前辈的博文分享。
 
CSS定位与布局:普通流
 
官方文档介绍:
 
In CSS 2.1, a box may be laid out according to three positioning schemes:
1. Normal flow. In CSS 2.1, normal flow includes block formatting of block-level boxes, inline formatting of inline-level boxes, andrelative positioning of block-level and inline-level boxes.
2. Floats. In the float model, a box is first laid out according to the normal flow, then taken out of the flow and shifted to the left or right as far as possible. Content may flow along the side of a float.
3.Absolute positioning. In the absolute positioning model, a box is removed from the normal flow entirely (it has no impact on later siblings) and assigned a position with respect to a containing block.
 
普通流( normal flow )
标准里的定义:Normal flow. In CSS 2.1, normal flow includes block formatting of block boxes, inline formatting of inline boxes, relative positioning of block or inline boxes, and positioning of run-in boxes.(这个属于CSS3新定义的属性,还未去了解)
即普通流包括:块格式化( block formatting ),行内格式化( inline formatting ),相对定位(relative positioning ),以及 run-in boxes(CSS3)的定位。
任何被渲染的元素都属于一个 box ,并且不是 block ,就是 inline 。在普通流中的 Box(框) 属于一种 formatting context(格式化上下文) ,类型可以是 block ,或者是 inline ,但不能同时属于这两者。并且, Block boxes(块框) 在 block formatting context(块格式化上下文) 里格式化, Inline boxes(块内框) 则在 inline formatting context(行内格式化上下文) 里格式化。即使是未被任何元素包裹的文本,根据不同的情况,也会属于匿名的 block boxes 或者 inline boxes。
普通流过程:
1、block formatting context:块级元素按照在HTML中的顺序,在容器框中从左到右,从上到下依次分配空间,每个块级元素独占一行,margin属性决定相邻inline-block元素距离,同一个BFC中的垂直边界被重叠(collapse)。其中,浮动的块级元素会有inline-block元素的一些表现,具体将在float定位中细讲。
 
2、inline formatting context:行内元素在容器框中的顶端开始水平排布,这里有必要说明下margin,padding,border的不同表现。
 
------------------------------------------------------举个栗子---------------------------------------------------
HTML:
 <div class="container">
<a class="inlineEle" href="#">inline element</a>
<a class="inlineEle" href="#">inline element</a>
</div>
CSS:
.container{
border: 1px solid #000;
}
.inlineEle {
background-color: #bbb;
border: 10px solid #000;
margin: 10px;
padding:20px;
height: 100px;
width: 300px;
}
chrome,firefox,opera,IE8+表现如下:
 
IE6,IE7下的表现:
 
IE6,IE7下,当容器框加了height:100px后内联元素高度变为line-height,其他部分被截掉了:
margin:水平的margin有效,但是垂直的margin不影响高度,或者说无效。
border:border的有兼容性问题,chrome,firefox,opera,IE8+下会表现出所有边框,但是垂直方向的border虽然出现了但是,并不能撑开容器框,当容器框设置overflow:hidden的时候会被hidden掉。在IE6,IE7下垂直方向的border已经不见了。其实IE5我也出于好奇测试了一下,发现居然表现和chrome等一样,实在是匪夷所思。不过IE5已经不在我的考虑之内了。
padding:padding均能表现,但是同样垂直方向的padding也无法撑开容器框,当容器框设置overflow:hidden的时候也会被hidden掉。
width,height:对于行内元素无效。
-----------------------------------------------------吃完栗子-----------------------------------------------------
 
一个水平行中的所有inline box组成了名为line box的区域,line box的高度始终容得下所有的inline box,并只有行内元素的行高能够撑开容器框。line-box的宽度受到父容器和浮动元素影响(浮动元素实现文字环绕效果)。如果line box的宽度小于容器,line box的水平排布就取决于text-align,当line box的宽度大于容器,则截断line box并换行在新的line box中重新排布元素(截断处不应用padding和margin值)。如果line box无法截断,如单词过长或者指定不换行,则会溢出容器。
 
3、对block box和inline box进行相对定位(position:relative),即相对于已排布的位置进行偏移,元素基于普通流的排布空间依然保留。
 
普通流中有一个比较重要的概念,即Formatting context。Formatting context是W3C CSS2.1规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。
 
最常见的 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。 
CSS2.1 中只有BFC和IFC, CSS3中还增加了GFC和FFC。下面只讲 BFC,IFC有机会再补充。
 
Block fomatting context 的创建:
  1. 根元素
  2. float属性不为none
  3. position为absolute或fixed
  4. display为inline-block, table-cell, table-caption, flex, inline-flex
  5. overflow不为visible
注:
1、CSS level 3 specification中,BFC(CSS3中用 "flow root" 表示)在以下情况中可以建立:position 的值不为 “static” 或者 “relative” ,即 fixed 也能建立BFC,但其实fixed算是 absolute positioning 的一个子集,在规范中引用一个绝对定位的元素(或他的box模型)意味着该元素的 “position” 属性值 “absolute” 或 “fixed”,因此在CSS2.1 中使用这个值也会触发 BFC ,只是在 CSS3 中更加明确了这一点。
2、display:table 本身并没有建立BFC,但是它能够产生匿名框,匿名框(display:table-cell)才会建立BFC。
即使两种样式都建立了BFC(隐式或显式),clear 属性作用在 display:table 和 display:table-cell 是不一样的。
3、fieldset元素也能触发BFC。www.w3.org上并没有对它的表现的描述,直到HTML5的规范中才有。有一些浏览器bugs(Webkit,Mozilla)提到过,但是都不是官方声明的。参考文章的作者Thierry Koblentz认为:即使fieldsets在大多数浏览器中都能建立BFC,也是不推荐的,CSS2.1中没有定义该属性应用于表单控件和框架,或者如何用CSS添加样式,用户代理可能可以为其提供CSS样式属性。故应该把这种支持作为实验性质的,未来版本的CSS可能会明确支持。
 
Block fomatting context 的作用与影响:
  1. 在同一个BFC中,boxes会在垂直方向,从一个containing block的顶部一个接一个放置,兄弟 boxes 的垂直距离由 ”margin“ 值决定。相邻 block boxes 的垂直 margin 会折叠(CSS2.1 8.3.1Collapsing margins)。
  2. 在同一个BFC中,每一个 box 的左外边缘与 containing block 左边缘接触(从右到左的格式化则是右边缘接触)。即使是浮动元素(虽然一个box的line boxes会因为浮动元素而收缩),除非 box 建立一个新的BFC(会因为和浮动元素接触而收缩)。
  3. BFC 使在同一个BFC中的相邻 block boxes 的垂直margin值不会折叠。
  4. BFC能够包含浮动元素。
  5. BFC区域不会与浮动元素重叠。
  6. 计算BFC的高度时,浮动元素也参与计算。(CSS2.1 10.6.7 'Auto' heights for block formatting context roots
  7. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
因为BFC内部的元素和外部的元素绝对不会互相影响,因此, 当BFC外部存在浮动时,它不应该影响BFC内部Box的布局,BFC会收缩而不与浮动有重叠。同样的,当BFC内部有浮动时,为了不影响外部元素的布局,BFC计算高度时会包括浮动的高度。避免margin重叠也是这样的一个道理。
 
-----------------------------------------------------举几个栗子说明一下-----------------------------------------------------
栗子一(BFC 使在同一个BFC中的相邻 block boxes 的垂直margin值不会折叠):
HTML:
<div class="container">
<div class="collapsediv">同一个BFC中的div.1</div>
<div class="collapsediv">同一个BFC中的div.2</div>
</div>
CSS:
.container {
border: 1px solid #000;
overflow: hidden;
*zoom:;
}
.collapsediv {
background-color: #ccc;
width: 300px;
height: 100px;
margin: 50px;
}
注:这里的*zoom:1是对IE6的hack,涉及到IE的私有属性hasLayout 。
表现如下:
 
此时 div.1 的 margin-bottom 和 div.2 的 margin-top 重叠了,如果给下面的div.2包裹在触发了BFC的容器中,则div.1和div.2则属于不同的BFC,则margin不会折叠(此时如果在.warp元素上加padding-top或者border属性都可以使margin不重叠,效果和出发BFC相同。当然IE6、IE7除外 )。
修改后的HTML:
<div class="container">
<div class="collapsediv_1">同一个BFC中的div.1</div>
<div class="wrap">
<div class="collapsediv_2">同一个BFC中的div.2</div>
</div>
</div>
CSS:
.collapsediv{
background-color: #ccc;
width: 300px;
height: 100px;
margin: 50px;
}
.wrap {
overflow: hidden;
*zoom:;
}
.inlineEle {
background-color: #bbb;
border: 10px solid #000;
margin: 10px;
padding: 20px;
height: 100px;
width: 300px;
}
表现如下:
 
栗子二(BFC能够包含浮动元素+计算BFC的高度时,浮动元素也参与计算):
HTML:
<div class="container">
<div class="floatdiv">浮动div.1</div>
<div class="floatdiv">浮动div.2</div>
</div>
CSS:
.container {
border: 2px solid #000;
}
.floatdiv {
background-color: #ccc;
width: 100px;
height: 50px;
float: left;
border:1px solid #666;
}
表现如下:
 
浮动元素脱离了普通流,使得容器框的高度变为0,此时为容器建立BFC就可以包含浮动元素,同时也说明此时计算容器框的高度时,浮动元素也参与计算。
修改后的CSS:
container {
border: 2px solid #000;
overflow: hidden;
*zoom:;
}
表现如下:
 
注:除了创建 BFC,还可以用清除浮动的方法,需要留意的是用 clear 清除浮动只会清除同一个BFC中的浮动元素。
 
栗子三(BFC区域不会与浮动元素重叠)
HTML代码:
<div class="container">
<div class="floatdiv">浮动div</div>
<div class="nofloatdiv">不浮动div</div>
</div>
CSS:
.floatdiv {
background-color: #ccc;
float: left;
height: 50px;
}
.nofloatdiv {
background-color: #999;
height: 100px;
}
.container {
border: 1px solid #000;
height: 150px;
}
 
 
在chrome,firefox,opera,IE8+表现如下:
 

IE7表现如下:

 
IE6表现如下,这里浮动和不浮动的div之间有3px的间距,这是IE6及以下版本独有的3px的bug:

修改CSS如下:
.nofloatdiv {
background-color: #999;
height: 100px;
overflow: hidden;
*zoom:;
}
除了IE6表现不变外,其他浏览器(包括IE7)表现如下:
 
-----------------------------------------------------吃完栗子-----------------------------------------------------
 
除了IE6,IE7外,和浮动元素相邻的块元素建立BFC后,不会和浮动元素重叠。而IE6、IE7在加了height属性后其实就触发了IE的私有属性hasLayout,以及IE6还存在3px的bug,这都和IE的私有属性hasLayout有关。关于hasLayout,这是IE7及更低版本所有的一个IE私有属性,和BFC有些类似,是IE兼容性的一个罪魁祸首,关于这个属性有一篇很旧但是很详实的文章On having layout(蓝色理想转载的中文翻译版本),原文:On having layout
 
BFC总结:
BFC 神奇背后的原理的总结个人觉得不错,很容易理解,也很容易记住。此处引用一下:
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
因为BFC内部的元素和外部的元素绝对不会互相影响,因此, 当BFC外部存在浮动时,它不应该影响BFC内部Box的布局,BFC会通过变窄,而不与浮动有重叠。同样的,当BFC内部有浮动时,为了不影响外部元素的布局,BFC计算高度时会包括浮动的高度。避免margin重叠也是这样的一个道理。
 
参考文档:
 
参考文章:
 
感谢文章作者。
 
水平有限,错误欢迎指正。原创博文,转载请注明出处。

CSS定位与布局:普通流的更多相关文章

  1. CSS定位与布局:浮动

    浮动的特点   浮动(float)属性提出的作用是实现文字的环绕效果,一个元素浮动后,会脱离普通流.主要的特点如下: 浮动的元素会向左或者向右移动直到它的外边缘接触容器框(containing blo ...

  2. CSS定位与布局

    我们在编写网页代码时,首先应该做的就是设计好页面的布局形式,然后再往里面填充内容.网页布局的好与坏,直接决定了网页最终的展示效果.PC端常见的网页布局形式有两列布局.三列布局等.在CSS中,我们通常使 ...

  3. HTML学习笔记 css定位浮动及瀑布流案例 第十三节 (原创) 参考使用表

    #fd { width: 100px; height: 150px; background-color: forestgreen; float: left; } #sd { width: 150px; ...

  4. (七)CSS定位(Positioning)

    CSS定位属性允许对元素进行定位. 一切皆为框: div.h1或p元素常被称为块级元素,而span和strong等元素成为行内元素,但是可是使用 display 属性改变框的类型,将display设置 ...

  5. CSS易混淆知识点总结与分享-定位与布局

    CSS定位有四种模式:static.relative.absolute.fixed,其它static是默认值,下面分别讲解下各自的特点: static:静态定位,处于动态布局流中,按照页面中的各元素先 ...

  6. CSS中的三种基本的定位机制(普通流、定位、浮动)

    一.普通流 普通流中元素框的位置由元素在XHTML中的位置决定.块级元素从上到下依次排列,框之间的垂直距离由框的垂直margin计算得到.行内元素在一行中水平布置. 普通流就是html文档中的元素如块 ...

  7. CSS概念 - 可视化格式模型(二) 定位概述(普通流、绝对定位)

    2.定位概念 上一节熟悉了盒模型, 现在来看一下可视化格式模型和定位模型. 理解这两个模型的细微差异是非常重要的, 因为它们一起控制着如何在页面上布置每个元素 2.1 可视化格式模型 CSS有三种基本 ...

  8. 前端(八)—— 高级布局:文档流、浮动布局、流式布局、定位布局、flex布局、响应布局

    高级布局:文档流.浮动布局.流式布局.定位布局.flex布局.响应布局 一.文档流 1.什么是文档流 将窗体自上而下分成一行一行,块级元素从上至下.行内元素在每行中从左至右的顺序依次排放元素 2.本质 ...

  9. css布局-瀑布流的实现

    一.基本思路 1.先看最终的效果图: 2.实现原理:通过position:absolute(绝对定位)来定位每一个元素的位置,并且将当前列的高度记录下来方便下一个dom位置的计算 二.代码实现 1.版 ...

随机推荐

  1. 自定义View/ViewGroup的步骤和实现

    1.设置属性(供XML调用) 在res目录新建attrs.xml文件 <?xml version="1.0" encoding="utf-8"?> ...

  2. Android stadio litepal

    今天看到技术交流群里有人招聘Android,要求会litepal. 我立马百度了下.嗯,我的学习技术的精神,是值得称赞的. litepal就是操作数据库的一个框架.git地址: https://git ...

  3. Python虚拟机类机制之对象模型(一)

    Python对象模型 在Python2.2之前,Python中存在着一个巨大的裂缝,就是Python的内置类type,比如:int和dict,这些内置类与程序员在Python中自定义的类并不是同一级别 ...

  4. 并发编程——多进程——multiprocessing开启进程的方式及其属性(3)

    开启进程的两种方式——Process 方式一:函数方法 from multiprocessing import Process import time def task(name): print('% ...

  5. ThinkPHP5 配置文件

    配置目录 系统默认的配置文件目录就是应用目录(APP_PATH),也就是默认的application下面,并分为应用配置(整个应用有效)和模块配置(仅针对该模块有效). ├─application 应 ...

  6. php开启子进程处理

    $pageNum = ceil($totalNum/$pageSize); for($page=1;$page<=$pageNum;$page++){ $this->o_pcntl-> ...

  7. setTimeOut传参数

    最近,因项目需要,需要实现setTimeOut传参数的功能,搜索了很多的资源.终于找到一个比较好的方法了,记录下来,与大家分享. 无论是window.setTimeOut还是window.setInt ...

  8. iOS App启动图不显示的解决办法.

    1. 正常来说,启动图以及App图标需按照命名规则命名, 但是命名不规范并不影响显示; 2. 设置启动图的两种方法:      (1) iOS 8—xcode 6 之后新出LaunchScreen.s ...

  9. 刷题总结——Genghis Khan the Conqueror (hdu4126)

    题目: Genghis Khan(成吉思汗)(1162-1227), also known by his birth name Temujin(铁木真) and temple name Taizu(元 ...

  10. 在vue中使用sass

    首先安装node-sass和sass-loader cnpm install node-sass && sass-loader --save 在webpack.config.js 的m ...