代碼優雅性反映出你的思維高度

身為一名前端,你是否還在為各種兼容性焦頭爛額?多頁面場景,是否會產生很多相互覆蓋的樣式,讓你為了覆蓋別人的樣式而疲於奔命?對於前端初學者,你是否總是遇到各種各樣奇葩的布局問題,上網一搜一堆hasLayout、BFC裝逼指數滿分卻對你毫無幫助的辭彙?本文將告訴你,如何通過優雅的html和css代碼,最大程度的規避掉紛繁複雜的前端渲染問題,讓你感受到代碼優雅的重要性。

一、 選擇器的藝術

選擇器是學習CSS的第一課,屬於非常基礎的知識,但即便是工作多年的老前端,也不一定能玩通透,依然有很大一部分人對於信手拈來的選擇器隨意使用,不瞻前,不顧後,不做全局考慮,這就會引發一系列問題。

問題1:「這公共樣式誰寫的?TMD把我樣式覆蓋了!」

上述責問你肯定沒少聽過吧?是的,css選擇器的全局性就是容易造成全局環境下的樣式覆蓋問題,尤其是一些公共樣式的書寫,如果肆意書寫,很可能就會影響到具體頁面內的樣式。

解決方案:

step1. 基本樣式(reset.css) 必須業務非相關,如color值,字體大小等,不允許定義。

step2. 全局樣式(g.css)儘可能採用單層類選擇器,在不十分確定的情況下,盡量不使用標籤選擇器。如下圖,若是直接對標籤p定義了顏色,那很可能會直接影響所有引用該全局樣式的頁面。

step3. 以組件,通用模塊等粒度對樣式進行抽離封裝,並以統一命名規範進行命名,從而變相對樣式進行虛擬的命名空間約束,達到 抵消css全局性 的功效。這裡推薦採用BEM等命名方式。如圖:

無法抽離成組件和模塊的樣式,也可以用類似的方式,在具體頁面內以「布局區域」來做粒度,對樣式進行約束。

問題2:「我靠,這樣式權重太大了,不好覆蓋啊!」 「誰TM寫的important,坑爹啊!」

嗯。。。看語氣就知道了,每次遇到這種問題是很心煩的,css權重問題處理的不好,就會讓前端疲於奔命的應付在你覆蓋我來我覆蓋你的道路上。。。尤其是遇到這種選擇器,真的想死:(截圖來自百度糯米首頁,真不怪我黑友商,我是隨意找的。。。)

解決方案:

step1. 參考問題1,對css進行命名約束,對於一個組件ui-dialog,全局只能有一個;對於某頁面內sec-banner,此頁面內也只應該存在唯一一個叫做sec-banner的區域,以此類推。這樣,我們就已經把某元素限定在了一個很小的範圍內,在此範圍內,你就可以肆無忌憚的命名而不用擔心命名重複了。舉例,用上圖的反例來舉吧,這個logo-item其實是位於一個叫做「精選品牌」的樓層里,那麼我們是不是可以先把這個區域定為「selected-brand」,而這個區域內,logo-item這個類名基本就完全可以做到不衝突,唯一性,那麼整個選擇器就會是「.selected-brand .logo-item」,當然了,要按我的辭彙量,我才不會叫什麼logo-item,叫brand不是更好?因為如果叫brand,那這個div里如果還有圖片啊,文字啊之類的,就可以採用BEM方式進行約束:brand__img,brand__title,而整體選擇器權重就只有兩層class,萬一有皮膚定製的需求,覆蓋起來也是分分鐘的事兒對吧。

咱提煉一個原則:在確保唯一性的前提下,儘可能縮減DOM層級和選擇器層級。

step2. 不要輕易使用 !important 和 * 。!important的噁心之處我就不多說了吧,至於*的使用,確實不會增加太多權重,但是!*會讓你的樣式定義遍布全球每一個角落!這種一棍子打死的選擇器使用方式,正常人干不出這種事兒!當然了,存在即合理,並不是說哪兒都不能用,我說的是不要輕易用,除非你很清楚你在幹嘛。

問題3:「咦?這樣式咋被劃掉了?被定義了兩遍?」

這次我拿自己的項目開涮,如圖:

明顯可以看出來,a標籤其實已經在全局範圍內定義了一個hover顏色,但是在具體業務頁面里又定義了一次,當然了,我可以解釋其實這裡是歷史遺留,所以呢?歷史遺留問題不應該清理一下?沒毛病。

解決方案:

