CSS佈局疑難雜症

margin-left:-100% 或-100px

  1. 使對象向左移動一段距離
    若100px是前一個div的寬度(100%指前一個div自己佔一行),則自己跑到前一個div的前面(或者窗口最左側);
  2. 只浮動,不使用margin左負值,後面的元素是會被擠在第二行的,使用margin負值後,div會上移

參考雙飛翼佈局

padding補償法

首先把列的padding-bottom設爲一個足夠大的值,再把列的margin-bottom設一個與前面的padding- bottom的正值相抵消的負值,父容器設置超出隱藏,這樣子父容器的高度就還是它裏面的列沒有設定padding-bottom時的高度,當它裏面的任 一列高度增加了,則父容器的高度被撐到它裏面最高那列的高度,其他比這列矮的列則會用它們的padding-bottom來補償這部分高度差。
因爲背景是 可以用在padding佔用的空間裏的,而且邊框也是跟隨padding變化的,所以就成功的完成了一個障眼法。

參考多列等高佈局

負邊距

  • 負邊距在普通文檔流中的作用和效果

    沒有脫離文檔流的元素(指不是浮動元素也不是絕對定位、固定定位的元素等),其在頁面中的位置是跟隨者文檔流的變化而變化的。

負邊距對這些由文檔流控制的元素的作用是,會使它們在文檔流中的位置發生偏移,但這種偏移不同於相對定位,通過相對定位偏移後,其仍然會堅守着它原來佔據的空間,不會讓文檔流的其它元素乘虛而入。而通過負邊距進行偏移的元素,它會放棄偏移前佔據的空間,這樣它後面文檔流中的其它元素就會“流”過來填充這部分空間

現在我們把上圖中的塊狀元素、行內元素以及inline-block元素都設一個負邊距 margin:-10px
這裏寫圖片描述
我們看到,黑灰色的塊狀元素好像向左和向上都分別嵌入了瀏覽器窗口的邊界裏10px,然後塊狀元素下面的文字也爬到了它身上,行內元素向左移動蓋住了它前面的一個字,它後面的文字也有一部分覆蓋在了它身上,inline-block的位置變化也很明顯。

好了,這點相信大家早就心知肚明瞭,就是負的邊距好像能減小元素在文檔流中的尺寸一樣,但事實上,它的尺寸大小並沒變,只是文檔流在計算元素位置的時候,會認爲負邊距把元素的尺寸減小了,因爲位置也就發生變化了。這只是打個很形象的比喻,幫助大家理解一下。還要注意的是,文檔流只能是後面的流向前面的,即文檔流只能向左或向上流動,不能向下或向右移動。

所以,一切只要是由文檔流決定的東西,負邊距就能起作用了。

比如,一個沒有設定高度的塊狀元素,其高度是自動的,具體來說就是由它裏面的文檔流最後的位置決定的。假設它裏面有一個出於文檔流中的子元素,高度爲100px;那這時這個父元素的高度就等於子元素的高度100px了,如果子元素繼續增高,那麼父元素也會跟着增高。可是如果這時子元素設一個負的margin-bottom,比如-20px,因爲負邊距會影響到文檔流,本來文檔流的高度是從父元素的最頂端到子元素的最底端這段高度,現在子元素有一個margin-bottom:-20px;就相當於文檔流要向上退後20px,這樣整個文檔流的高度就減少了20px了,那麼父元素的高度也會跟着減少20px。在IE8+以及那些標準瀏覽器中,這還需要父元素擁有一個overflow:hidden的屬性,因爲父元素的高度變了,但子元素的高度並沒有變,所以需要使子元素超出隱藏,但即使不設置overflow:hidden,父元素的高度也是變小了的,只不過這時子元素的高度會超出父元素。在IE6中則不需要,但需要觸發它的hasLayout屬性。所以以前所說的多列等高佈局就是利用這個原理來實現的。

