我就是要用CSS實現

發表於2016-01-15

寫在最前

我們都是前端工程師,無論你現在是頁面仔,還是Node服務開發者,抑或是全端大神,毋庸置疑的是,我們都是前端工程師,我們生來就對追求頁面的極致擁有敏銳的觸覺,無論是頁面實現方式的高大上、頁面的極致的效能還是頁面完美的展現,都是我們孜孜不倦的追求目標。即使這些在別人眼裡,只是跟其他的頁面一樣沒什麼不同,但我們卻能為其中那只有我們才知道的一抹別緻而竊喜。

而今天我要講的,就是我們最熟悉的老朋友,CSS。不講枯燥的語法,拋開js,讓我們一起來看業務中那別緻的純CSS實現,讓我們一起來追求那更好的頁面實現,希望我帶著你走完這段旅程後,你能收穫一些驚喜甚至靈感。

WHY,為什麼

“我有很多事要做誒,忙都忙不過來,難道我要在這CSS上面浪費很多時間?”

不,不,不,我們要做的事情,當然不會只是滿足技術的追求,而是會有實質的好處的!

我的觀點如下:

  1. CSS跟UI結合更加緊密;
  2. 用CSS來實現,能減少JS計算,減少樣式修改,減少重繪,提升渲染效率;
  3. 用CSS實現的,是一種模組化,更符合Web Components元件化思想,shadow DOM不就是致力於這麼做麼;
  4. 我們最愛的,逼格更高~

 

WHEN,何時

“我懂了,看起來是有那麼點意思,可是我什麼時候能用CSS來做大事啊?”

在我看來:

  1. 實現的物件是非互動性UI;
  2. 這麼做不會給你帶來過量的DOM。要知道最不能忍受的,就是臃腫的頁面;
  3. 這麼做能完美實現UI、能覆蓋所有場景,否則設計跟產品不服。

什麼是非互動性UI,就是不會在使用者觸發了某種行為時,嘩啦啦來個閃瞎眼的互動,嚇得使用者直接高潮,而是從頁面渲染後,就一直在那裡,那麼安靜,那麼美的女子,哦不,UI。

 

HOW,該怎麼做

“可是我還是不懂該如何做才能這麼有逼格”

我個人的見解:

  1. 佈局之美,理解透盒子模型,熟悉各種佈局,不要忘了這是我們的根本;
  2. 自適應之美,放心交給瀏覽器去做,我們要做的,是思考規則;
  3. Magic,新技術及小技巧,總能在某一剎那給你最需要的援助;
  4. 前人之鑑,坑王之王,你已經身經百戰了,還怕什麼。

這些就是我總結出你要用CSS來實現一個別人想不到的東西時,應該具有素質。最重要的還是思考,因為沒有一個東西是絕對最好的,我們總在前進。

EM{B0CE8533-03D7-62AC-27EF-6E2E9AABF024}-(10)

下面就以兩個手機QQ實際業務的例子,帶領大家感受一下CSS的魅力。

 

一、手Q吃喝玩樂  好友去哪兒九宮格圖

下圖是手Q吃喝玩樂  好友去哪兒九宮格圖的圖示:

九宮格

 

從上圖我們可以分析出如下需求:

  • 圖片大小自適應;
  • 圖片個數不同時,圖片按照指定方式排列;
  • 圖片相鄰處有1px空白間隙。

我們以最複雜的6圖佈局為例,一步一步來看如何以純CSS實現。

float佈局

最容易想到的,也是最簡單的方案,就是 float 佈局:

  • 圖片大小自適應:寬度百分比,高度使用 padding-top 百分比
  • 圖片個數不同時,圖片按照指定方式排列:使用 nth-child 偽類指定不同情況下的元素大小
  • 圖片相鄰處有1px空白間隙:使用 border-box + border模擬邊框

這裡父元素的高度未知,height使用百分比行不通,而padding的百分比值是依據父元素的寬度來計算的,我們可以使用padding-top撐開高度。

讓我們一瞅偽碼,猛擊我看demo

 

 

實際效果並不理想,如下圖:

1

可以看到 float 佈局的優點是DOM結構十分簡單,缺點是容易出現空白間隙錯位,優缺點都十分明顯,它更適用於js計算的版本。

flex佈局

還有誰?flex!flex佈局有以下重要特性

  • 可以將 flex 佈局下的元素展示在同一水平、垂直方向上;
  • 可以支援自動換行、換列(移動端-webkit-box暫不支援,好訊息是從iOS9.2、Android4.4開始都支援新flex了);
  • 可以指定 flex 佈局下的元素如何分配空間,可以讓元素自動佔滿父元素剩餘空間;
  • 可以指定 flex 佈局下的元素的展示方向,排列方式。

這裡面的子元素同一水平、垂直方向展示對我們很有幫助,它使我們更容易控制子元素的排列,而不會錯位。

使用 flex 佈局與 float 佈局不同的地方在於,移動端目前主要還是-webkit-box,因此圖片個數不同時,我們需要使用不同的html,組合出不同的塊。

flex 佈局上下劃分

來,我們快動手分塊吧!新解決方案出現導致的腎上腺素上升,使我們迫不及待使用了傳統css文件流自上而下的方式來劃分,我稱為上下劃分,如下圖:

上下劃分

上面一塊包含左側1個2/3的大塊,右側2個1/3的小塊,下面一塊則是3個1/3的小塊。

我們指定2/3的大塊寬度是66.6%,1/3的小塊寬度是33.3%(實際可以使用-webkit-box-flex來分配,這裡為了下面的計算方便)。

