使用 Sass mixin 實現 CSS 的居中效果

發表於2015-08-15

雖然使用 CSS 建立居中效果需要耍一些花招,特別是垂直居中效果,但我認為由此生出的詆譭,對於 CSS 則是不公平的。實際上我們有太多的方式使用 CSS 建立居中效果了,而且作為一名前端開發者,你真的有必要對其中的原理了解一二。

寫作本文的目的不是為了向各位解釋這些方法的工作原理,而是介紹將這些方法編寫為 Sass mixin 的方式,繼而將它們複用到各類專案中。如果你還不熟悉使用 CSS 建立居中效果的方法,我建議你仔細閱讀以下這篇文章:Centering In CSS: A Complete Guide

總體概述

本文將會專注於解決子元素居中於父類容器的問題,就實踐經驗來說,這也是最常使用到的居中效果。當你請教別人 CSS 中和居中效果相關的問題時,他們往往會反問你:你知道元素具體的寬高嗎?之所以會有這樣的反問,是因為如果知道元素的寬高,那麼最好的解決方案就是使用 CSS transform 屬性。雖然該屬性在瀏覽器中的支援度稍低,但卻有著高度靈活的特性;如果因為瀏覽器相容性令你不能使用 CSS transform 屬性,或者也不知道元素的寬高,那麼實現居中效果的最簡單方法就是使用負向 margin。

我們今天要建立的 Sass mixin 就是基於上述的方法:將元素的左上角絕對定位到容器的中心位置,然後為 mixin 新增兩個可選引數,分別代表元素的寬高,如果傳遞了引數,那麼就使用負向 margin 的方法實現居中;如果沒有傳遞引數,就使用 CSS transform 的方法。

當我們的 Sass mixin 建立成功後,基本的使用方式如下所示:

上述 Sass 程式碼經過編譯之後,輸出結果如下:

還不錯,就是看起來有點囉嗦,不過鑑於是用來做 demo 的,也不必太過強求了。

建立 mixin

思路屢清楚了,下面開工!根據上面的程式碼片段,我們已經知道了這個 mixin 的主要特徵:接收兩個可選的引數,用來表示元素的寬高($width 和 $height)。

然後,由分析知,要實現居中必須讓元素絕對定位:

在這裡讓我們暫停一下,深入分析後續邏輯的層次:

width height solution
null null translate
defined defined margin
defined null margin-left + translateY
null defined margin-right + translateX

秀程式碼:

通過上面的程式碼,我們已經搭好了 mixin 的骨架,只需要再新增上具體的邏輯程式碼即可:

注意!上面程式碼中的 #{0 0} 實際上一種容錯措施,如果直接使用 0 0 的話,Sass 解析器會嘗試進行數值運算(在這裡會自動進行 0 -($height / 2) 的數學運算),進而導致我們得到 margin: mt 0 ml; 而不是想要得到的 margin: mt 0 0 ml;

深入淺出

基本的功能實現後,我們還可以新增更多的特性,比如新增 @support 來檢查瀏覽器對 CSS transform 的支援度,進而可以根據 CSS transform 的支援度輸出相應的條件樣式。此外,我們還可以更嚴謹地去測試出入的引數是否是有效數值……

使用 Flexbox

看到 Flexbox 這個詞是不是就很興奮啊,少年!確實,使用 Flexbox 確實是最簡單的方式,它和前面方法主要的差別在於,使用 Flexbox 需要為父容器設定相關樣式,而使用前面的方法則主要是為子元素設定相關樣式(當然,父容器需要被設定為除 static 之外的任意 position)。

使用 Flexbox 實現子元素的居中效果,只需三行程式碼:

由於 Flexbox 還是比較新的屬性,那麼新增上相關的瀏覽器字首的話,會讓它擁有更廣泛的相容性。

正如你料想的那樣,就這麼簡單我們就實現了:

總結

我們就想要一個簡短的 mixin 讓元素在父容器中居中,我們做到了,而且做的更好。它不僅僅簡單易用無副作用,而且提供了良好的開發介面。

相關文章