一、包含塊(Containing Block)
要講position,首先就涉及到一個概念:包含塊。
1、包含塊介紹
包含塊簡單理解就是一個定位參考塊,就是"大盒子里套小盒子"中那個大盒子。元素有positon屬性就必然涉及到包含塊。先簡單總結一下。
1、初始包含塊(Initial containing block),即根元素的包含框。 在瀏覽器中是原點與 canvas 原點重合、大小與 viewport 相同的矩形。
2、position:static|relative 元素包含塊為最近的塊級【block|list-item|table】父元素的內容框content-box
3、positon:absolute 先找absolute最近已定位祖先元素【沒有的話包含塊就是初始包含塊】
- 如果祖先元素是塊級元素,則包含塊是祖先元素的padding框。
- 如果祖先元素是內聯元素,包含塊取決於祖先元素的direction屬性
- dirrection:ltr,祖先元素的第一個盒子的上、左padding框邊界是包含塊的上和左,祖先元素最后一個盒子的下、右padding邊界是包含塊的下和右。
- direction:rtl,祖先元素第一個盒子的上、右padding框邊界是包含塊的上右,祖先元素最后一個元素的下、左padding框邊界是包含塊的下、左。
4、positon:fixed 元素的包含塊是由viewport決定的,和根元素無關。
2、static和包含塊
舉例:沒有設置postion,所以標簽position都是默認的static。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>包含塊 by starof</title> </head> <body> <div id="div1"> <p id="p1">第一段內容</p> <p id="p2"> 這些文字是 <em id="em1">第 <strong id="strong1">二</strong>段</em> 內容 </p> </div> </body> </html>
產生盒子的元素——》包含塊
body——》initial C.B.(UA-dependent)
div1——》body
p1——》div1
p2——》div1
em1——》p2
strong1——》p2
3、absolute和包含塊
主要介紹一下祖先元素是內聯元素的情況。
舉例:direction:ltr
包含塊的上,左是祖先元素span生成的第一個框的上,左padding 框,包含塊下右是祖先元素span的最后一個line box的下右padding框。
<p style="border:1px solid red; width:200px; padding:20px;"> TTT <span style="background-color:#C0C0C0; position:relative;padding:10px;"> 這段文字從左向右排列,紅 XX 和 藍 XX 和黃 XX 都是絕對定位元素,它的包含塊是相對定位的SPAN。 可以通過它們絕對定位的位置來判斷它們包含塊的邊緣。 <em style="position:absolute; color:red; top:0; left:0;">XX</em> <em style="position:absolute; color:yellow; top:20px; left:0;">XX</em> <em style="position:absolute; color:blue; bottom:0; right:0;">XX</em> </span> </p>
包含塊的寬度可以為負,行內元素的第一個框的起始位置位於最后一個框結束位置的右側,這時包含塊為負值。
我增刪幾個字符來看看效果如下

<p style="border:1px solid red; width:200px; padding:20px;"> TTTTT <span style="background-color:#C0C0C0;position:relative;padding:10px;"> 這段文字從左向右排列,紅XX 和 藍 XX 和黃 XX 都是絕對定位元素,它的包含塊是相對定位的SPAN。 可以通過它們絕對定位的位置來判斷它們包含塊 <em style="position:absolute; color:red; top:0; left:0;">XX</em> <em style="position:absolute; color:yellow; top:20px; left:0;">XX</em> <em style="position:absolute; color:blue; bottom:0; right:0;">XX</em> </span> </p>
舉例:direction:rtl
包含塊的上,右是祖先元素第一個框的上,右padding框,包含塊的下左是祖先元素最后一個line box的下左padding同理。

