那些被忽略的盒子模型小知識

kenzung發表於2019-03-31

本文是筆者在學習CSS時的一些小白總結

我們知道的盒子模型主要由4個區域組成,分別是內容區域(content),內邊距區域(padding),邊框區域(border)和外邊距區域(margin)。 對於不瞭解盒子模型的朋友可以移步到這裡瞭解一下。

那些被忽略的盒子模型小知識

Content(內容)

1. 替換元素

替換元素(replaced element),顧名思義就是內容可以被替換的元素。

我們通常會把一些特殊意義的文字替換成圖片,比如一個網站的logo。

那些被忽略的盒子模型小知識
我們會在頁面上看到的不是h1標籤顯示的”Google“文字,而是谷歌logo的圖片。使用了content的元素的內容在html標籤中是不存在的。這樣做就有個好處,當爬蟲來訪問我們的網站,爬蟲可以知道我們這個主站的h1標題是”Google“而不是一個img標籤,且在視覺上給使用者更好的體驗。

2. 偽元素::before和::after

那些被忽略的盒子模型小知識
為了實現上面顯示價格,之前寫react程式碼時候會經常這麼寫,感覺在邏輯上寫了好多關聯性不大的文字。其實可以利用::before::after兩個偽元素,把這些與邏輯不相關的寫在css裡,react dom則專注於資料的表現。

<div className="price-panel">
  <span className="price-panel__price">
    ¥
    {(totalPrice / 100).toFixed(1)}
  </span>
  <span className="price-panel__discount-price">
    已省¥
    {(totalDiscountPrice / 100).toFixed(1)}
  </span>
  <span className="price-panel__discount">
    (
    {(discount / 10).toFixed(1)}
    折)
  </span>
</div>
複製程式碼

使用了偽元素後的react程式碼顯然更加清晰表示資料。 HTML:

<div className="price-panel">
  <span className="price-panel__price">
    {(totalPrice / 100).toFixed(1)}
  </span>
  <span className="price-panel__discount-price">
    {(totalDiscountPrice / 100).toFixed(1)}
  </span>
  <span className="price-panel__discount">
    {(discount / 10).toFixed(1)}
  </span>
</div>
複製程式碼

SCSS:

.price-panel {
  &__price {
    &::before {
      content: '¥';
    }
  }
  &__discount-price {
    &::before {
      content: '已省¥';
    }
  }
  &__discount {
    &::before {
      content: '(';
    }
    &::after {
      content: '折)';
    }
  }
}
複製程式碼

我們還能使用偽元素幫助實現一些本來需要多個div實現的樣式,比如下面這個對話方塊。

那些被忽略的盒子模型小知識

HTML:

<div class="dialog">Hi,I’m a bubble dialog. Can you see me?</div>
複製程式碼

CSS:

.dialog {
  background: #f0f;
  padding: 10px;
  border-radius: 10px;
  color: white;
  max-width: 250px;
  position: relative;
  overflow: visible;
}

.dialog::after {
  position: absolute;
  content: '';
  display: inline-block;
  border-width: 5px 10px;
  border-style: solid;
  border-color: transparent transparent #f0f #f0f;
  width: 0;
  height: 0;
  right: -20px;
}
複製程式碼

Padding(內邊距)

padding的百分比值是非常有用的。需要注意的padding的百分比值,無論是水平方向還是垂直方向都是相對於寬度進行計算的。

如果需要弄一張16:9的等比縮放圖片,可以利用padding的這個特性,設定一個padding-top或者padding-bottom為56.25%即可(100\16*9)

那些被忽略的盒子模型小知識

那些被忽略的盒子模型小知識

Margin(外邊距)

1. margin合併

塊級元素的margin-topmargin-bottom有時候會合併為單個margin,這種現象叫margin合併。 margin合併發生兩個重要元素

  1. 必須是塊級元素
  2. 只發生在垂直方向。

margin合併的場景

1.1 相鄰兄弟元素

那些被忽略的盒子模型小知識

1.2 父級和第一個/最後一個子元素

在實際開發中,父子margin合併很有可能會帶給我們麻煩。 如下圖所示,div表現出和我們預想不一致的結果。

那些被忽略的盒子模型小知識

那麼怎麼才能防止這種父子margin合併導致的和預想不一致問題呢? 解決方法如下(這裡直接複製了張鑫旭老師書籍《CSS世界》的原話。): (1)對於margin-top合併(滿足一個即可):

  • 父元素設定為BFC
  • 設定border-top的值(親測transparent也可以的)
  • 設定padding-top的值
  • 父元素和第一個子元素之間新增內聯元素

(2)對於margin-bottom合併(滿足一個即可):

  • 父元素設定為BFC
  • 設定border-bottom(transparent也可以的)
  • 設定padding-bottom
  • 父元素和最後一個子元素之間新增一個內聯元素
  • 父元素設定heightmin-height或者max-height

1.3 空塊級元素的margin合併

那些被忽略的盒子模型小知識

2. margin auto

每當說到margin:auto,我的第一反應是居中。但這個只是一個淺層應用的表象。 接下來我們去一起看看這個margin:auto究竟是‘何方神聖’。

margin:auto的填充規則如下:

  • 如果一側定值,一側auto,則auto為剩餘空間大小。注意auto並不是0的意思。
  • 如果兩側都是auto,則平分剩餘的空間

我會疑惑為什麼我設定了margin: auto,卻在垂直方向上沒有居中。

那些被忽略的盒子模型小知識

這裡《css世界》中給出的答案讓人非常容易理解。假如把.son元素的height去掉,.son的高度會自動變成父元素的200px,顯然不會,所以無法觸發margin: auto。同理,如果把width為200px去掉,確實是會和父元素一樣寬。

那麼如何讓垂直居中呢? 子元素使用絕對定位後設定margin: auto即可

那些被忽略的盒子模型小知識

Border(邊框)

用border繪製三角形

我們可以利用border color為透明來繪製一些圖形,比如三角形

那些被忽略的盒子模型小知識

注意border-color這個屬性。

/* border-color: color; 單值語法 */ 
border-color: red;

/* border-color: vertical horizontal; 雙值語法*/
border-color: red #f015ca;

/* border-color: top horizontal bottom; 三值語法 */
border-color: red yellow green;

/* border-color: top right bottom left; 四值語法 */
border-color: red yellow green blue;
複製程式碼

當然,我們繪製三角形不限於這種等腰三角。

那些被忽略的盒子模型小知識

這裡繪製了一個底邊分別是60px和160px的直角三角形。

參考

文章主要參考了張鑫旭老師的《css世界》並根據自己的業務做出的一些實踐總結。

相關文章