手機淘寶的flexible設計與實現
看到小黑的文章 關於webapp中的文字單位的一些搗騰 感覺很贊。尤其是,他提到了手機淘寶的meta,所以覺得要講講我們這方面的一些實踐。
手機淘寶從2014年中開始,全面推行flexible設計。什麼叫flexible呢?其實flexible就是responsive的低端形態和基礎。對我們來說,最直觀的感受就是,在超寬螢幕上,網頁顯示不會兩邊留白。以前pc時代大家經常講的流體佈局,其實就是一種flexible design。只不過,流體的表述角度是實現,flexible的表述角度是結果,為了跟高大上的responsive保持一致,我們這裡使用了flexible這個說法。
討論方案之前,需要先了解三個關鍵概念:
- 單位英寸畫素數(Pixel Per Inch,PPI):現實世界的一英寸內畫素數,決定了螢幕的顯示質量
- 裝置畫素比率(Device Pixel Ratio,DPR):物理畫素與邏輯畫素(px)的對應關係
- 解析度(Resolution):螢幕區域的寬高所佔畫素數
當我們決定不同螢幕的字型和尺寸的單位時,螢幕的這幾個引數非常重要。
場景1——Resolution適配
一張banner圖片,當你面對不同的螢幕時你希望它的行為是怎樣的?
在這個場景中,我們主要需要面對的是解析度適配問題,考慮到多數網頁都是縱向滾動的,在不同的螢幕尺寸下,banner的行為應該是總是鋪滿螢幕寬度以及總是保持寬高比。
最自然的思路是使用百分比寬度,但是假如使用百分比寬度,即width:100%,我們又有兩種思路來實現固定寬高比:一是利用img標籤的特性,只設寬度等圖片載入完,這種方法會導致大量的重排,並且非固定高度會導致懶載入等功能難以實現,所以果斷放棄;二是使用before偽元素的margin撐開高度,這種方法是比較乾淨的純css實現,但是不具備任何複用性而且要求特定html結構,所以也只好放棄了。
於是,剩下最合適的辦法是使用其它相對單位,本來最合適的單位是vw,它的含義是視口寬度,但是這個單位存在嚴重的相容問題,所以也只好放棄。
最後我們只好配合js來做,硬算也是一條路,但是同樣不具備任何可複用性,最終我們選擇了rem,我們用js給html設定一個跟螢幕寬度成正比的font-size,然後把元素寬高都用rem作為單位。
這是我們目前的線上方案了,它是一個近乎Hack的用法,已知的問題包括:
- 某些Android機型會丟掉rem小數部分
- 佔用了rem單位
- 不是純css方案
場景2——PPI適配
一段文字,當你面對不同的螢幕時你希望它的行為是怎樣的?
顯然,我們在iPhone3G和iPhone4的Retina屏下面,希望看到的文字尺寸是相同的,也就是說,我們不希望文字在Retina屏尺寸變小,此外,我們在大屏手機上,希望看到更多文字,以及,現在絕大多數的字型檔案,是自帶一些點陣尺寸的,通常是16px和24px,所以我們不希望出現13px、15px這樣的奇葩尺寸。
這樣的特徵決定了,場景1中的rem方案,不適合用到段落文字上。所以段落文字應該使用px作為單位,考慮到Retina,我們利用media query來指定不同的字型,考慮到dpr判定的相容性,我們用寬度替換來代替:
.a {
font-size:12px
}
@media (min-width: 401px){
.a {
font-size:24px
}
}
另一種場景,一些標題性文字,希望隨著螢幕寬而增大的,我們可以仍然使用rem作為單位。超過35px(個人直觀感受)的文字,已經不用太考慮點陣資訊了,靠字型的向量資訊也能渲染的很好。
場景3——DPR匹配
一個區塊,設計稿上有1畫素邊框,當你面對不同的螢幕時你希望它的行為是怎樣的?
這個場景,需求很簡單,設計師希望在任何螢幕上這條線都是1物理畫素。
好吧,當然這個問題的答案不是寫1px那麼簡單。在retina屏下面,如果你寫了這樣的meta
<meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
你將永遠無法寫出1px寬度的東西,除此之外,inline的SVG等元素,也會按照邏輯畫素來渲染,整個頁面的清晰度會打折。
所以,手機淘寶用JS來動態寫meta標籤,程式碼類似這樣:
var metaEl = doc.createElement('meta');
var scale = isRetina ? 0.5:1;
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
if (docEl.firstElementChild) {
document.documentElement.firstElementChild.appendChild(metaEl);
} else {
var wrap = doc.createElement('div');
wrap.appendChild(metaEl);
documen.write(wrap.innerHTML);
}
結語
總的來說,手機淘寶的flexible方案是綜合運用rem和px兩種單位+js設定scale和html字型。
這些JS的內容,可以在我們開源的庫ml中找到:
相關文章
- Redis 設計與實現 (五)--多機資料庫的實現Redis資料庫
- 淘寶彈性佈局方案lib-flexible實踐Flex
- Titan 的設計與實現
- LFU 的設計與實現
- API的設計與實現API
- 手撕商城系統架構設計與實現架構
- 5款手機APP介面設計欣賞與手機APP設計學習APP
- 基於python爬蟲技術對於淘寶的資料分析的設計與實現Python爬蟲
- Picker元件的設計與實現元件
- RedisHttpSession 的設計與實現RedisHTTPSession
- 限流 SDK 的設計與實現
- 手機APP與原生APP設計的區別APP
- Redis設計與實現Redis
- 《redis設計與實現》Redis
- 單機秒殺系統的架構設計與實現架構
- Cobar SQL審計的設計與實現SQL
- Python實現火柴人的設計與實現Python
- Redis設計與實現閱讀總結(二)單機資料庫的實現Redis資料庫
- RedisSyncer同步引擎的設計與實現Redis
- 數獨遊戲的設計與實現遊戲
- Cuckoo Filter:設計與實現Filter
- Android Binder設計與實現 - 設計篇Android
- Python實現微博輿情分析的設計與實現Python
- 基於SSH培訓機構管理系統的設計與實現
- 淺析pplx庫的設計與實現。
- 旅遊網站的設計與實現網站
- 認證授權的設計與實現
- Steps 元件的設計與實現元件
- RocketMQ Compaction Topic的設計與實現MQ
- 聊聊「訂單」業務的設計與實現
- PouchContainer CRI的設計與實現方法AI
- Spring IOC容器的設計與實現Spring
- 事件匯流排的設計與實現事件
- 手機淘寶官方資料:2013年上半年手機淘寶運營資料
- linux核心設計與實現Linux
- 淺談VueUse設計與實現Vue
- OpenMP 原子指令設計與實現
- Redis 設計與實現 4:字典Redis