CSS的margin屬性在頁面布局中的使用攻略

基礎
1.元素containing-box寬高度等于內容寬度
HTML
- <div class="wrap">
- <div class="item1"></div>
- <div class="item2"></div>
- </div>
CSS
- .wrap {
- float: left;
- border: 2px solid #000;
- }
- .item1 {
- width: 100px;
- height: 100px;
- background: #fdf;
- margin-left: 10px;
- margin-top: 10px;
- margin-right: 20px;
- margin-bottom: 30px;
- }
- item2 {
- width: 50px;
- height: 50px;
- background: #adf;
- }
能滿足原理1的條件只有一種,元素不設寬度且不在文檔流中,此時,父元素wrap產生的containing-box的寬高寬度等子元素border-box的寬高度加上外邊距的寬高度,也就是說,子元素的margin值也是其containing-box的一部分。margin一共有兩類參考線,第一類是margin-top與margin-left的參考線,第二類是margin-bottom與margin-right的參考線,第一類margin的參考線是以其所處的containing-box的邊緣線為參考線,如上例所示,當調整元素.item1的margin-top與margin-left的值時,元素.item1所處的containing-box的大小也在發(fā)生變化因此其邊緣線也在不斷變化同時也就導致.item1元素自身的位置也在發(fā)生變化,看起來就是.item1自身發(fā)生了移動。第二類margin的參考線是以元素自身的邊緣線(外邊距的外側為邊緣線)為參考線,同樣的,調整上例中的margin-bottom值,.item1的margin-bottom也在不斷的發(fā)生變化,也就是說其自身邊緣線在不斷的移動,同時導致了.item2的移動。根據上面的論述,我們可以得出結論,外邊距的調整也就等于讓其自身相對的參考線的位置在發(fā)生移動,同時導致相對于參考線運動的元素發(fā)生移動。元素自身相對于containing-box的邊緣線移動而移動,與元素自身為兄弟關系的元素相對于元素自身的邊緣線移動而移動。參考線示意圖如圖所示,按箭頭所指方向使參考線變化的margin值都為正值。
綜上,我們可以利用margin對元素自身進行移動,同時也可讓其相鄰元素進行移動,移動的同時我們需要知道的是其所處的containing-box的大小也在發(fā)生變化。
綜上,當元素寬高度等于內容寬高度時,可通過調整內容的margin值來調整其containing-box的大小,因為containing-box的變化也就會導致元素本身的移動,也就是說既可以移動元素,也可調整元素與元素之間的間距。
2.元素內容寬度等于其containing-box的寬度
- <div class="wrap">
- <div class="wrap-inner"></div>
- </div>
- .wrap {
- width: 100px;
- border: 2px solid #000;
- margin: 0 auto;
- }
- .wrap-inner {
- height: 50px;
- background: #fdf;
- }
上例中,元素wrap-inner的border-box寬度加上margin的大小等于其containing-box的寬度,因此當containing-box寬度固定,根據公式'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block,調整其自身margin-left或margin-right值,便會使wrap-inner自身大小發(fā)生變化,margin-left為正值且值逐漸變大,則wrap-inner自身寬度逐漸變小,若margin-left為負值且逐漸變小,則wrap-inner自身寬度逐漸變大,margin-right同理。一定要注意這里的寬度繼承和width:100%是有本質區(qū)別的,因為width:100%就等于它的containing-box的100%和它的margin,border或者padding都木有關系,具體可看我的關于寬度與高度討論的系列文章三里的例子,羅嗦了一點,但是這里是容易犯錯誤的地方。一定要注意,一定要注意,一定要注意?。?!。重要的事情說三遍。
將margin-left和right調整為-10px,如圖,根據計算,wrap-inner變寬
將margin-left和right調整為10px,如圖,根據計算,wrap-inner變窄
綜上,當元素寬或高度等于其containing-box的寬度或高度時,且containing-box的寬度固定我們便可以利用margin對其進行自身寬度大小的調整。也就是說寬高度和containing-box有關系時,我們利用margin可進行內里元素大小的調整。
不同元素margin的計算
行內級元素
Inline,非置換元素:如果margin值為auto,則margin-left和margin-right的計算值也就為0
Inline,置換元素:同上
Inline-block,置換元素在文檔流中:同上
Inline-block,非置換元素在文檔流中:同上
塊級元素
塊級非置換元素,在文檔流中
'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
下面的情況下,如果margin值為auto
如果width是auto值,那么其他值是auto的值就為0
如果margin-left和margin-right的值為auto,使用的值相等,那么就相對于包含塊水平居中。
塊級置換元素,在文檔流中
同塊級非置換元素一樣。
小結
行內級置換元素和非置換元素,在margin值為auto時,margin-left和margin-auto的計算值都為0。
塊級置換元素和非置換元素:
'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
如果width是auto值,那么其他值是auto的值就為0
如果margin-left和margin-right的值為auto,使用的值相等,那么就相對于包含塊水平居中。
利用Margin進行布局
通常在布局中我們會遇到那些問題呢?下面是我自己實踐中遇到的一些問題
問題1
當我們拿到一份設計稿,然后這份設計稿有像下面這樣的布局,整體居中,里面元素排一排,當然布局的方式會有很多種,那么如果我們采用浮動布局或者display:inline-block進行布局會出現什么問題呢,如圖我們可以看出,若采用上述兩種方式進行布局,那么每個塊的寬度加上間隙,就會超出包含塊的寬度,當然我們也可以將包含塊的寬度進行增大以留下足夠的位置供元素擺放,但是這種方法明顯是不可取的,那么如何解決這個位置不夠的問題呢,可以看下面的栗子1 。
栗子
html
- <div class="container">
- <div class="inner-wrap">
- <div class="inner"></div>
- <div class="inner"></div>
- <div class="inner"></div>
- </div>
- </div>
css
- body {
- margin: 0;
- }
- .container {
- margin: 0 auto;
- width: 980px;
- }
- .inner-wrap {
- margin-left: -10px;
- }
- .inner {
- float: left;
- margin-left: 10px;
- width: 320px;
- height: 200px;
- background: #2df;
- }
此布局便利用了原理2,利用負margin增加了inner-wrap的寬度,但不改變整體的寬的情況下,實現效果。如下
問題2
上面的例子僅僅只是實現了三列固定寬度的布局,這樣的布局當屏幕寬度發(fā)生變化的時候便會出現問題。因此我們便會有如下需求。
左右列固定,中間列自適應
栗子
html
- <div class="main">
- <div class="main-content"></div>
- </div>
- <div class="left"></div>
- <div class="right"></div>
css
- .main {
- float: left;
- width: 100%;
- }
- .main-content {
- height: 200px;
- background: #2da;
- margin: 0 200px;
- }
- .left,.rightright {
- float: left;
- width: 200px;
- height: 200px;
- background: #ccc;
- }
- .left {
- margin-left: -100%;
- }
- .rightright {
- margin-left: -200px;
- }
效果如下,當你縮小屏幕時,中間部分會隨著屏幕的縮小而縮小,另外兩部分寬度不變,同樣也滿足了主要內容優(yōu)先加載的需求,可謂一舉兩得
分析:
可以看出上面的布局利用了原理2,但是這里仍然會有幾個為什么要問。
首先,為什么main里面一定要嵌套main-content,為什么不能直接使用單個main(假設1)?
其次,為什么main上一定要設置float:left,可以設置其他值嗎,如position:absolute(假設2)?
分析上面的布局之前,我們也要了解到上面的布局滿足了我們的什么需求,這里有兩點1.主要內容優(yōu)先加載。2.主要內容自適應。這里我們可以分析一下,我們是怎樣達到上述兩個目的的。首先,要達到目的1,我們就的把div.main放在前面來寫,因為瀏覽器是從下到下渲染頁面的,放在前面的也就會先渲染。且由于div.main為文檔流中的塊級元素,因此會獨占一行,因此我們需要使其脫離文檔流,這樣才能使下面的元素能有機會上的來(這里之所以不考慮display:inline-block是因為div.main的長度會獨占一行,就算設置display:inline-block也沒有任何作用,下面的元素仍然上不來)。而要達到目的2,需要用到原理2。同時在上面提出的兩個問題中,有兩個假設。
假設1,如果使用單個main可不可以滿足上述兩個需求?我們可以試試。
html
- <div class="main"></div>
- <div class="left"></div>
- <div class="right"></div>
css
- body {
- margin:0;
- }
- /*這里注意需要改掉main的流方式,下面的元素才上的來*/
- .main {
- float:left
- margin: 0 210px;
- height: 200px;
- background:#2da;
- }
- .left,.rightright {
- float: left;
- width: 200px;
- height: 200px;
- background: #ccc;
- }
- .left {
- margin-left: -100%;
- }
- .rightright {
- margin-left: -200px;
- }
從中線分開的黃色兩部分為各自為main的左右外邊距
從結果中,我們可以看出使用單個main是不行的,因為在不設寬度且元素不在文檔流中時,元素的寬度為0,不能滿足我們的需求,正因為我們同時要滿足1.main元素不在文檔流中2.元素不設寬度且在文檔流中。這兩個條件當然是不能同時在一個main元素下能達到的,因此我們需要再嵌套一個main-content讓它來滿足條件2。這也就解釋了為什么一定要嵌套一個main-content。
解決了問題1,現在我們來說問題2。
假設2,main上的float值可以換為position:absolute嗎?
同樣的,我們試試
html
- <div class="main">
- <div class="main-content"></div>
- </div>
- <div class="left"></div>
- <div class="right"></div>
css
- body {
- margin: 0;
- }
- .main {
- position:absolute;
- width:100%;
- }
- .main-content {
- margin: 0 210px;
- height: 200px;
- background: #2da;
- }
- .left,.rightright {
- width: 200px;
- height: 200px;
- background:#ccc;
- }
- .left {
- float: left;
- }
- .rightright {
- float: rightright;
- }
答案是可以的,只是我們需要改掉一些值,而當main為float之所以要給div.left與div.right要設置margin-left值是因為浮動元素浮動時,當它的外邊緣碰到包含框或者另一個浮動框的邊框為止。而為浮動元素的div.main占據了整整一行,因此下面的浮動元素div.left與div.right便被擠了下來,而設置它們的margin-left值便可以把它們移上去,這里便運用了原理1。而當我們把div.main的float值改為position:absolute時,便不會存在被擠下來的問題,可直接設置div.left與div.right的float的值。效果如下。
如若只需要達到寬度自適應的要求,那么,這時候便可以將div.main放在最后面且不用嵌套div.main-content,具體如何實現,大家可以自己試試。
問題3
如下所示設計稿,在我們進行布局的過程中,可能會出現border重合的情況,因為一方面我們需要對整個整體加上border,而另一方面我們又需要利用border隔開那三個小塊。那么如果我們對每個小塊都加上右邊框,可以想象,最右邊就會出現邊框的堆疊而這不是我們希望看到的,所以,要如何解決這個問題,可以看如下例子給出的答案。
栗子
html
- <ul>
- <li>1</li>
- <li>2</li>
- <li>3</li>
- </ul>
css
- ul {
- position:absolute;
- margin: 0;
- padding:0;
- list-style:none;
- border: 4px solid #c5c5c5;
- }
- li {
- float:left;
- width: 200px;
- height: 50px;
- line-height: 50px;
- text-align: center;
- border-right: 4px solid #c5c5c5;
- }
沒在li上加margin-right:-4px;前,效果如圖,發(fā)生了堆疊。
加了margin-right: -4px后,達到預期效果。因為加上了ul的右邊框發(fā)生了移動與第三個li的右邊框進行了重疊。因此效果上來看便符合了預期,如圖
此布局便利用了原理1,通過元素對相鄰元素位置的控制來達到預期的效果。
而利用原理1也可以實現元素居中的布局,先讓元素上左各移50%,然后再讓設置元素的上左margin值設置為元素自身寬度的一半長度,以對元素本身進行移動。便可達到元素居中放置的目的。
總結
1.元素寬度等于containing-box寬度時。
可以通過調整margin的值來調整元素的寬度。
2.元素寬度與containing-box無關時。
可以通過調整margin的值來移動元素的位置。
相關文章
- 下面小編就為大家?guī)硪黄獪\談css margin重疊。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-07-19
- 下面小編就為大家?guī)硪黄狢SS 之margin知識點(必看)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-07-10
- 這篇文章主要為大家詳細介紹了css布局之負margin妙用及其他實現的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-07-07
- 這篇文章和大家詳細說一說CSS中margin屬性的使用,重點描述了關于margin,我們日常不太容易發(fā)現的“坑,感興趣的小伙伴們可以參考一下2016-02-25
- 這篇文章主要介紹了CSS中的margin屬性的使用,margin是元素盒模型(box model)的基礎屬性,常被用來設置外邊距,實際用途非常廣泛,需要的朋友可以參考下2016-02-02
- 這篇文章主要介紹了CSS中使用負margin值來調整居中位置的方法,文中同時提到了這種常用方法的一些值得注意的地方,需要的朋友可以參考下2015-07-15
- margin 簡寫屬性在一個聲明中設置所有外邊距屬性。該屬性可以有 1 到 4 個值。這個簡寫屬性設置一個元素所有外邊距的寬度,或者設置各邊上外邊距的寬度。塊級元素的垂直相2014-10-22
- 這篇文章主要介紹了解決margin 外邊距合并問題 ,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-07-03