<p style="border:1px solid red; width:200px; padding:20px; direction:rtl;"> T <span style="background-color:#C0C0C0; position:relative;padding:10px;"> 這段文字從右向左排列,紅 XX 和 藍 XX 和黃 XX 都是絕對定位元素,它的包含塊是相對定位的SPAN。 可以通過它們絕對定位的位置來判斷它們 <em style="position:absolute; color:red; top:0; left:0;">XX</em> <em style="position:absolute; color:yellow; top:20px; left:0;">XX</em> <em style="position:absolute; color:blue; bottom:0; right:0;">XX</em> </span> </p>
其他情況相對簡單,不做介紹。接下來是position各取值細節。
二、position:static
static是默認值,表示元素沒有別"positioned",position其它值表示元素被"positioned"。所以"已定位元素"表示的就是設置position屬性為除static之外的值的元素。position:static元素的布局就是按照盒子模型在正常流中來布局。
使用:
一般不用顯示指定,除非想要覆蓋之前設置的定位,讓元素回歸到正常流。
三、position:relative
relative表現和static一樣,除非添加了top|right|bottom|left屬性。//lxy可以理解為relative是從static到absolute的一個過渡屬性狀態。就像在inline和block中間過渡有一個inline-block。
相對定位元素屬性設置top|right|bottom|left偏離正常位置后,其他元素不會調整位置來彌補偏離后剩下的空間。也可以理解為仍然占據原來空間,所以不影響其他元素布局,可能會覆蓋別的元素。
總結:relative元素仍然處於正常流,且不改變display屬性,可能會覆蓋頁面其他元素。
舉例:
<style> div{ display: inline-block; } .red{ width: 100px; height: 100px; border:1px solid red; position: relative; background-color: yellow; } .green{ width: 100px; height: 100px; border:1px solid green; } /*.left{ left: -50px; }*/ </style> <body> <div class="red left">第一個元素</div> <div class="green">第二個元素</div> <div class="red left">第三個元素</div> </body>
取消注釋查看設置偏移后的對比效果:
四、position:absolute
position:absolute相對於最近的"positioned" 祖先元素定位。如果沒有“positioned”祖先元素,那么它是相對於文檔的 body 元素,並且它會隨着頁面滾動而移動。
絕對定位元素的定位值發生沖突時的解決方法:
- 如果同時指定
top
和bottom
(非auto
),優先采用top
。 - 如果同時指定
left
和right
,若包含塊的direction
為ltr
(英語、漢語等),則優先采用left
;若包含塊的direction
為rtl
(阿拉伯語、希伯來語等),則優先采用right
。
總結幾點:
position:absolute和margin,padding都不沖突,可同時生效。
position:absolute會改變display值,所以會產生包裹性。
position:absolute的元素脫離正常流。所以會產生破壞性。
position:absolute存在時【不加top,right,bottom,left】,float不起作用,所以可以用來去浮動。
1、包裹性
設置了position:absolute的元素,其尺寸會收縮正好容納內容。
因為position:absolute會改變元素的display屬性【類似浮動】,inline變成block,比如下面例子。
<style> .container{ border: 1px solid green; padding: 30px; background-color: green; background-clip: content-box;/*將背景裁剪到內容框,方便看絕對定位元素效果*/ position: absolute; } </style> <div class="container">內容</div>
塊狀元素設置position:absolute后,chrome下top,right,bottom,left變為auto,而ff下直接是計算出的寬度。
補充:【update20170419】
chrome 55.0.2883.87 下設置了position:absolute的元素的top,right,bottom,left也變成了計算值。
下圖中盒模型中position盒子的值即為top,right,bottom,left的值。
2、破壞性
舉例:子元素absolute,父元素高度塌陷。
<style> .father{ border:1px solid red; } .son{ background-color: green; position: absolute; /*float: left;*/ } </style> </head> <body> <div class="father"> <div class="son" >元素內容</div> </div> </body>
原理:和float一樣,position:absolute讓元素脫離正常流,而父元素還在正常流中,它們已經是兩個世界的東東了,自然撐不起父元素高度。
Note:設置position:absolute后再設置float:left不生效,且最終計算的float值還是none而不是設置的值。
3、不受relative控制的position:absolute舉例
不使用top,right,bottom,left中任何一個屬性或者使用auto作為值。
一般都是用absolute加margin調整位置。
舉例:hot圖片始終在求課文字右上角。

<style type="text/css"> .icon-hot { position: absolute; width: 28px; height: 11px; margin: -6px 0 0 2px; background-color: red; background: url(img/new.jpg); } </style> <body> <h3> <a href="#"> 新項目 <i class="icon-hot"></i> </a> </h3> <a href="#">新項目</a><img src="img/new.jpg" style="margin-bottom:15px;"> </body>
分析:因為position:absolute讓<i>標簽的display值從inline變成block,所以可以設置寬高。通過margin調整位置。
類似例子:

