CSS:Margin與佈局

Margin與寬高度的關係

博客同步地址Margin與佈局css

在講此以前,必須知道什麼是containing-box以及一些寬高度的一些關係,關於containing-box的概念以及與寬高度的關係可看個人前一篇文章CSS:關於元素高度與寬度的討論 系列文章(三)html

1.元素containing-box寬高度等於內容寬度(原理1)

HTMLgit

<div class="wrap">
    <div class="item1"></div>
    <div class="item2"></div>
</div>

CSSgithub

.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的大小也在發生變化所以其邊緣線也在不斷變化同時也就致使.item1元素自身的位置也在發生變化,看起來就是.item1自身發生了移動。第二類margin的參考線是以元素自身的邊緣線(外邊距的外側爲邊緣線)爲參考線,一樣的,調整上例中的margin-bottom值,.item1的margin-bottom也在不斷的發生變化,也就是說其自身邊緣線在不斷的移動,同時致使了.item2的移動。根據上面的論述,咱們能夠得出結論,外邊距的調整也就等於讓其自身相對的參考線的位置在發生移動,同時致使相對於參考線運動的元素髮生移動。元素自身相對於containing-box的邊緣線移動而移動,與元素自身爲兄弟關係的元素相對於元素自身的邊緣線移動而移動。參考線示意圖如圖所示,按箭頭所指方向使參考線變化的margin值都爲正值。
綜上,咱們能夠利用margin對元素自身進行移動,同時也可以讓其相鄰元素進行移動,移動的同時咱們須要知道的是其所處的containing-box的大小也在發生變化。
圖片描述
綜上,當元素寬高度等於內容寬高度時,可經過調整內容的margin值來調整其containing-box的大小,由於containing-box的變化也就會致使元素自己的移動,也就是說既能夠移動元素,也可調整元素與元素之間的間距。segmentfault

2.元素內容寬度等於其containing-box的寬度(原理2)

<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自身大小發生變化,margin-left爲正值且值逐漸變大,則wrap-inner自身寬度逐漸變小,若margin-left爲負值且逐漸變小,則wrap-inner自身寬度逐漸變大,margin-right同理。必定要注意這裏的寬度繼承和width:100%是有本質區別的,由於width:100%就等於它的containing-box的100%和它的margin,border或者padding都木有關係,具體可看個人關於寬度與高度討論的系列文章三裏的例子,羅嗦了一點,可是這裏是容易犯錯誤的地方。必定要注意,必定要注意,必定要注意!!!。重要的事情說三遍。瀏覽器

  • 將margin-left和right調整爲-10px,如圖,根據計算,wrap-inner變寬
    圖片描述佈局

  • 將margin-left和right調整爲10px,如圖,根據計算,wrap-inner變窄
    圖片描述spa

綜上,當元素寬或高度等於其containing-box的寬度或高度時,且containing-box的寬度固定咱們即可以利用margin對其進行自身寬度大小的調整。也就是說寬高度和containing-box有關係時,咱們利用margin可進行內裏元素大小的調整。設計

利用Margin進行佈局

一般在佈局中咱們會遇到那些問題呢?下面是我本身實踐中遇到的一些問題3d

問題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

上面的例子僅僅只是實現了三列固定寬度的佈局,這樣的佈局當屏幕寬度發生變化的時候便會出現問題。所以咱們便會有以下需求。

左右列固定,中間列自適應

栗子
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,.right {
  float: left;
  width: 200px;
  height: 200px;
  background: #ccc;
}

.left {
  margin-left: -100%;
}

.right {
  margin-left: -200px;
}

效果以下,當你縮小屏幕時,中間部分會隨着屏幕的縮小而縮小,另外兩部分寬度不變,一樣也知足了主要內容優先加載的需求,可謂一箭雙鵰
圖片描述

分析

能夠看出上面的佈局利用了原理2,可是這裏仍然會有幾個爲何要問。

  • 首先,爲何main裏面必定要嵌套main-content,爲何不能直接使用單個main(假設1)?

  • 其次,爲何main上必定要設置float:left,能夠設置其餘值嗎,如position:absolute(假設2)?

分析上面的佈局以前,咱們也要了解到上面的佈局知足了咱們的什麼需求,這裏有兩點1.主要內容優先加載。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,.right {
  float: left;
  width: 200px;
  height: 200px;
  background: #ccc;
}
.left {
  margin-left: -100%;
}
.right {
  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,.right {
  width: 200px;
  height: 200px;
  background:#ccc;
}
.left {
  float: left;
}
.right {
  float: right;
}

答案是能夠的,只是咱們須要改掉一些值,而當main爲float之因此要給div.leftdiv.right要設置margin-left值是由於浮動元素浮動時,當它的外邊緣碰到包含框或者另外一個浮動框的邊框爲止。而爲浮動元素的div.main佔據了整整一行,所以下面的浮動元素div.leftdiv.right便被擠了下來,而設置它們的margin-left值即可以把它們移上去,這裏便運用了原理1。而當咱們把div.main的float值改成position:absolute時,便不會存在被擠下來的問題,可直接設置div.leftdiv.right的float的值。效果以下。
圖片描述
如若只須要達到寬度自適應的要求,那麼,這時候即可以將div.main放在最後面且不用嵌套div.main-content,具體如何實現,你們能夠本身試試。
兩列布局的道理也是差很少的,這裏我就不寫了,你們能夠看這篇文章
margin系列之佈局篇

問題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;前,效果如圖,發生了堆疊。
圖片描述
加了margin-right: -4px後,達到預期效果。由於加上了ul的右邊框發生了移動與第三個li的右邊框進行了重疊。所以效果上來看便符合了預期,如圖
圖片描述
此佈局便利用了原理1,經過元素對相鄰元素位置的控制來達到預期的效果。
而利用原理1也能夠實現元素居中的佈局,先讓元素上左各移50%,而後再讓設置元素的上左margin值設置爲元素自身寬度的一半長度,以對元素自己進行移動。即可達到元素居中放置的目的。

總結

1.元素寬度等於containing-box寬度時。能夠經過調整margin的值來調整元素的寬度。2.元素寬度與containing-box無關時。能夠經過調整margin的值來移動元素的位置。

相關文章
相關標籤/搜索