總之一句話,在文檔流中,元素的最終邊界是由margin決定的,margin爲負的時候就相當於元素的邊界向裏收,文檔流認的只是這個邊界,不會管你實際的尺寸是多少。

  • 左和右的負邊距對元素寬度的影響
    負邊距不僅能影響元素在文檔流中的位置,還能增加元素的寬度

這個作用能實現的前提是:該元素沒有設定width屬性(當然width:auto是可以的)。

這裏寫圖片描述
- 負邊距對浮動元素的影響
負邊距對浮動元素的影響與負邊距對文檔流中元素的影響其實是差不多的。文檔流中元素的位置由文檔流的走向決定,浮動的元素也可以看成有一個“浮動流”存在,不過浮動流既可以向左,也可以向右
這裏寫圖片描述
這裏寫圖片描述
所以那些說得很好聽的什麼聖盃佈局、雙飛翼佈局啊什麼的,都是利用這個原理實現的。就是某個元素雖然是寫在了後面,但可以通過負邊距讓它在瀏覽器顯示的時候是在前面的。

  • 負邊距對絕對定位元素的影響
    絕對定位的元素定義的top、right、bottom、left等值是元素自身的邊界到最近的已定位的祖先元素的距離,這個元素自身的邊界指的就是margin定義的邊界,所以,如果margin爲正的時候,那它的邊界是向外擴的,如果margin爲負的時候,則它的邊界是向裏收的。利用這點,就有了經典的利用絕對定位來居中的方法
    這裏寫圖片描述
    但該方法的缺點是必須要知道要居中元素的高度和寬度。

垂直外邊距的合併問題margin cllapse

  1. 在標準流中上下兩個盒子的外邊距回合,即上盒子的margin-bottom會與下盒子的margin-top合併爲兩者之間的最大值。

這裏寫圖片描述

2 一個盒子包裹另一個盒子,當包裹盒子沒有設置border和padding時,裏邊盒子的設置的上邊距不會起作用。

這裏寫圖片描述
設置邊框後
這裏寫圖片描述

解釋:

對於父塊DIV內含子塊DIV的情況,就會按另一條CSS慣例來解釋了,那就是:對於有塊級子元素的元素計算高度的方式,如果元素沒有垂直邊框和填充,那其高度就是其子元素頂部和底部邊框邊緣之間的距離。

解決方法:

解決父子DIV中頂部margin cllapse的問題,需要給父div設置:

(1)邊框,當然可以設置邊框爲透明;

   border:1px solid transparentborder-top:1px solid transparent

(2)、爲父DIV添加padding,或者至少添加padding-top;
此外,還可以通過over-flow來解決,給父DIV寫入:

over-flow:hidden;

CSS標準流佈局 normal flow

大多數元素都在正常流中,要讓一個元素不在正常流中,唯一的方法就是使之成爲浮動元素或定位元素。

標準流中,塊級元素獨佔一行,垂直放置。行級元素在水平方向上一個接一個的排列。

BFC

1、BFC是什麼?

在解釋 BFC 是什麼之前,需要先介紹 Box、Formatting Context的概念。

Box 是 CSS 佈局的對象和基本單位, 直觀點來說,就是一個頁面是由很多個 Box 組成的。
元素的類型和 display 屬性,決定了這個 Box 的類型。 不同類型的 Box, 會參與不同的 Formatting Context(一個決定如何渲染文檔的容器),因此Box內的元素會以不同的方式渲染。讓我們看看有哪些盒子:

block-level box:display 屬性爲 block, list-item, table 的元素,會生成 block-level box。並且參與 block fomatting context;
inline-level box:display 屬性爲 inline, inline-block, inline-table 的元素,會生成 inline-level box。並且參與 inline formatting context;

  
Formatting context
  
Formatting context 是 W3C CSS2.1 規範中的一個概念。它是頁面中的一塊渲染區域,並且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關係和相互作用。最常見的 Formatting context 有 Block fomatting context (簡稱BFC)和 Inline formatting context (簡稱IFC)。

  
CSS2.1 中只有 BFC 和 IFC, CSS3 中還增加了 GFC 和 FFC。

  
1.BFC 定義
  
