一、一切從line-height行高說起
想想看,你CSS構建頁面的時候,預設的字型大小和行高分別是多少?
下面是我統計的一些資料:
- 新浪微博:
12px/1.5
- 騰訊微博:
12px/1.75
- 淘寶網/天貓/騰訊微雲:
12px/1.5
- 京東:
12px/150%
計算下來,基本行高要麼是18畫素,要麼是21畫素~
我想,大多數小夥伴應該沒關注過這方面的細節,基本行高大致就可以,取1.5
方便計算,1.75
呢似乎也無傷大雅。
當下的網頁早已告別當初就只能瀏覽資訊的那種狀態,頁面結構更加複雜,大段描述文字的情況只佔少數,因此,行高的角色有點從閱讀體驗層面轉換為更方便的計算或者其他什麼角色。
這裡的“其他什麼角色”看似平淡無奇的一句話,其實才是本文的主角。在本文,行高擔任了網頁垂直格柵基準的角色!
我們以前可能聽過網頁格柵佈局,老實講,我對水平格柵一點興趣也沒有,幾百篇CSS文章我也從來沒有介紹過,因為跟自己的佈局理念不符;但是,我今天倒是要提一提垂直格柵!
頁面內容往往是自上而下瀑布式的呈現,內容千變萬化,元素的高度也是變幻莫測,因此對於垂直方向,所謂格柵,幾乎是無稽之談。確實是這樣,但是,區域性的格柵有時候會讓我們的頁面變得更加規範,以及可以讓我們的工作更加輕鬆。
而這一切,就要從行高說起。我們以前寫頁面,都是設定字型大小以及行高值,確定單行文字所佔據的高度內容;而我們這裡,則逆向思維,我們希望頁面基本文字所佔據的高度是20
畫素,則我們的行高應該是?
現在是大屏時代,假設我們的預設字號大小是14
畫素,我們計算下:20/14≈1.4285714285714286
,四捨五入的結果,於是得到:
1 2 3 4 |
body { line-height: 1.42857; font-size: 14px; } |
不好意思,給大家下套子了,注意了,在CSS中,行高計算的時候,一定不要向下四捨五入,而要向上。類似上面的程式碼,雖然14*1.42857
近乎就是20畫素,但是,不好意思,最後還是以19畫素的高度呈現,在Chrome瀏覽器下就是如此!
因此,實際的設定應該是:
1 2 3 4 |
body { line-height: 1.42858; font-size: 14px; } |
於是,我們就得到了一個20畫素為基準的網頁佈局環境了,此時,普通一行文字的高度就是20畫素,那又有什麼好處呢?
單一來看,20畫素的高度單元和21畫素似乎沒什麼差別,但是,如果放在一個完整的體系裡面,價值就能很好地體現了!
二、20畫素為基準的20*20畫素的小圖示策略
基本上每一個網站都離不開小圖示,國際通用的圖形語言,對於一個網站而言,無論是體驗還是辨識度都是必不可缺的。
目前而言,絕大多數網站還是處於12畫素字型時代,設計師設計的圖示都是按照16*16畫素規格設計的偏多;不太專業的設計師可能會14~20畫素之間搖擺。
反正不管怎樣,最後(加上sprite工具盛行)我們圖形在網頁中的尺寸基本上就是16px*16px
:
1 2 3 4 |
.icon-hi { display: inline-block; width: 16px; height: 16px; } |
當然,17px*18px
也是很常見的:
1 2 3 4 |
.icon-hi { display: inline-block; width: 17px; height: 18px; } |
這種一小圖示真實尺寸構建CSS程式碼的方式有3個比較大的問題:
- 與後面文字的對齊
- 點選區域大小
- 重複冗餘的CSS程式碼
1. 與後面文字的對齊
由於vertical-align
屬性的相容性,以及vertical-align:middle
並不是嚴格意義的垂直居中,因此,小圖示+文字的對齊,基本上都要針對不同瀏覽器加個hack補丁;在加上,如果你的圖示尺寸一會兒16畫素,一會兒18畫素,顯然,沒法通過全域性一個設定使得整站的小圖示和文字都對齊良好!
例如,騰訊微博這裡,圖示就是16畫素尺寸,然後,一些五花八門的處理:
很多補丁,很多CSS處理,裡面圖示使用了absolute絕對定位,這倒是處理相容挺不錯的方法,但是,顯然不具有普遍適用性。
2. 點選區域大小
有時候,我們的小圖示直接就是點選按鈕,此時,如果你的尺寸就是16畫素*16畫素,會不會點不準的概率就上升了,如果圖示是20px*20px呢?
3. 重複冗餘的CSS程式碼
當下類似grunt-spritesmith的小圖示合併工具基本成了前端團隊的標配,而根據我的觀察,基本上,大家都是設計師給的圖示直接扔到資料夾裡面進行合併,於是,產出的程式碼基本上就是width
/height
/background-position
的模式,然而,可能裡面70%寬高都是16畫素,20%是18畫素,還有10%是其他小尺寸,也就是,其實很多CSS程式碼是可以合併的,然而,都浪費了。
如下生成less程式碼截圖(源自真實專案):
以上這些問題實際上一個對策就可以搞定,就是所有圖示統一按照20px*20px的標準處理!
你想啊,我們網頁文字基礎高度是20畫素,圖示也是20畫素高,天然對齊,問題1解決;20*20的點選區域對吧,顯然比16*16要大,問題2解決;所有圖示都是20*20的尺寸範圍內,所有width
/height
都可以合併,大大減少CSS程式碼,問題3也搞定了!
如下圖CSS生成模板示意:
————-低調的分隔線————-
然而,實際上的處理要比上面說的複雜和深奧的多!
圖示和文字天然對齊
按照我們直觀的認知,兩個元素都是20畫素高,都在自己的垂直範圍內居中,那這兩個元素應該是在一個水平線上的。實際上真的是這樣嗎?是的,但是,注意這裡的但是,是有條件限制的!
在“CSS深入理解vertical-align和line-height的基友關係”一文中,其中就已經提及過:
The baseline of an ‘inline-block’ is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its ‘overflow’ property has a computed value other than ‘visible’, in which case the baseline is the bottom margin edge.
中文直譯就是:
‘inline-block’的基線是正常流中最後一個line box的基線, 除非,這個line box裡面既沒有line boxes或者本身’overflow’屬性的計算值而不是’visible’, 這種情況下基線是margin底邊緣。
翻譯成白話就是:
如果inline-block水平元素’overflow’不是’visible’,或者裡面沒有內聯元素(圖片、文字之類),則整個元素的基線就是自身的下邊緣;否則,基線就是裡面最後一行圖文元素的基線(這是我們需要的)。
有點不太理解?沒關係,不是本文的重點。你只要知道,我們要想20畫素高的圖示和20畫素高的文字天然對齊顯示,需要滿足這兩個條件:
overflow
屬性值除了visible
都不行;- 裡面需要有不加修飾的文字內容;
所以,下面兩種情況都是淘汰的!
1 2 3 4 5 6 |
.icon { display: inline-block; width: 20px; height: 20px; background: ... overflow: hidden; } |
1 2 3 4 5 6 7 |
<i class="icon"></i> .icon { display: inline-block; width: 20px; height: 20px; background: ... } |
第一種情況是overflow:hidden
拖後腿了;第二種情況是<i>
標籤裡面是空大屁,基線還是元素底邊緣而不是裡面的文字(如果有)。
因此,要想實現小圖示天然對齊,我們不能有overflow:hidden
同時HTML標籤內部有文字內容,我靠,好多限制,貌似很煩啊,然而,經過本人的實踐,是可以有CSS程式碼段滿足各種場景的對齊效果的,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.icon { display: inline-block; width:20px; height:20px; background: ...; white-space:nowrap; letter-spacing: -1em; text-indent: -99em; color: transparent; /* IE7 */ *text-indent: 0; *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '\3000'); } .icon:before { /* 偽元素插入空格文字 */ content: '\3000'; } |
您可以狠狠地點選這裡:小圖示文字對齊的終極解決方案demo
結果,無論是空標籤HTML,還是內建可訪問性提示文字的HTML,都是對齊效果棒棒噠!
1 2 3 |
<i class="icon"></i> <a href="javascript:" class="icon">刪除</a> |
而且,就算文字的字號大小變化,例如14px
→16px
圖示和文字也是對齊良好的,因為,對齊的本質是圖示元素裡面的文字和後面的文字對齊,文字和文字對齊,自然是天然對齊的,千古難題就這麼有了解決方案,以前的CSS hack啊,什麼vertical-align
控制,還有margin
負值偏移都是浮雲了!
圖示20*20尺寸擴充套件grunt工具
設計師設計的圖示都是16px~20px不等,CSS程式碼都是Grunt工具生成的,我們很難簡單控制讓所有圖示都是20*20的區域大小。除非,我們對所有的小圖示在匯出的時候,手動擴充套件畫布到20px*20px。
親,什麼年代了,又不是搞藝術品,手工勞作年代過去了,直接上工具。
我基於GM搞了個20畫素以下小圖示自動擴充套件為20畫素大小圖片的Grunt工具:https://github.com/zhangxinxu/canvasExpand
精力有限,這個小專案還沒細整就扔上去了,可以看到,很多模板生成的文字我還沒來得及改。
window使用者記得要安裝ImageMagick.exe,安裝時候記得勾上那個全域性變數什麼東西的。
如果有什麼問題,歡迎……不要來打擾我,忙,自己想辦法,麼麼噠~~
圖示的重心畫素級處理
有些圖示,雖然設計師給的尺寸是標準的,沒有多餘畫素,但是,可能圖示本身的形狀並不是對稱的,尤其上下,這就會導致圖示的重心會有些偏上或者偏下,導致和後面的文字呈現的時候,雖然真實尺寸是對齊的,但是視覺感覺卻是不在一條線上。如果要求很高,可以讓設計師或UI工程師自己微調下,一般1畫素就夠了,當然,是調整圖片,例如,重心低的,下面多1畫素高度的透明區域。
三、40畫素高度的UI元件體系
前面提到過,20畫素的基準行高要在體系中才能大放異彩,而這個體系的另一個非常重要的成員就是頁面的基本UI元件們!
所有的按鈕均是40畫素高度,所有的輸入框都是40畫素高度,所有的下拉框、時間選擇框都是40畫素高度;
上圖截自“基於原生HTML的UI元件開發”一文那個展示前端分離的例子:QQ公眾平臺UI元件下的前端分離demo
由於我們的基準文字高度是20畫素,因此,左邊文字距離頂部的間距,就是標準的10畫素!
這就使得我們網頁中無論是大模組之間的間距,還是小的文字和空間之間的間距;無論是水平的間距還是垂直的間距,全部都是標準的5畫素的倍數。從而讓我們所有的大小模組的實際高度都是10的倍數(padding-top + line-height*行數 + padding-bottom)。
換句話說,我們以20畫素為基準進行佈局和UI元件設計,使得我們的網頁間距標準化了,無形之中會讓我們頁面的排版更專業,同時也讓zxx.lib.css的利用率提升了。
如果我們進一步深究按鈕或者輸入框的實現細節,你會發現,其CSS實現本身就是按照20畫素為基準的策略進行實現的:
//zxx: 擦,一看程式碼,發現按鈕直接行高控制的,失策失策,我回去就調整下,這其實是有問題的,適用性大了折扣,因為沒有遇到按鈕中有圖示的設計情境,所以沒有暴露出來。更好實現應該和上面輸入框一行,20畫素行高,使用padding實現最終的40畫素高度。
四、結束語
看似是簡單的要求以20畫素為基準,實際上根植於體系中並有一套完整的解決方案。
不過,跳出內容本身,換個角度講,本文的內容其實挺無聊的。
人家淘寶天貓就是基礎高度18畫素,不是這裡推薦的20畫素,但照樣年銷售額3萬億,照樣上市,照樣造就了一大批土豪。
所以,大家大可不必過分在意一點點的CSS細節,CSS對於產品的商業價值有,但是到了一定階段以後,實際上就有限,或者說很難直觀的體現,或者說價效比就不高了。今天還有小夥伴問我,absolute
絕對定位元素display:none
和visiibility:hidden
兩個隱藏的渲染效能差異,這個問題的商業價值比本文內容還要小1萬倍,以現在瀏覽器的渲染效能以及我們實際的開發需求,就算有差異,有價值嗎,肯定沒有!
大環境如此浮躁,你會發現,自己遇到的困境並不是技術成長遇到了瓶頸,而是根據不需要你這方面進一步的技術成長,來,乾點收益更明顯的事情!
我想,很多前輩技術部落格斷掉了,怕也是人在職場,身不由己!
我能不能走出一條不一樣的路呢?