在寫樣式的時候,要充分利用樣式繼承(當然了前提是你能hold住這個樣式而不被反覆蓋),避免重複定義樣式。繼承用得好,是可以減少好多工作量的喔~

上面幾個問題,只是拋磚引玉,實際生產中,還有很多不優雅的選擇器使用方式。還是那句話,選擇器很簡單,但是要用好,真的不簡單。技術不複雜,但需要融入很多的整體思考,大局觀。

二、一些可以更優雅的場景

有很多場景,是我們經常會遇到的,這些場景總會給我們製造一些小麻煩,小困擾,每次我們都會直接針對性的hack掉就完了,實際上,只要我們多思考一點,就可以做得更優雅一些,形成一套可以隨時復用的解決方案,就不用每次遇到都hack了。

場景1:子元素margin沒有撐開父容器,但影響到相鄰元素,從而影響距離計算。

這就是著名的BFC邊距摺疊問題,具體原理我就不闡述了,各位自行查資料。為什麼要把這個問題拿出來說?因為在視覺還原要求較高(像素級還原)的團隊,兩個元素之間的距離是需要精確計算的。舉例如下圖,父容器a其實沒有margin,但子元素c的邊距使得a與b之間產生了間距,這並不是我們預期的,

我們希望看到的標準輸出應該如下圖。

解決方案:

原理上就是要解決BFC摺疊問題,(點這裡有原理解釋l),這裡有詳細解釋,有興趣的同學自行閱讀,一般來講,我們可以用這兩種方法解決,

1. 父元素添加overflow:hidden,但前提是該容器內沒有需要「伸出容器」的內容,比如小箭頭什麼的。

2. 給父元素增加偽元素:after,並設置其display:table。其實就是我們平時說的「清除浮動clearfix」,當然原理並不是什麼清除浮動,而是在相鄰父子元素之間增加一個看不見的間隙,強制性阻止margin摺疊。

場景2:<img>標籤總會多那麼1px空白。

解決方案:

這個經典問題的答案也是網上一搜一大堆,原理是img標籤的特殊性(表現為塊狀元素的行內元素)導致其做垂直對齊時候會默認做基線對齊,而不是底部對齊,從而留出一些空白。那照這個原理來講,我們人為讓img做底部對齊不就可以了?是的,設置verticle-align:bottom就能解決。

但是,我在這裡想分享另一個思路,img標籤,最好使用一個容器存放!好處如下:

1. 方便添加跳轉鏈接。是的,大部分有圖的地方一定會有個鏈接或者交互動作。

2. 方便根據需求隨時調整寬高。將圖片100%撐滿容器,調整容器寬高即可改變圖片寬高。

3. 方便根據運營需求,隨時切換為動態可配置圖片。

4. 容器可以做佔位,即使圖片掛掉,布局也不會錯亂,還可以設置默認背景圖,優雅容災。

嗯,將圖片放入容器後,設置display:block即可解決1px空白問題。更重要的是,我們不僅僅解決了1個問題,還擁有了一套更加優雅的,可以應對各種複雜問題的圖片解決方案,豈不更好?

場景3:彈窗垂直居中。(泛指需要居中在整個視窗中間的絕對定位元素)

解決方案:

移動端強烈推薦使用translate(-50%,-50%)搞定,方便簡單無副作用。

PC端就比較蛋疼一點,若是元素寬高固定,那傳統做法使用負值margin就可以搞定,但寬高不固定呢?給大家推薦一個非常好用的方法,給遮罩層加一個:afrer並設置其高度100%撐滿容器,但由於其寬度為0所以其實不佔位,然後將需要垂直居中的元素都設置為dislpay:inline-block從而將問題轉換為行內元素如何垂直居中問題,如圖:

別跟我說ie6怎麼辦,這是2017年了,你老闆還要你支持ie6的話,你可以甩他一臉ie6!

-----------------------------此處需要出現一條分割線------------------------------

結語:

這次給大家分享的意義,其實不在於說你能學到幾個解決實際問題的方法和技巧,更重要的是學到一種思維方式,即培養一種全局思維,跳出執行層面的局限性,更多的從整體收益來看待問題

代碼行中悟真知,優雅的解決問題,會讓你的思維高度提升一大個層級!


推薦閱讀:

從Vue.js源碼角度再看數據綁定
為什麼 ++[[]][+[]]+[+[]] = 10?
好的 CSS 命名規範可以節約 Debug 時間
Effective前端(2)優化html標籤

TAG:前端开发 | HTMLCSS | 重构 |