BFC(Block formatting context)直譯爲”塊級格式化上下文”。它是一個獨立的渲染區域,只有Block-level box參與, 它規定了內部的Block-level Box如何佈局,並且與這個區域外部毫不相干。

BFC佈局規則:

  • 內部的Box會在垂直方向,一個接一個地放置。
  • Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊
  • 每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,否則相反)。即使存在浮動也是如此。
  • BFC的區域不會與float box重疊。
  • BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素。反之也如此。
  • 計算BFC的高度時,浮動元素也參與計算

2、哪些元素會生成BFC?

  • 根元素
  • float屬性不爲none
  • position爲absolute或fixed
  • display爲inline-block, table-cell, table-caption, flex, inline-flex
  • overflow不爲visible

3、BFC的作用及原理

  • 自適應兩欄佈局
    這裏寫圖片描述

根據BFC佈局規則第3條:
每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,否則相反)。即使存在浮動也是如此。

  因此,雖然存在浮動的元素aslide,但main的左邊依然會與包含塊的左邊相接觸。
  
  這裏寫圖片描述
 

根據BFC佈局規則第四條:
BFC的區域不會與float box重疊。

我們可以通過通過觸發main生成BFC, 來實現自適應兩欄佈局。

.main {
overflow: hidden;
}

  當觸發main生成BFC後,這個新的BFC不會與浮動的aside重疊。因此會根據包含塊的寬度,和aside的寬度,自動變窄。

  • 清除內部浮動
<style>
.par {
    border: 5px solid #fcc;
    width: 300px;
}
.child {
    border: 5px solid #f66;
    width:100px;
    height: 100px;
    float: left;
}
</style>
<body>
<div class="par">
    <div class="child"></div>
    <div class="child"></div>
</div>
</body>
頁面

這裏寫圖片描述

根據BFC佈局規則第六條:
計算BFC的高度時,浮動元素也參與計算

  爲達到清除內部浮動,我們可以觸發par生成BFC,那麼par在計算高度時,par內部的浮動元素child也會參與計算。

 代碼:

.par {
    overflow: hidden;
}

這裏寫圖片描述

  • 防止垂直 margin 重疊
<style>
p {
    color: #f55;
    background: #fcc;
    width: 200px;
    line-height: 100px;
    text-align:center;
    margin: 100px;
}
</style>
<body>
<p>Haha</p>
<p>Hehe</p>
</body>

這裏寫圖片描述

兩個p之間的距離爲100px,發送了margin重疊。

 根據BFC佈局規則第二條:
Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊

  我們可以在p外面包裹一層容器,並觸發該容器生成一個BFC。那麼兩個P便不屬於同一個BFC,就不會發生margin重疊了。

<style>
.wrap {
    overflow: hidden;
}
p {
    color: #f55;
    background: #fcc;
    width: 200px;
    line-height: 100px;
    text-align:center;
    margin: 100px;
}
</style>
<body>
<p>Haha</p>
<div class="wrap">
    <p>Hehe</p>
</div>
</body>

這裏寫圖片描述

總結

其實以上的幾個例子都體現了BFC佈局規則第五條:

BFC就是頁面上的一個隔離的獨立容器,容器裏面的子元素不會影響到外面的元素反之也如此。

因爲BFC內部的元素和外部的元素絕對不會互相影響,因此, 當BFC外部存在浮動時,它不應該影響BFC內部Box的佈局,BFC會通過變窄,而不與浮動有重疊。同樣的,當BFC內部有浮動時,爲了不影響外部元素的佈局,BFC計算高度時會包括浮動的高度。避免margin重疊也是這樣的一個道理。

IFC

IFC(Inline Formatting Contexts)直譯爲”內聯格式化上下文”,IFC的line box(線框)高度由其包含行內元素中最高的實際高度計算而來(不受到豎直方向的padding/margin影響)
IFC中的line box一般左右都貼緊整個IFC,但是會因爲float元素而擾亂。float元素會位於IFC與與line box之間,使得line box寬度縮短。 同個ifc下的多個line box高度會不同。 IFC中時不可能有塊級元素的,當插入塊級元素時(如p中插入div)會產生兩個匿名塊與div分隔開,即產生兩個IFC,每個IFC對外表現爲塊級元素,與div垂直排列。
那麼IFC一般有什麼用呢?

