由 Bootstrap 的媒體物件(Media object) 談 flexbox

ziyoung發表於2017-12-19

CSS3 彈性盒子(flexbox),是一種新的佈局方式。使用 flexbox,可以很方便的實現常見的佈局以及居中效果。Bootstrap v4 的 Media object 也是使用 flexbox 來實現。flexbox 相關的屬性較多,本文便結合幾種的情形來探討 flexbox 的應用場景。

Boostrap v3 中的 Media object 使用 table-cell 實現,新版本則採用了 flexbox。table-cell 是一個不太常見的屬性,使用該屬性主要是:1. 實現兩欄或者多欄佈局;2.很容易實現元素垂直居中效果。

v4 版本使用了 flexbox,完成功能的同時,相較於 v3 更加簡潔了。下面我們來結合 Media Object 介紹 flexbox 的相關知識。

1. 常見的 Media object

Media object 用來實現常見的兩欄或者多欄佈局。

常見的三欄佈局

html 片段:

<div class="media">
    <img class="media-left media-pic" src="../assets/logo.png" />
    <div class="media-body">body</div>
    <div class="media-right">right</div>
</div>
複製程式碼

scss 片段:

.media {
    display: flex;
    .media-pic {
        width: 50px;
        height: 50px;
        margin-right: 10px;
    }
    .media-body {
        flex: 1 1 230px;
        background-color: #b1b1b1;
    }
    .media-right {
        width: 50px;
    }
}

複製程式碼

在需要佈局的區域設定 display: flex 就完成了最基本的佈局。通過在 media-body 部分設定 flex: 1 來讓這部分自動佔據剩餘寬度。flex 是 flex-grow,flex-shrink 與 flex-basis 的簡寫,flex: 1 相當於 flex: 1 1 none,其中 flex-shink 為 1,該元素寬度擴張為剩餘的寬度。

2. 常見的居中效果

有了 flexbox,我們可以很方便實現一些居中效果。這裡討論兩種情形的居中。

2.1 元素的居中

在沒有 flexbox 之前,讓一個塊級元素垂直居中用的是 負外邊距 或者 table-cell 的方式來實現。現在有了 flexbox,居中很容易實現。

html 片段:

<div class="vertical-container">
    <p>簡單的垂直居中佈局的方法</p>
</div>
複製程式碼

scss 片段:

.vertical-container {
    display: flex;
    align-items: center;
    justify-content: center;
}
複製程式碼

2.2 align-self-center

在進行多欄佈局中,我們其中的某一項垂直居中,Bootstrap 提供了一個 align-self-center 的類。把這個類新增到需要垂直居中的 flex item 上即可。

align-self-center

.align-self-center {
    align-self: center;
}
複製程式碼

3. 關於 Flexbox 的一些細節

3.1 flex 與 flex-wrap 屬性

flex 是 flex-shrink flex-grow flex-basis 的縮寫,初始值是 flex: 0 1 auto。 預設情況下 flex-shrink 為 1,也就是說當 flex item 元素的寬度大於 Flexbox 的寬度時,flex item 元素的寬度會自動等比縮小,以避免撐破父元素。如果不希望子元素縮放,有兩種情形。

  1. 設定 flex-shrink 為 0,父元素加上滾動條。
    1
.media {
    overflow-x: scroll;
    .box {
        flex-shirnk: 0;
    }
    
}
複製程式碼
  1. 設定父元素的 flex-wrap 為 wrap。
    2
.media {
    flex-wrap: wrap;
}
複製程式碼

3.2 當使用 text-overflow 需要注意的細節

CSS 的 text-overflow 可以用來控制超長溢位的文字內容的顯示方式,對於超出的內容可以是直接截斷、用省略號表示,或用自定義的字元替代。但是要想使該屬性生效,還需設定元素的 overflow,white-space 屬性。我們可以簡單寫一個 text-overflow 的類,專門用來控制文字的顯示。

.text-overflow {
    text-overflow: ellipsis;
    white-space: nowrap;
    overflow: hidden;
}
複製程式碼

white-space: no-wrap 表示文字不會換行,除非遇到 <br>。與 Media object 想結合時,可能會導致文字把 Flex 容器撐破的情形。

<h4>情形-1</h4>
<div class="media">
  <img class="media-left" src="../assets/logo.png" />
  <div class="media-body text-overflow">
    Vue.js (讀音 /vjuː/,類似於 view) 是一套構建使用者介面的漸進式框架。與其他重量級框架不同的是,Vue 採用自底向上增量開發的設計。
  </div>
  <div class="media-right"></div>
</div>
<h4>情形-2</h4>
<div class="media media3 media3-3">
  <img class="media-left" src="../assets/logo.png" />
  <div class="media-body">
    <p class="text-overflow">Vue.js (讀音 /vjuː/,類似於 view) 是一套構建使用者介面的漸進式框架。與其他重量級框架不同的是,Vue 採用自底向上增量開發的設計。</p>
  </div>
  <div class="media-right"></div>
</div>
複製程式碼

渲染效果如下:

最終預覽效果
我們發現 text-overflow 作用在 flex item 下的元素時,flex item 寬度被撐破,整個 Flexbox 排版也全亂掉。情形-2演示的場景很常見。為了排版的靈活性,一般情況下,並不會把 media-body 的寬度設定為一個固定值。一種最簡便的解決方案是設定 media-body 的 min-width 為 0。

.media-body {
    min-width: 0;
}
複製程式碼

當設定 min-width 為 0,media-body 的寬度就不會超過 Flexbox 的剩餘寬度。

4. 總結

flex 彈性盒子的屬性眾多,一篇文章詳解全部的屬性也不太可能。一種好的方法是結合常見的排版情形來學習 flexbox。 下面總結一下文中涉及到的 flex box 相關的屬性。

作用在 flex container 的屬性:

  1. justify-content
  2. align-items
  3. flex-wrap

作用在 flex item 上的屬性:

  1. flex (flex-shrink flex-grow flex-basis)
  2. align-self

本文只是結合自己的開發經驗總結出一些常見情形,文中未涉及到或者講解不詳細的地方,大家可以在 mdn 上查閱關於 flex 的資料

參考資料

相關文章