來看下實際效果,你也可以猛擊demo來檢視原始碼:

2

demo中我們看到中間那條豎空白間隙錯位了,為什麼?按照預期我們上面塊左側寬度66.6%,下面塊左側寬度33.3% + 33.3%,兩個寬度應該相等才對。

然而我們忽略了flex一個重要特性,子元素會自動佔滿父元素剩餘空間,這時子元素寬度計算受flex控制,下面塊的3個子元素寬度計算並非一定是相等的,會有些許差異,此時66.6% != 33.3% + 33.3%

怎麼破!別急,我們剛剛只是受到了腎上激素的影響,讓我們冷靜下來重新思考如何劃分。

flex 佈局左右劃分

問題在於豎間隙涉及到的左右側寬度計算不穩定,既然如此,我們可以考慮依據豎間隙左右劃分,排除不穩定因素,如下圖:

左右劃分

這樣就解決了豎間隙錯位問題,但我們依然有所擔心,中間的橫間隙會錯位嗎?我們來算一下。

整體父元素寬度確定,為W;

整體父元素高度由子元素撐開,不確定;

左側大塊高度:左側flex父元素寬度(W * 66.6%) * 100% = W * 66.6%;

左側小塊高度:左側flex父元素寬度( W * 66.6%) * 50% = W * 33.3%;

右側小塊高度:右側flex父元素寬度( W * 33.3%) * 100% = W * 33.3%。

依然是66.6%與33.3% + 33.3%的等式,但這次高度計算會受 flex 影響嗎?

不會,因為此時整體父元素的高度是不確定的,是由子元素內容撐開的,flex的高度也是由子元素來撐開的。

最終 66.6% === 33.3% + 33.3%

我們來看下偽碼,猛擊我看demo

 

 

實際效果:

3

QQ圖片20160113000812

 

二、手Q家校群先鋒教師進度條

下圖是手Q家校群先鋒教師進度條設計稿:

先鋒教師進度條

圖中的12345便是主角進度條。分析需求如下:

  • 線的長度不固定
  • 點平均地分佈在一條線上
  • 點的個數不固定,可能會改變
  • 啟用的點之間線的顏色是綠色的

讓我們看下如何用純CSS實現。

絕對定位大法

我們看了第一眼,便想起了最受青睞的萬金油 absoulte,方案圖如下:

絕對定位大法

  • 將點、線分離,灰色背景線使用父元素的after實現;
  • 點使用絕對定位,left百分比值定位;
  • 綠色線條使用父元素before實現,絕對定位,寬度百分比值。

不消一會兒我們就做出來了,但再多看一眼覺得十分不妥,點和線百分比值都要手動指定,不便修改點的數量,且過多的絕對定位不優雅。

這並不是我們想要的CSS實現。

百分比寬度切分

於是我們迴歸本源,遵從CSS世界的規則來,將點線合起來看,每個子元素包含自己的點線,從左至右排列,並使用自適應佈局的方式,子元素寬度為百分比,如下圖的方案:

百分比寬度劃分

  • 灰色背景線依舊使用父元素的after實現;
  • 每個子元素寬度一致,為平均下來的百分比值,如25%;
  • 點絕對定位在子元素右側;
  • 綠色線條在子元素內實現。

然而我們發現這麼做不靈,在普通盒子模型裡,子元素寬度總和無法溢位父元素(除了flex),在這裡總寬度是4個帶線子元素(百分比)+1個點寬度(固定),實際25%的劃分展示與理想不符。

此外,最左側只有點,沒有線條,點的寬度固定,線條寬度不定,css無法計算(忘掉表示式吧),無法隱藏線條,fail!

百分比寬度切分進化版

攪屎棍就是最左側那固定的點,難道就不能把最左邊那該死的點從我們的百分比團隊裡排除掉嗎?如下圖:

百分比寬度劃分進化版

當然可以!我們只需父元素騰出這個子元素寬度出來,不算在其餘子元素寬度百分比計算內。

騰出空間方式:父元素 margin-left 出空間,子元素負 margin-left 移回原位。

此時父元素給子元素的內容計算寬度就是width – margin-left,除首個子元素外,其餘每個子元素寬度一致,為平均下來的百分比值。

實際效果,由於原始碼較長,請猛擊demo看原始碼:

4

完(美),話還沒說完,產品就找來要改點的數量。

圖片6

我們一看寬度是百分比設死的,這樣在點的數量修改時,我們還是要改css,完。

圖片7

百分比寬度劃分究極版

來,心中默唸3遍“要優雅不要汙”,靈光一閃,flex大法好!

flex重要特性之一,可以指定 flex 佈局下的元素如何分配空間,我們將點線元素寬度改為-webkit-box-flex:1,此時子元素就自動平均分了父元素寬度。

實際效果,猛擊demo

5

QQ圖片20160113000812

 

旅程還在繼續

本文講了筆者對前端頁面開發中儘量思考多用CSS實現的一些見解,主觀性強烈,歡迎大家的一起來探討。

通過業務實踐中的兩個例子帶領大家走了一回CSS實現旅程,還望各位觀眾姥爺過了癮,如大家有一些更好的實踐十分歡迎與我分享。

我跟你的旅程就在此結束了,但你的旅程依然在繼續,若本文能給你帶來啟發,我就最開心不過了。

最後,flex大法好!

 

行文匆忙,如大家發現錯誤歡迎指正。

感謝你的閱讀!

 

相關文章