實用的 Web 佈局技巧:Flex 主軸上的自動外邊距

問題描述

先來看一個需求場景:

圖片描述

上圖中需要實現在水平方向上子元素之間、子元素和父容器邊框之間的間距要相等。

實現的方法有很多,我們這裏要討論的是:如何簡潔地使用 Flex 佈局來實現?
我這裏採用的方法是:使用自動的外邊距在主軸上對齊。

自動的外邊距在主軸上對齊

我們先來看一下 MDN 關於這個的解釋:

... 自動的外邊距會佔據全部的多餘的空間——在一個塊上設置自動的左右外邊距可以使它居中。兩邊儘可能佔據多的空間,塊就被置於中間位置了。

這很好理解:自動外邊距將平分全部的剩餘空間。下面就來嘗試下這個方案吧,代碼如下:

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
</div>
.container {
  display: flex;
  align-items: center;
  box-sizing: border-box;
  border: 2px dashed #7cb305;
  width: 600px;
  height: 200px;
  margin: auto;
}


.item {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0 auto;
  width: 100px;
  height: 100px;
  background: #722ed1;
  border-radius: 50%;
  color: #fff;
  font-size: 22pt;
}

然後看一下效果:

圖片描述

貌似有點不對。仔細看看子元素之間的間距比到邊框的大,大概是子元素到邊框的兩倍,跟我們預期的效果有差異。
按照 MDN 的解釋來看,自動的外邊距會等分剩餘空間,但爲什麼會出現上圖的情況呢?下面來談一下我的理解。

主軸剩餘空間“分配權重”與子元素自動外邊距的關係

這個分配權重關係沒有在 MDN 上找到相關解釋,純粹是個人見解,我們可以這樣來理解:

  • 如果一個子元素在主軸的一個區域(或方向)上聲明瞭 margin-*: auto,那麼這個空間的分配權重 + 1
  • 如果另外一個子元素也在同樣的區域(或方向)上有自動外邊距的聲明,那麼分配權重再 + 1
  • 在這些聲明瞭自動外邊距的區域上,剩餘空間根據分配權重來劃分間距大小

首先,這個理解顯然是可以滿足 MDN 上的解釋。然後我們再來看看上圖的情況怎麼解釋:

  • 我們把 子元素1 的左邊區域命名爲 間距區域1子元素1 的右邊區域命名爲 間距區域2
  • 子元素1 的左邊和右邊都有自動外邊距,那麼 間距區域1的權重 = 1間距區域2的權重 = 1
  • 子元素2 的左邊和右邊都有自動外邊距,那麼 間距區域2的權重 = 1 + 1 = 2
  • 最後 間距區域1的權重間距區域1的權重 就是 1:2 的關係
  • 其他區域依次類推,最後根據權重劃分間距區域大小

然後依據這種理解我們來調整下代碼,只需要在每個相隔的區域上聲明一次自動外邊距就好了:

  • 首先我們把 .item 這個樣式上的 margin 去掉
  • 然後只在 html 的 子元素1子元素3 上設置 style="margin: 0 auto"

調整後如下:

<div class="container">
  <div class="item" style="margin: 0 auto">1</div>
  <div class="item">2</div>
  <div class="item" style="margin: 0 auto">3</div>
</div>
.container {
  display: flex;
  align-items: center;
  box-sizing: border-box;
  border: 2px dashed #7cb305;
  width: 600px;
  height: 200px;
  margin: auto;
}


.item {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100px;
  height: 100px;
  background: #722ed1;
  border-radius: 50%;
  color: #fff;
  font-size: 22pt;
}

OK,問題解決了
根據這個理解還有一種設置也可以達到同樣效果:

<div class="container">
  <div class="item" style="margin-left: auto">1</div>
  <div class="item" style="margin: 0 auto">2</div>
  <div class="item" style="margin-right: auto">3</div>
</div>

以上代碼已放到 codepen 上:https://codepen.io/deepfunc/pen/BembyQ
各位童鞋如果覺得還可以請點贊和收藏下哈

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