瀏覽器在解析渲染咱們所寫的html內容,順序渲染(普通文檔流)。css
<body> <div>1</div> <div>2</div> <div>3</div> <div>4</div> </body>
渲染結果以下圖html
這兒有一個知識點:
一、文檔流:按個人理解就是html在瀏覽器渲染顯示的一個模式,這個模式的特色:自上而下,從左到右(排列規則)。若是不特殊指定,瀏覽器會默認當前的HTML渲染是按文檔流模式。
二、浮動:平時咱們所知的脫離文檔流的一種方式,把html元素的佈局更改,浮動在視圖層上
三、絕對定位:脫離文檔流的另一種方式,也是渲染在視圖層上程序員
這兒又有個知識點:css盒模型chrome
盒模型是css渲染的時候抽象於html標籤在畫布所佔有區域,由CSS引擎根據文檔中的內容所建立。瀏覽器
盒模型的關鍵屬性:內容(content)、內邊距(padding)、邊框(border)、外邊距(margin)。佈局
盒模型是有兩種標準的,一個是標準模型,一個是IE模型。flex
從圖中很直觀能看出來,兩種模型的寬度和高度的計算規則不同。ui
在css中,兩個模型的定義方式爲:atom
/* 標準模型 */ box-sizing:content-box; /*IE模型*/ box-sizing:border-box;
視覺格式化模型會根據CSS盒子模型將文檔中的元素轉換爲一個個盒子。spa
每一個盒子的佈局由如下因素決定:
盒子的尺寸:精確指定、由約束條件指定或沒有指定 盒子的類型:行內盒子(inline)、行內級盒子(inline-level)、原子行內級盒子(atomic inline-level)、塊盒子(block) 定位方案(positioning scheme):普通流定位、浮動定位或絕對定位 文檔樹中的其它元素:即當前盒子的子元素或兄弟元素 視口尺寸與位置 所包含的圖片的尺寸 其餘的某些外部因素
該模型會根據盒子的包含塊(containing block)的邊界來渲染盒子。一般,盒子會建立一個包含其後代元素的包含塊,可是盒子並不禁包含塊所限制,當盒子的佈局跑到包含塊的外面時稱爲溢出(overflow)
在這兒把咱們用到的術語作一個解釋說明:
塊:block,一個抽象的概念,一個塊在文檔流上佔據一個獨立的區域,塊與塊之間在垂直方向上按照順序依次堆疊。 包含塊:containing block,包含其餘盒子的塊稱爲包含塊。 盒子:box,一個抽象的概念,由CSS引擎根據文檔中的內容所建立,主要用於文檔元素的定位、佈局和格式化等用途。盒子與元素並非一一對應的,有時多個元素會合並生成一個盒子,有時一個元素會生成多個盒子(如匿名盒子)。 塊級元素:block-level element,元素的 display 爲 block、list-item、table 時,該元素將成爲塊級元素。元素是不是塊級元素僅是元素自己的屬性,並不直接用於格式化上下文的建立或佈局。 塊級盒子:block-level box,由塊級元素生成。一個塊級元素至少會生成一個塊級盒子,但也有可能生成多個(例如列表項元素)。咱們查詢資料會看到:塊格式化上下文(Block Formatting Context,BFC),就是當前的區域。 塊盒子:block box,若是一個塊級盒子同時也是一個塊容器盒子(見下),則稱其爲塊盒子。除具名塊盒子以外,還有一類塊盒子是匿名的,稱爲匿名塊盒子(Anonymous block box),匿名盒子沒法被CSS選擇符選中。 塊容器盒子:block container box或block containing box,塊容器盒子側重於當前盒子做爲「容器」的這一角色,它不參與當前塊的佈局和定位,它所描述的僅僅是當前盒子與其後代之間的關係。換句話說,塊容器盒子主要用於肯定其子元素的定位、佈局等。 注意:盒子分爲「塊盒子」和「塊級盒子」兩種,但元素只有「塊級元素」,而沒有「塊元素」。下面的「行內級元素」也是同樣。 行內級元素:inline-level element,display 爲 inline、inline-block、inline-table 的元素稱爲行內級元素。與塊級元素同樣,元素是不是行內級元素僅是元素自己的屬性,並不直接用於格式化上下文的建立或佈局。 行內級盒子:inline-level box,由行內級元素生成。行內級盒子包括行內盒子和原子行內級盒子兩種,區別在於該盒子是否參與行內格式化上下文的建立。行內格式化上下文(inline formatting context, IFC),就是當前區域。 行內盒子:inline box,參與行內格式化上下文建立的行內級盒子稱爲行內盒子。與塊盒子相似,行內盒子也分爲具名行內盒子和匿名行內盒子(anonymous inline box)兩種。 原子行內級盒子:atomic inline-level box,不參與行內格式化上下文建立的行內級盒子。原子行內級盒子一開始叫作原子行內盒子(atomic inline box),後被修正。原子行內級盒子的內容不會拆分紅多行顯示。
當元素的 display 爲 block、list-item 或 table 時,該元素將成爲塊級元素。一個塊級元素會被格式化成一個塊(例如文章的一個段落),默認按照垂直方向依次排列。
比較生硬的知識BFC,IFC,後面的說明中會用到:
建立BFC區域的方式:
根元素或包含根元素的元素 浮動元素(元素的 float 不是 none) 絕對定位元素(元素的 position 爲 absolute 或 fixed) 行內塊元素(元素的 display 爲 inline-block) 表格單元格(元素的 display爲 table-cell,HTML表格單元格默認爲該值) 表格標題(元素的 display 爲 table-caption,HTML表格標題默認爲該值) 匿名錶格單元格元素(元素的 display爲 table、table-row、 table-row-group、table-header-group、table-footer-group(分別是HTML table、row、tbody、thead、tfoot的默認屬性)或 inline-table) overflow 值不爲 visible 的塊元素 display 值爲 flow-root 的元素 contain 值爲 layout、content或 strict 的元素 彈性元素(display爲 flex 或 inline-flex元素的直接子元素) 網格元素(display爲 grid 或 inline-grid 元素的直接子元素) 多列容器(元素的 column-count 或 column-width 不爲 auto,包括 column-count 爲 1) column-span 爲 all 的元素始終會建立一個新的BFC,即便該元素沒有包裹在一個多列容器中
BFC對浮動定位與清除浮動都很重要。浮動定位和清除浮動時只會應用於同一個BFC內的元素。浮動不會影響其它BFC中元素的佈局,而清除浮動只能清除同一BFC中在它前面的元素的浮動。外邊距摺疊也只會發生在屬於同一BFC的塊級元素之間
BFC區域內模型的規則:
一、內部的box會在垂直方向,一個接一個的放置 二、每一個元素的margin box的左邊,與包含塊border box的左邊相接觸(對於從左往右的格式化,不然相反) 三、box垂直方向的距離由margin決定,屬於同一個BFC的兩個相鄰box的margin會發生重疊 四、BFC的區域不會與浮動區域的box重疊 五、BFC是一個頁面上的獨立的容器,外面的元素不會影響BFC裏的元素,反過來,裏面的也不會影響外面的 六、計算BFC高度的時候,浮動元素也會參與計算
來看一個例子,margin重疊的問題:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> * { margin: 0; padding: 0; } .top{ background: #0ff; height:100px; margin-bottom:30px; } .bottom{ height:100px; margin-top:50px; background: #ddd; } </style> </head> <body> <div class="top"> <h1>上</h1> margin-bottom:30px; </div> <div class="bottom"> <h1>下</h1> margin-top:50px; </div> </body> </html>
上述視圖效果,上下邊距重疊取最大的值。
用BFC能夠解決垂直margin重疊的問題
<section class="top"> <h1>上</h1> margin-bottom:30px; </section> <!-- 給下面這個塊添加一個父元素,在父元素上建立BFC --> <div style="overflow:hidden"> <section class="bottom"> <h1>下</h1> margin-top:50px; </section> </div>
每一個塊級盒子都會參與塊格式化上下文(block formatting context)的建立,而每一個塊級元素都會至少生成一個塊級盒子,即主塊級盒子(principal block-level box)。有一些元素,好比列表項會生成額外的盒子來放置項目符號,而那些會生成列表項的元素可能會生成更多的盒子。不過,多數元素只生成一個主塊級盒子。
主塊級盒子包含由後代元素生成的盒子以及內容,同時它也會參與定位方案。
定位規則:一旦生成了盒子之後,CSS引擎就須要定位它們以完成佈局。下面是定位盒子時所使用的規則:
普通流:按照次序依次定位每一個盒子 浮動:將盒子從普通流中單獨拎出來,將其放到外層盒子的某一邊 絕對定位:按照絕對位置來定位盒子,其位置根據盒子的包含元素所創建的絕對座標系來計算,所以絕對定位元素有可能會覆蓋其餘元素
一個塊級盒子可能也是一個塊容器盒子。塊容器盒子(block container box)要麼只包含其它塊級盒子,要麼只包含行內盒子並同時建立一個行內格式化上下文(inline formatting context)。
可以注意到塊級盒子與塊容器盒子是不一樣的這一點很重要。前者描述了元素與其父元素和兄弟元素之間的行爲,然後者描述了元素跟其後代之間的行爲。有些塊級盒子並非塊容器盒子,好比表格;而有些塊容器盒子也不是塊級盒子,好比非替換行內塊和非替換表格單元格。
一個同時是塊容器盒子的塊級盒子稱爲塊盒子(block box)。
在某些狀況下進行視覺格式化時,須要添加一些增補性的盒子,這些盒子不能用CSS選擇符選中,所以稱爲匿名盒子(anonymous boxes)。
CSS選擇器不能做用於匿名盒子(anonymous boxes),因此它不能被樣式表賦予樣式。也就是說,此時全部可繼承的 CSS 屬性值都爲 inherit ,而全部不可繼承的 CSS 屬性值都爲 initial。
塊包含盒子可能只包含行內級盒子,也可能只包含塊級盒子,但一般的文檔都會同時包含二者,在這種狀況下,就會在相鄰的行內級盒子外建立匿名塊盒子。
假如div和p標籤都保持默認樣式(即它們的 display 爲 block):
<div>Some inline text <p>followed by a paragraph</p> followed by more inline text.</div>
此時會產生兩個匿名塊盒子:一個是 <p> 元素前面的那些文本(Some inline text),另外一個是 <p> 元素後面的文本(followed by more inline text.)。此時會生成下面的塊結構:
對這兩個匿名盒子來講,程序員沒法像 <p> 元素那樣控制它們的樣式,所以它們會從 <div> 那裏繼承那些可繼承的屬性,如 color。其餘不可繼承的屬性則會設置爲 initial,好比,由於沒有爲它們指定 background-color,所以其具備默認的透明背景,而 <p> 元素的盒子則可以用CSS指定背景顏色。相似地,兩個匿名盒子的文本顏色老是同樣的。
另外一種會建立匿名塊盒子的狀況是一個行內盒子中包含一或多個塊盒子。此時,包含塊盒子的盒子會拆分爲兩個行內盒子,分別位於塊盒子的前面和後面。塊盒子前面的全部行內盒子會被一個匿名塊盒子包裹,塊盒子後面的行內盒子也是同樣。所以,塊盒子將成爲這兩個匿名塊盒子的兄弟盒子。
若是有多個塊盒子,而它們中間又沒有行內元素,則會在這些盒子的前面和後面建立兩個匿名塊盒子:
假設 <p> 的 display 爲 inline,<span> 的 display 爲 block:
<p>Some <em>inline</em> text <span>followed by a paragraph</span> followed by more inline text.</p>
此時會產生兩個匿名塊盒子:一個是 <span> 元素前面的文本(Some inline text),另外一個是其以後的文本(followed by more inline text.)。此時會生成下面的塊結構:
若是一個元素的 display 屬性爲 inline、inline-block 或 inline-table,則稱該元素爲行內級元素。顯示時,它不會生成內容塊,可是能夠與其餘行內級內容一塊兒顯示爲多行。一個典型的例子是包含多種格式內容(如強調文本、圖片等)的段落,就能夠由行內級元素組成。
行內級元素會生成行內級盒子,該盒子同時會參與行內格式化上下文(inline formatting context)的建立。行內盒子既是行內級盒子,也是一個其內容會參與建立其容器的行內格式化上下文的盒子,好比全部具備 display:inline 樣式的非替換盒子。若是一個行內級盒子的內容不參與行內格式化上下文的建立,則稱其爲原子行內級盒子。而經過替換行內級元素或 display 值爲 inline-block 或 inline-table 的元素建立的盒子不會像行內盒子同樣能夠被拆分爲多個盒子。
在同一個行內格式化上下文中,原子行內級盒子不能拆分紅多行:
<style> span { display:inline; /* default value*/ } </style> <div style="width:20em;"> The text in the span <span>can be split in several lines as it</span> is an inline box. </div>
顯示爲:
The text in the span can be split into several
lines as it is an inline box.
<style> span { display:inline-block; } </style> <div style="width:20em;"> The text in the span <span>cannot be split in several lines as it</span> is an inline-block box. </div>
顯示爲:
The text in the span
cannot be split into several lines as it is an
inline-block box.
其中的「cannot be split into several lines as it」永遠不會換行。
行內格式化上下文(inline formatting context)
行框(line boxes)
相對於BFC,在IFC中,框(boxes)一個接一個地水平排列,起點是包含塊的頂部。水平方向上的margin,border和padding在框之間獲得保留。框在垂直方向上能夠以不一樣的方式對齊:它們的頂部或底部對齊,或根據其中文字 的基線對齊。包含那些框的長方形區域,會造成一行,叫作行框。
行框的寬度有它的包含塊和其中的浮動元素決定。高度的肯定由行高度計算規則決定。
行框的範圍
一般,行框的左邊接觸到包含塊的左邊,右邊接觸到其包含塊的右邊。然而,浮動元素可能會處於包含塊邊緣和行框邊緣之間。總之,儘管在相同的行內格式化上下文中的行框一般擁有相同的寬度(包含塊的寬度),它們可能會因浮動元素縮短了可用寬度,而在寬度上發生變化。同一行內格式化上下文中行框一般高度不同(如,一行包含了一個高的圖形,而其它行只包含文本)。
例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> * { margin: 0; padding: 0; } .p-box { background: rgb(87, 97, 97); /* width: 100px; */ overflow: hidden; } .span-float { border: 2px solid rgb(255, 163, 163); font-size: 50px; float: left; } .inline { border: 2px solid rgb(102, 216, 197); font-size: 30px; } .primary { border: 2px solid rgb(248, 109, 207); } </style> </head> <body> <p class="p-box"> <span class="span-float">float</span> <em class="inline">inline box</em> <span class="primary">primary</span> </p> </body> </html>
顯示結果:
行內框可能被分割
若是幾個行內框在水平方向沒法放入一個行框內,它們能夠分配在兩個或多個垂直堆疊的行框中。所以,一個段落就是行框在垂直方向上的隊疊。行框在堆疊時沒有垂直方向上的分割且永不重疊。
若是一個行內框超出包含它的行框的寬度,它會被分割成幾個框,而且這些框會被分佈到幾個行框內。若是一個行框不能被分割(例如:行內框只包含單個字符,或者語言特殊的斷字規則不容許在行內框裏換行,或者行內框受到帶有「nowrap「或」pre「值的」white-space「特性的影響),這時,行內框會益處行框。
若是一個行內框被分割,margin,padding和border在全部分割處沒有視覺效果。
行內框還可能因爲雙向文本處理(bidirectional text processing)而在同一個行框內被分割爲好幾個框。具體看上面的例子。
行內框的對齊
1)、行內框在行框中垂直方向上的對齊
行框的高度老是足夠容納所包含的全部框。不過,它可能高於它包含的最高的框(例如:框對齊會引發基線對齊)。當一個框B的高度小雨包含它的行框的高度時,B在行框中垂直方向上的對齊決定於」vertical-aligin「的特性。」vertical-align「默認值基線(baseline)對齊。
貼一個關於基線(baseline)的圖,最直觀:
2)、行內框在行框中水平方向上的對齊
當一行中行內寬度的總和小於包含它們的行框的寬,它們在水平方向上的對齊,取決於"text-align"特性。若是其值是」justify「,用戶端也能夠拉伸行內框(除了」inline-table「和」inline-block「框)中的空間和文字。
空的行內框應該被忽略
不包含文本,保留空白符,margin/padding/border非0的行內元素,以及其餘常規流中的內容(好比,圖片,inline-blocks和inline-tables),而且不是以換行結束的行框,必須被看成0高度行框對待。就外邊距摺疊而言,這種行框必須被忽略。
相似於塊盒子,CSS引擎有時候也會自動建立一些行內盒子。這些行內盒子沒法被選擇符選中,所以是匿名的,它們從父元素那裏繼承那些可繼承的屬性,其餘屬性保持默認值 initial。
一種常見的狀況是CSS引擎會自動爲直接包含在塊盒子中的文本建立一個行內格式化上下文,在這種狀況下,這些文本會被一個足夠大的匿名行內盒子所包含。可是若是僅包含空格則有可能不會生成匿名行內盒子,由於空格有可能會因爲 white-space 的設置而被移除,從而致使最終的實際內容爲空。
在浮動定位中,浮動盒子會浮動到當前行的開始或尾部位置。這會致使普通流中的文本及其餘內容會「流」到浮動盒子的邊緣處,除非元素經過 clear 清除了前面的浮動。
一個盒子的 float 值不爲 none,而且其 position 爲 static 或 relative 時,該盒子爲浮動定位。若是將 float 設置爲 left,浮動盒子會定位到當前行盒子的開始位置(左側),若是設置爲 right,浮動盒子會定位到當前行盒子的尾部位置(右側)。不論是左浮動仍是右浮動,行盒子都會伸縮以適應浮動盒子的大小。
在絕對定位中,盒子會徹底從當前流中移除,而且不會再與其有任何聯繫(譯註:此處僅指定位和位置計算,而絕對定位的元素在文檔樹中仍然與其餘元素有父子或兄弟等關係),其位置會使用 top、bottom、left 和 right 相對其包含塊進行計算。
若是元素的 position 爲 absolute 或 fixed,該元素爲絕對定位。
對固定位置的元素來講,其包含塊爲整個視口,該元素相對視口進行絕對定位,所以滾動時元素的位置並不會改變。
GFC(GridLayout Formatting Contexts)意爲「網格佈局格式化上下文」當一個元素設置爲display:grid的時候,此元素將得到一個獨立的渲染區域,能夠在網格容器上定義網格行和列,爲每個網格定義位置和空間。GFC和table的區別在於GridLayout會有更加豐富的屬性來控制行列,控制對齊以及更爲精細的渲染。
FFC(Flex Formatting Contexts)意爲「自適應格式化上下文」,display值爲flex或者inline-flex的元素將會生成自適應容器,當前只有谷歌和火狐支持該屬性,不過在移動端幾乎沒有障礙(移動端是chrome和Safari的天下)。flex box由伸縮容器和伸縮子元素組成。經過設置元素display:flex/inline-flex能夠獲得伸縮容器,前者爲塊級元素,後者爲行內元素。伸縮容器外元素不受影響。