<!doctype html> <html> <head> <meta charset="utf-8"> <title>圖標定位二三事</title> <style> body { font: 14px/1.4 "Microsoft YaHei"; background-color: #EDEFF0; } body, h3, h5 { margin: 0; } img { border: 0 none; vertical-align: bottom; } .l { float: left; }.r { float: right; } .constr { width: 1200px; margin-left: auto; margin-right: auto; } .course { padding-top: 10px; } .course-list { float: left; width: 280px; height: 240px; margin: 5px 10px 15px; border-radius: 0 0 1px 1px; background-color: #F7FAF9; background-color: rgba(255,255,255,1); box-shadow: 0 1px 2px #c5c5c5; text-decoration: none; } .course-list-img { background-color: #6396F1; } .course-list-h { line-height: 50px; font-size: 14px; font-weight: 400; color: #363d40; text-align: center; } .course-list-tips { margin: 0 14px; font-size: 12px; color: #b4bbbf; overflow: hidden; } .icon-recom { position: absolute; line-height: 20px; padding: 0 5px; background-color: #f60; color: #fff; font-size: 12px; } .icon-vip { position: absolute; width: 36px; height: 36px; margin-left: -36px; background: url(http://img.mukewang.com/5453048000015d8800360036.gif); text-indent: -9em; overflow: hidden; } </style> </head> <body> <div class="main"> <div class="constr"> <div class="course"> <a href="http://www.imooc.com/view/121" class="course-list"> <div class="course-list-img"> <span class="icon-recom">推薦</span> <img width="280" height="160" alt="分享:CSS深入理解之float浮動" src="http://img.mukewang.com/53d74f960001ae9d06000338-300-170.jpg"><!-- --><i class="icon-vip">vip</i> </div> <h5 class="course-list-h">分享:CSS深入理解之float浮動</h5> <div class="course-list-tips"> <span class="l">已完結</span> <span class="r">3514人學習</span> </div> </a> </div> </div> </div> </body> </html>
4、無固定寬高容器內絕對定位元素拉伸
舉例:實現遮罩效果

<style> body { background-color: #ddd; } img { vertical-align: bottom; } .container { display: inline-block; position: relative; } .cover { position: absolute; left: 0; top: 0; right: 0; bottom: 0; background-color: blue; opacity: .5; filter: alpha(opacity=50); } </style> <body> <span class="container"> <i class="cover"></i> <img src="img/wb.jpg"> </span> </body>
同樣的原理實現:全屏自適應遮罩層效果,切加上margin:auto可實現水平且直居中。

<!doctype html> <html> <head> <meta charset="utf-8"> <title>沒有寬度和高度聲明實現的全屏自適應效果by starof</title> <style> html, body { height: 100%; } .overlay { display: none; position: absolute; left: 0; top: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); } .content { position: absolute; width: 300px; height: 200px; margin: auto; left: 0; top: 0; right: 0; bottom: 0; background-color: #fff; } </style> </head> <body> <div class="overlay" id="overlay"> <div class="content"> 彈出層內容 <a href="javascript:void(0);" id="close">關閉</a> </div> </div> <a href="javascript:void(0);" id="open">打開</a> <script> var openA=document.getElementById("open"); var overlay=document.getElementById("overlay"); var closeA=document.getElementById("close"); openA.onclick=function(){ overlay.style.display="block"; } closeA.onclick=function(){ overlay.style.display="none"; } </script> </body> </html>
五、position:fixed
fixed是absolute的特例,相對於視窗來定位,所以頁面滾動它還是停靠在相對位置。
所以fixed也會改變元素的display屬性,會讓元素脫離正常流。
六、position和float的關系
1、position:static;position:relative和float屬性可共存。
3、同時設置position:absolute和float,float無效。
4、設置position:absolute的元素可能會覆蓋float元素。
舉例:

<style> .float{ width: 300px; height: 150px; background: green; float:left; } .abs{ width: 150px; background-color: red; position: absolute; top:50px; } </style> </head> <body> <div class="float">我是float:left的DIV</div> <div class="abs">我是一個應用了position:absolute的DIV。</div> </body>
為什么絕對定位元素可能會覆蓋浮動元素,因為瀏覽器渲染的時候相同堆疊上下文中,先渲染非定位元素,再渲染浮動元素,最后渲染已定位元素。
關鍵問題是,此時設置float元素的z-index來覆蓋absolute無效。因為z-index值只適用於已經定位的元素(即position:relative/absolute/fixed),對浮動元素不起作用的。
可將float元素的position屬性值設置為relative,然后設置z-index。因為已定位元素並且z-index不是默認的auto的話會生成一個新的堆疊上下文。
如果上面說的還不是很懂,或者想更深入了解z-index原理,可參考:z-index堆疊規則
七、資源鏈接
KB012: 絕對定位( Absolute positioning )
http://w3help.org/zh-cn/causes/RM1020
http://w3help.org/zh-cn/kb/008/
本文作者starof,因知識本身在變化,作者也在不斷學習成長,文章內容也不定時更新,為避免誤導讀者,方便追根溯源,請諸位轉載注明出處:http://www.cnblogs.com/starof/p/4617776.html有問題歡迎與我討論,共同進步。