半熟前端

軟體工程師 / 台灣人 / 在前端的路上一邊探索其他領域的可能性

本部落格使用 Gatsby 製作

本部落格有使用 Google Analytic 及 Cookie

前端

高度相同的排版解決方案

在前端的頁面中,我們經常會碰到需要相同高度的排版。最直覺的方法就是將容器裡的所有元素設為 float 或是 inline-block。

float 及 inline-block

如果是使用 float 排版,不但要先撐開父元素容器(clearfix),還要針對子元素設定 margin。 所以一旦內容太多,或是高度不足就會跑版。

而且,這樣的排版最大的缺陷就是,必須設定高度

那,如果不設置高度呢? 就算設定了 min-height 也一樣,當內容超出高度時,就必定會面臨 overflow 的危機。

後來決定直接用 css media query 在不同的螢幕寬度下分別給予不同的高度。 雖然解法比較麻煩,也比較醜一點,但的確解決了寬度過窄時會跑版的問題。

這個問題後來一直深埋在心中,直到最近發現了 flex 的奧秘。

排版遇到困難,先想想 flex

人生遇到挫折的時候,想想 flex,這個彈性盒子常常會救你一命。 flex 已經支援大部分的主流瀏覽器,而且真的很好用!

將 display 設置為 flex 的時候,如果子元素沒有設定高度,則子元素的高度會是其中最高的那個。

一行屬性就解決了我朝思暮想的問題,真是優雅的 flex

但除此之外,我們還需要對排版做一些調整。 flex 預設如果沒有設置 flex-wrap 屬性的話,就會以單行顯示的方式來撐開父容器。 因此我們可以再加上一行。

css
.wrap {
flex-wrap: wrap;
}

好了,高度相同的 responsive 排版,不宣告 height 就此完成。大概的 css 會長得像這樣:

css
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
.card {
height: auto;
width: 30%;
border: 1px solid #aaa;
}

不支援 flex 的瀏覽器怎麼辦?

首先 flex 已經支援大部分的主流瀏覽器了,不要用支援度這種藉口來忽視這麼好用的 flex。 但如果瀏覽器真的不支援,可以用 js 的方式來做排版。主要的原理是不設定高度,偵測 container 裡面的所有元素,並且找出高度最高的,並將此高度套用到每個元素中。

寫了一個很基本的範例代碼:

js
var cards = document.querySelectorAll(".card")
function getMaxinumHeight(elements) {
var nums = []
elements.forEach(function(value) {
nums.push(value.offsetHeight)
})
return nums.sort(function(a, b) {
return a < b
})[0]
}
var maxHeight = getMaxinumHeight(cards)
cards.forEach(value => {
value.style.height = maxHeight + "px"
})

Table is new sexy

雖然古老的 table 排版已經被唾棄,不過像是等高這種場景,如果不幸無法使用 flex 時,可以利用 table 的特性來達成等高排版。

要完成 table 排版,可以使用 display: table, display:table-row, display: table-cell,來完成。

display: table 等同於 <table>display: table-row 等同於 <tr>display: table-cell 等同於 <td>

不過,雖然能夠達到等高的效果,但 HTML 的 markup 變得更複雜了。而且 table 在使用上仍然有一些限制,像是 margin 沒辦法在 table 裡頭生效等等,這些在實作 mockup 時都是很大的阻礙。所以,如果能夠用 flex 來做的話,就盡量使用 flex 吧!

延伸閱讀

Flexbox responsive equal height

如果覺得這篇文章對你有幫助的話,可以考慮到下面的連結請我喝一杯 ☕️
可以讓我平凡的一天變得閃閃發光 ✨

Buy me a coffee