水平居中:當一個塊要在環境中水平居中時,設置其爲inline-block則會在外層產生IFC,通過text-align則可以使其水平居中。
垂直居中:創建一個IFC,用其中一個元素撐開父元素的高度,然後設置其vertical-align:middle,其他行內元素則可以在此父元素下垂直居中

GFC

GFC(GridLayout Formatting Contexts)直譯爲”網格佈局格式化上下文”,當爲一個元素設置display值爲grid的時候,此元素將會獲得一個獨立的渲染區域,我們可以通過在網格容器(grid container)上定義網格定義行(grid definition rows)和網格定義列(grid definition columns)屬性各在網格項目(grid item)上定義網格行(grid row)和網格列(grid columns)爲每一個網格項目(grid item)定義位置和空間。
那麼GFC有什麼用呢,和table又有什麼區別呢?首先同樣是一個二維的表格,但GridLayout會有更加豐富的屬性來控制行列,控制對齊以及更爲精細的渲染語義和控制。

FFC

FFC(Flex Formatting Contexts)直譯爲”自適應格式化上下文”,display值爲flex或者inline-flex的元素將會生成自適應容器(flex container),可惜這個牛逼的屬性只有谷歌和火狐支持,不過在移動端也足夠了,至少safari和chrome還是OK的,畢竟這倆在移動端纔是王道。
Flex Box 由伸縮容器和伸縮項目組成。通過設置元素的 display 屬性爲 flex 或 inline-flex 可以得到一個伸縮容器。設置爲 flex 的容器被渲染爲一個塊級元素,而設置爲 inline-flex 的容器則渲染爲一個行內元素。
伸縮容器中的每一個子元素都是一個伸縮項目。伸縮項目可以是任意數量的。伸縮容器外和伸縮項目內的一切元素都不受影響。簡單地說,Flexbox 定義了伸縮容器內伸縮項目該如何佈局。

世界一切皆對象

Flex佈局

http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=tuicool
這個教程講解得很好,看了好幾遍了,悟出來最重要的牢記以下幾點

1.確定容器和項目

採用Flex佈局的元素,稱爲Flex容器(flex container),簡稱”容器”。
它的所有子元素自動成爲容器成員,稱爲Flex項目(flex item),簡稱”項目”。

2.找準主軸,交叉軸

容器默認存在兩根軸:水平的主軸(main axis)和垂直的交叉軸(cross axis)。主軸的開始位置(與邊框的交叉點)叫做main start,結束位置叫做main end;交叉軸的開始位置叫做cross start,結束位置叫做cross end

這裏寫圖片描述

3.重要的屬性—看準誰確定交叉軸,是容器還是項目的屬性

  • flex-direction屬性決定主軸的方向(即項目的排列方向)。
    row(默認值):主軸爲水平方向,起點在左端。項目水平排列

  • justify-content屬性定義了項目在主軸上的對齊方式。
    flex-start(默認值):左對齊

  • align-items屬性定義項目在交叉軸上如何對齊
    stretch(默認值):如果項目未設置高度或設爲auto,將佔滿整個容器的高度。

  • align-content屬性定義了多根軸線的對齊方式。

  • flex屬性

4.關注簡寫形式

容器:

  • flex-flow
    flex-flow屬性是flex-direction屬性和flex-wrap屬性的簡寫形式,默認值爲row nowrap。
.box {
  flex-flow: <flex-direction> || <flex-wrap>;
}

項目:

flex屬性是flex-grow, flex-shrink 和 flex-basis的簡寫,默認值爲0 1 auto。後兩個屬性可選。

.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

該屬性有兩個快捷值:auto (1 1 auto) 和 none (0 0 auto)。
建議優先使用這個屬性,而不是單獨寫三個分離的屬性,因爲瀏覽器會推算相關值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章