前端基礎知識概述 -- 移動端開發的屏幕、圖像、字體與佈局的兼容適配

本文是內部的一次分享沉澱,偏向基礎可是涉及了一些有意思的細節,文筆有限,才疏學淺,文中如有不正之處,萬望告知。css

前端的一大工做內容就是去兼容頁面在不一樣內核的瀏覽器,不一樣的設備,不一樣的分辨率下的行爲,使頁面的能正常工做在各類各樣的宿主環境當中。html

而本文的主題 -- 移動端開發的兼容適配與性能優化,就是但願能從一些常見的移動端開發問題出發,釐清 Web 移動端開發的前先後後,一些技術的發展過程,一些問題的優化手段以及給出一些常見的兼容性問題的解決方案。前端

 

什麼是響應式設計

首先先聊聊響應式設計,這個與移動端開發有着密切的聯繫。node

響應式設計便是 RWD,Responsive Web Design。git

這裏百度或者谷歌一下會有各類各樣的答案。這裏一段摘自知乎上我以爲很棒的一個答案:什麼是響應式佈局設計?github

根據維基百科及其參考文獻,理論上,響應式界面可以適應不一樣的設備。描述響應式界面最著名的一句話就是「Content is like water」,翻譯成中文即是「若是將屏幕看做容器,那麼內容就像水同樣」。web

 

爲何要設計響應式界面

爲何要費神地嘗試統一全部設備呢?chrome

  • 即使是PC或Mac用戶,有查顯示只有一半的人會將瀏覽器全屏顯示,而剩下的通常人使用多大的瀏覽器,很難預知;
  • 臺式機、投影、電視、筆記本、手機、平板、手錶、VR……智能設備正在不斷增長,「主流設備」的概念正在消失;
  • 屏幕分辨率正飛速發展,同一張圖片在不一樣設備上看起來,大小可能天差地別;
  • 鼠標、觸屏、筆、攝像頭手勢……不可預期的操控方式正在不斷出現。

 

響應式界面的四個層次

  • 同一頁面在不一樣大小和比例上看起來都應該是溫馨的;
  • 同一頁面在不一樣分辨率上看起來都應該是合理;
  • 同一頁面在不一樣操做方式(如鼠標和觸屏)下,體驗應該是統一的;
  • 同一頁面在不一樣類型的設備(手機、平板、電腦)上,交互方式應該是符合習慣的。

 

響應式界面的基本規則

  • 可伸縮的內容區塊:內容區塊的在必定程度上可以自動調整,以確保填滿整個頁面
    npm

  • 可自由排布的內容區塊:當頁面尺寸變更較大時,可以減小/增長排布的列數
    瀏覽器

  • 適應頁面尺寸的邊距:到頁面尺寸發生更大變化時,區塊的邊距也應該變化

  • 可以適應比例變化的圖片:對於常見的寬度調整,圖片在隱去兩側部分時,依舊保持美觀可用

  • 可以自動隱藏/部分顯示的內容:如在電腦上顯示的的大段描述文本,在手機上就只能少許顯示或所有隱藏

  • 能自動摺疊的導航和菜單:展開仍是收起,應該根據頁面尺寸來判斷

  • 放棄使用像素做爲尺寸單位:用dp(對於前端來講,這裏多是rem)尺寸等方法來確保頁面在分辨率相差很大的設備上,看起來也能保持一致。同時也要求提供的圖片應該比預想的更大,才能適應高分辨率的屏幕

上面一段我以爲已經涵蓋了響應式設計的絕大部分,簡單總結起來,能夠歸納爲:

  1. 媒體查詢,邊界斷點的規則設定(Media queries && break point)
  2. 內容的可伸縮性效果(Flexibel visuals)
  3. 流式網格佈局(Fluid grids)
  4. 主要內容呈現及圖片的高質量(Main content and high quality)

 

響應式 vs. 自適應

響應式設計是 Responsive Web Design(RWD),自適應設計是 Adaptive Web Design(AWD)。常常有人會將二者混爲一談,或者其實根本也區分不了所謂的響應式與自適應。

其實在我寫這篇文章的時候,我也沒法很好的去區分二者。

RWD 和 AWD 二者都是爲了適配各類不一樣的移動設備,致力於提高用戶體驗所產生的的技術。核心思想是用技術來使網頁適應從小到大(如今到超大)的不一樣分辨率的屏幕。一般認爲,RWD 是 AWD 的子集。

RWD:Ethan Marcote 的文章是你們認爲 RWD 的起源。他提出的 RWD 方案是經過 HTML 和 CSS 的媒體查詢技術,配合流體佈局實現。RWD 傾向於只改變元素的外觀佈局,而不大幅度改變內容。Jeffrey Zeldman 總結說,咱們就把 RWD 定義爲一切能用來爲各類分辨率和設備性能優化視覺體驗的技術。

AWD:Adaptive Design 是 Aaron Gustafson 的書的標題。他認爲 AWD 在包括 RWD 的 CSS 媒體查詢技術之外,也要用 Javascript 來操做 HTML 來更適應移動設備的能力。AWD 有可能會針對移動端用戶減去內容,減去功能。AWD 能夠在服務器端就進行優化,把優化過的內容送到終端上。

一圖勝千言。

image

從定義上而言,RWD 是一套代碼,適用於全部屏幕。而 AWD 則是多端多套代碼。本文不會過多去糾結響應式與自適應區別,我以爲這二者的本質都是致力於適配不一樣設備,更好地提高用戶體驗。

Quora - Responsive Design vs. Adaptive Design?
zhihu -- Responsive design 和 Adaptive design 的區別

 

漸進加強 vs. 優雅降級

  • 漸進加強(progressive enhancement):針對低版本瀏覽器進行構建頁面,保證最基本的功能,而後再針對高級瀏覽器進行效果、交互等改進和追加功能達到更好的用戶體驗。

  • 優雅降級(graceful degradation):一開始就構建完整的功能,而後再針對低版本瀏覽器進行兼容。

區別:優雅降級是從複雜的現狀開始,並試圖減小用戶體驗的供給,而漸進加強則是從一個很是基礎的,可以起做用的版本開始,並不斷擴充,以適應將來環境的須要。降級(功能衰減)意味着往回看;而漸進加強則意味着朝前看,同時保證其根基處於安全地帶。 

漸進加強/優雅降級一般是 AWD 會牽扯到的另外一個技術術語。本質上而言便是隨着屏幕的大小的改變,功能會一點一點加強。

也一般會用在一些高級 CSS3 屬性上,咱們對一些 CSS 屬性進行特性檢測,甚至不進行特性檢測直接使用。後果是在支持它的網頁上該屬性正常展現,而不支持它的網頁該屬性不生效,但也不影響用戶的基本使用。

典型的例子是 CSS3 逐漸被大衆承認並被使用,PC端頁面開始由 IE678 向兼容性更好的IE9+,chrome,firefox瀏覽器轉變的時期。咱們能夠對頁面元素直接使用陰影,圓角等屬性。對於不支持它的低版本 IE 而言,沒有什麼損失,而對於支持它的高級瀏覽器而言,帶給了用戶更好的交互視覺體驗,這就是漸進加強。

 

移動端屏幕適配方案

下面會針對一些具體的案例,展開講講。第一個是高保真還原設計稿,也就是如何適配移動端繁雜的屏幕大小。

一般而言,設計師只會給出單一分辨率下的設計稿,而咱們要作的,就是以這個設計稿爲基準,去適配全部不一樣大小的移動端設備。

在此以前,有一些基礎概念須要理解。

一些概念性的東西,大部分人很難一次性記住,或者記了又忘,我以爲記憶這個東西比較看技巧,好比關聯法,想象法,把這些生硬的概念與一些符合咱們常識的知識關聯在一塊兒記憶,每每可以事半功倍。

設備獨立像素

以 iPhone6/7/8爲例,這裏咱們打開 Chrome 開發者工具:

image

這裏的 375 * 667 表示的是什麼呢,表示的是設備獨立像素(DIP),也能夠理解爲 CSS 像素,也稱爲邏輯像素:

設備獨立像素 = CSS 像素 = 邏輯像素

如何記憶呢?這裏使用 CSS 像素來記憶,也就是說。咱們設定一個寬度爲 375px 的 div,恰好能夠充滿這個設備的一行,配合高度 667px ,則 div 的大小恰好能夠充滿整個屏幕。

 

物理像素

OK,那麼,什麼又是物理像素呢。咱們到電商網站購買手機,都會看一看手機的參數,以 JD 上的 iPhone7 爲例:

image

能夠看到,iPhone7 的分辨率是 1334 x 750,這裏描述的就是屏幕實際的物理像素。

物理像素,又稱爲設備像素。顯示屏是由一個個物理像素點組成的,1334 x 750 表示手機分別在垂直和水平上所具備的像素點數。經過控制每一個像素點的顏色,就可使屏幕顯示出不一樣的圖像,屏幕從工廠出來那天起,它上面的物理像素點就固定不變了,單位爲pt。

設備像素 = 物理像素

 

DPR(Device Pixel Ratio) 設備像素比

OK,有了上面兩個概念,就能夠瓜熟蒂落引出下一個概念。DPR(Device Pixel Ratio) 設備像素比,這個與咱們一般說的視網膜屏(多倍屏,Retina屏)有關。

設備像素比描述的是未縮放狀態下,物理像素和設備獨立像素的初始比例關係。

簡單的計算公式:

DPR = 物理像素 / 設備獨立像素

咱們套用一下上面 iPhone7 的數據(取設備的物理像素寬度與設備獨立像素寬度進行計算):

iPhone7’s DPR = iPhone7’s 物理像素寬度 / iPhone7's 設備獨立像素寬度 = 2

750 / 375 = 2
或者是 1334 / 667 = 2

能夠獲得 iPhone7 的 dpr 爲 2。也就是咱們常說的視網膜屏幕。

視網膜(Retina)屏幕是蘋果公司"發明"的一個營銷術語。 蘋果公司將 dpr > 1 的屏幕稱爲視網膜屏幕。

image

在視網膜屏幕中,以 dpr = 2 爲例,把 4(2x2) 個像素當 1 個像素使用,這樣讓屏幕看起來更精緻,可是元素的大小自己卻不會改變:

image

OK,咱們再來看看 iPhone XS Max:

屏幕快照 2019-07-08 下午8 02 00

它的物理像素如上圖是 2688 x 1242

image

它的 CSS 像素是 896 x 414,很容易得出 iPhone XS Max 的 dpr 爲 3。

上面三個概念(CSS像素、設備獨立像素、DPR)是我以爲比較重要的,還有一些其餘比較重要的概念 PPI、DPI 不影響後續的內容,能夠自行去加深理解。

OK,到這裏咱們就完成了一個小的里程碑。咱們一般說的H5手機適配也就是指的這兩個維度:

  1. 適配不一樣屏幕大小,也就是適配不一樣屏幕下的 CSS 像素
  2. 適配不一樣像素密度,也就是適配不一樣屏幕下 dpr 不一致致使的一些問題

 

適配不一樣屏幕大小

適配不一樣屏幕大小,也就是適配不一樣屏幕下的 CSS 像素。最先移動端屏幕 CSS 像素適配方案是CSS媒體查詢。可是沒法作到高保真接近 100% 的還原。

適配不一樣屏幕大小其實只須要遵循一條原則,確保頁面元素大小的與屏幕大小保持必定比例。也就是:按比例還原設計稿

屏幕快照 2019-07-29 下午7 23 05

假設咱們如今拿到標註爲 375*667 的大小的設計稿,其中一個元素的標註以下:

屏幕快照 2019-07-29 下午7 28 13

屏幕快照 2019-07-29 下午7 30 24

以頁面寬度爲基準的話,那麼,

  • 元素的寬度爲:209/375 = 55.73%
  • 元素的高度爲:80/375 = 21.33%
  • 元素的上左右邊距依次計算...

這樣,不管屏幕的 CSS 像素寬度是 320px 仍是 375px 仍是 414px,按照等量百分比還原出來的界面老是正確的。

然而,理想很豐滿,現實很骨感。實現上述百分比方案的核心須要一個全局通用的基準單位,讓全部百分比展現以它爲基準,可是在 CSS 中,根據CSS Values and Units Module Level 4的定義:

百分比值總要相對於另外一個量,好比長度。每一個容許使用百分比值的屬性,同時也要定義百分比值參照的那個量。這個量能夠是相同元素的另外一個屬性的值,也能夠是祖先元素的某個屬性的值,甚至是格式化上下文的一個度量(好比包含塊的寬度)。

具體來講:

  • 寬度(width)、間距(maring/padding)支持百分比值,但默認的相對參考值是包含塊的寬度;

  • 高度(height)百分比的大小是相對其父級元素高的大小;

  • 邊框(border)不支持百分值;

  • 邊框圓角半徑(border-radius)支持百分比值,但水平方向相對參考值是盒子的寬度,垂直方向相對參考值是盒子的高度;

  • 文本大小(font-size)支持百分比值,但相對參考值是父元素的font-size的值;

  • 盒陰影(box-shadow)和文本陰影(text-shadow)不支持百分比值;

首先,支持百分比單位的度量屬性有其各自的參照基準,其次並不是全部度量屬性都支持百分比單位。因此咱們須要另闢蹊徑。

 

rem 適配方案

在 vw 方案出來以前,最被大衆接受的就是使用 rem 進行適配的方案,由於 rem 知足上面說的,能夠是一個全局性的基準單位。

rem(font size of the root element),在 CSS Values and Units Module Level 3中的定義就是, 根據網頁的根元素來設置字體大小,和 em(font size of the element)的區別是,em 是根據其父元素的字體大小來設置,而 rem 是根據網頁的跟元素(html)來設置字體大小。

flexible

基於此,淘寶早年推行的一套以 rem 爲基準的適配方案:lib-flexible。其核心作法在於:

  • 根據設備的 dpr 動態改寫 <meta> 標籤,設置 viewport 的縮放
  • 給 <html> 元素添加 data-dpr 屬性,而且動態改寫 data-dpr 的值
  • 根據 document.documentElement.clientWidth 動態修改 <html> 的 font-size ,頁面其餘元素使用 rem 做爲長度單位進行佈局,從而實現頁面的等比縮放

關於頭兩點,其實如今的 lib-flexible 庫已經不這樣作了,再也不去縮放 Viewport,字體大小的設定也直接使用了 rem

hotcss

hotcss 不是一個庫,也不是一個框架。它是一個移動端佈局開發解決方案。使用 hotcss 可讓移動端佈局開發更容易。本質的思想與 flexible 徹底一致。

 

對於 rem 方案的一些總結

使用 flexible/hotcss 做爲屏幕寬度適配解決方案,是存在一些問題的:

  1. 動態修改 Viewport 存在必定的風險的,譬如經過 Viewport 改變了頁面的縮放以後,獲取到的 innerWidth/innerHeight 也會隨之發生變化,若是業務邏輯有獲取此類高寬進行其餘計算的,可能會致使意想不到的錯誤;

到今天,其實存在不少在 flexible 基礎上演化而來的各類 rem 解決方案,有的不會對 Viewport 進行縮放處理,自行處理 1px 邊框問題。

  1. flexible/hotcss 都並不是純 CSS 方案,須要引入必定的 Javascript 代碼
  2. rem 的設計初衷並不是是用於解決此類問題,用 rem 進行頁面的寬度適配多少有一種 hack 的感受
  3. 存在必定的兼容性問題,對於安卓 4.4 如下版本系統不支持 viewport 縮放(固然,flexible 處理 Android 系列時,始終認爲其 dpr 爲 1,沒有進行 viewport 縮放)

 

vw 適配方案

嚴格來講,使用 rem 進行頁面適配實際上是一種 hack 手段,rem 單位的初衷自己並非用來進行移動端頁面寬度適配的。

到了今天,有了一種更好的替代方案,使用 vw 進行適配 。

百分比適配方案的核心須要一個全局通用的基準單位,rem 是不錯,可是須要藉助 Javascript 進行動態修改根元素的 font-size,而 vw/vh(vmax/vmin) 的出現則很好彌補 rem 須要 JS 輔助的缺點。

根據 CSS Values and Units Module Level 4:vw等於初始包含塊(html元素)寬度的1%,也就是

  • 1vw 等於 window.innerWidth 的數值的 1%
  • 1vh 等於window.innerHeight 的數值的 1%

再以上面設計稿圖的元素爲例,那麼,

  • 元素的寬度爲:209/375 = 55.73% = 55.73vw
  • 元素的高度爲:80/375 = 21.33% = 21.33vw
  • 元素的上左右邊距依次計算...

根據相關的測試,可使用 vw 進行長度單位的有:

  • 容器大小適配,可使用 vw
  • 文本大小的適配,可使用 vw
  • 大於 1px 的邊框、圓角、陰影均可以使用 vw
  • 內距和外距,可使用 vw

簡單的一個頁面,看看效果,徹底是等比例縮放的效果:

vw

CodePen Demo(移動端打開):使用 vw 進行頁面適配

 

自動轉換插件

當咱們使用 rem 做爲長度單位的時,一般會有藉助 Sass/Less 實現一個轉換函數,像是這樣:

// 假設設計稿的寬度是 375px,假設取設計稿寬度下 1rem = 100px
$baseFontSize: 100;

@function px2rem($px) {
	@return $px / $baseFontSize * 1rem;
}

同理,在 vw 方案下,咱們只須要去改寫這個方法:

// 假設設計稿的寬度是 375px
@function px2rem($px) {
	@return $px / 375 * 100vw;
} 

固然,咱們還能夠藉助一些插件包去實現這個自動轉換,提升效率,譬如 postcss-px-to-viewport

 

vw polyfill

vw 如今畢竟仍是存在兼容問題的,看看兼容性:

image

其實已經覆蓋了絕大部分設備,那麼若是業務使用了且又真的出現了兼容問題,應該怎麼處理呢?有兩種方式能夠進行降級處理:

  • CSS Houdini:經過CSS Houdini針對vw作處理,調用CSS Typed OM Level1 提供的 CSSUnitValue API。
  • CSS Polyfill:經過相應的Polyfill作相應的處理,目前針對於 vw 單位的 Polyfill 主要有:vminpoly、Viewport Units Buggyfill、vunits.js和 Modernizr

 

對於 vw 方案的一些總結

vw 確實看上去很不錯,可是也是存在它的一些問題:

  1. 也沒能很好的解決 1px 邊框在高清屏下的顯示問題,須要自行處理
  2. 因爲 vw 方案是徹底的等比縮放,在徹底等比還原設計稿的同時帶來的一個問題是沒法很好的限定一個最大最小寬度值,因爲 rem 方案是藉助 Javascript 的,因此這一點 rem 比 vw 會更加的靈活

固然,兩個方案現階段其實均可以使用甚至一塊兒搭配使用,更多詳情能夠讀讀:

 

1px線

上面說到使用 vw 適配屏幕大小方案,其中有一個缺點就是在 Retina 屏下,沒法很好的展現真正的 1px 物理像素線條。

設計師想要的 retina 下 border: 1px,實際上是 1 物理像素寬,而不是 1 CSS 像素寬度,對於 CSS 而言:

  • 在 dpr = 1 時,此時 1 物理像素等於 1 CSS 像素寬度;
  • 在 dpr = 2 時,此時 1 物理像素等於 0.5 CSS 寬度像素,能夠認爲 border-width: 1px 這裏的 1px 實際上是 1 CSS像素寬度,等於 2 像素物理寬度,設計師其實想要的是 border-width: 0.5px;
  • 在 dpr = 3 時,此時 1 物理像素等於 0.33 CSS 寬度像素,設計師其實想要的是 border: 0.333px

然而,並非全部手機瀏覽器都能識別 border-width: 0.5px,在 iOS7 如下,Android 等其餘系統裏,小於 1px 的單位會被當成爲 0px 處理,那麼如何實現這 0.5px、0.33px 呢?

這裏介紹幾種方法:

  • 漸變實現
  • 使用縮放實現
  • 使用圖片實現(base64)
  • 使用SVG實現(嵌入 background url)

Retina 屏幕下 1px 線的實現

 

圖片適配及優化

圖像一般佔據了網頁上下載資源絕的大部分。優化圖像一般能夠最大限度地減小從網站下載的字節數以及提升網站性能。

一般能夠,有一些通用的優化手段:

  1. 消除多餘的圖像資源
  2. 儘量利用 CSS3\SVG 矢量圖像替代某些光柵圖像
  3. 謹慎使用字體圖標,使用網頁字體取代在圖像中進行文本編碼
  4. 選擇正確的圖片格式
  5. 爲不一樣 DPR 屏幕提供最適合的圖片尺寸

本文重點關注如何在不一樣的 dpr 屏幕下,讓圖片看起來都不失真。

首先就是上述的第二點,儘量利用 CSS3\SVG 矢量圖像替代某些光柵圖像。某些簡單的幾何圖標,能夠用 CSS3 快速實現的圖形,都應該儘可能避免使用光柵圖像。這樣可以保證它們在任何尺寸下都不會失真。

其次,實在到了必須使用光柵圖像的地步,也是有許多方式能保證圖像在各類場景下都不失真。

 

無腦多倍圖

在移動端假設咱們須要一張 CSS 像素爲 300 x 200 的圖像,考慮到如今已經有了 dpr = 3 的設備,那麼要保證圖片在 dpr = 3 的設備下也正常高清展現,咱們最大可能須要一張 900 x 600 的原圖。

這樣,無論設備的 dpr 是否爲 3,咱們統一都使用 3 倍圖。這樣即便在 dpr = 1,dpr = 2 的設備上,也能很是好的展現圖片。

固然這樣並不可取,會形成大量帶寬的浪費。現代瀏覽器,提供了更好的方式,讓咱們可以根據設備 dpr 的不一樣,提供不一樣尺寸的圖片。

  

srcset 配合 1x 2x 像素密度描述符

簡單來講,srcset 能夠根據不一樣的 dpr 拉取對應尺寸的圖片:

<div class='illustration'>
  <img src='illustration-small.png'
       srcset='images/illustration-small.png 1x,
               images/illustration-big.png 2x'
       style='max-width: 500px'/>
</div>

上面 srcset 裏的 1x,2x 表示 像素密度描述符,表示

  • 當屏幕的 dpr = 1 時,使用 images/illustration-small.png 這張圖
  • 當屏幕的 dpr = 2 時,使用 images/illustration-big.png 這張圖

 

srcset 屬性配合 sizes 屬性 w 寬度描述符

上面 1x,2x 的寫法比較容易接受易於理解。

除此以外,srcset屬性還有一個 w 寬度描述符,配合 sizes 屬性一塊兒使用,能夠覆蓋更多的面。

如下面這段代碼爲例子:

<img 
        sizes = 「(min-width: 600px) 600px, 300px" 
        src = "photo.png" 
        srcset = 「photo@1x.png 300w,
                       photo@2x.png 600w,
                       photo@3x.png 1200w,
>

解析一下:

sizes = 「(min-width: 600px) 600px, 300px" 的意思是,若是屏幕當前的 CSS 像素寬度大於或者等於 600px,則圖片的 CSS 寬度爲 600px,反之,則圖片的 CSS 寬度爲 300px。

也就是 sizes 屬性聲明瞭在不一樣寬度下圖片的 CSS 寬度表現。這裏能夠理解爲,大屏幕下圖片寬度爲 600px,小屏幕下圖片寬度爲 300px。(具體的媒體查詢代碼由 CSS 實現)

這裏的 sizes 屬性只是聲明瞭在不一樣寬度下圖片的 CSS 寬度表現,而具體使圖片在大於600px的屏幕上展現爲600px寬度的代碼須要另外由 CSS 或者 JS 實現,有點繞。

srcset = 「photo@1x.png 300w, photo@2x.png 600w, photo@3x.png 1200w 裏面的 300w,600w,900w 叫寬度描述符。怎麼肯定當前場景會選取哪張圖片呢?

1. 當前屏幕 dpr = 2 ,CSS 寬度爲 375px。

當前屏幕 CSS 寬度爲 375px,則圖片 CSS 寬度爲 300px。分別用上述 3 個寬度描述符的數值除以 300。

  1. 300 / 300 = 1
  2. 600 / 300 = 2
  3. 1200 / 300 = 4

上面計算獲得的 一、 二、 4 便是算出的有效的像素密度,換算成和 x 描述符等價的值 。這裏 600w 算出的 2 即知足 dpr = 2 的狀況,選擇此張圖。 

2. 當前屏幕 dpr = 3 ,CSS 寬度爲 414px。

當前屏幕 CSS 寬度爲 414px,則圖片 CSS 寬度仍爲 300px。再計算一次:

  1. 300 / 300 = 1
  2. 600 / 300 = 2
  3. 1200 / 300 = 4

由於 dpr = 3,2 已經不知足了,則此時會選擇 1200w 這張圖。

3. 當前屏幕 dpr = 1 ,CSS 寬度爲 1920px。

當前屏幕 CSS 寬度爲 1920px,則圖片 CSS 寬度變爲了 600px。再計算一次:

  1. 300 / 600 = .5
  2. 600 / 600 = 1
  3. 1200 / 600 = 2

由於 dpr = 1,因此此時會選擇 600w 對應的圖片。

具體的能夠試下這個 Demo:CodePen Demo -- srcset屬性配合w寬度描述符配合sizes屬性

此方案的意義在於考慮到了響應性佈局的複雜性與屏幕的多樣性,利用上述規則,能夠一次適配 PC 端大屏幕和移動端高清屏,一箭多雕。

瞭解更多細節,推薦看看:

 

字體適配方案

字體大小

字體是不少前端開發同窗容易忽略的一個點,可是其中也是有不少小知識點。

首先要知道,瀏覽器有最小字體限制:

  • PC上最小 font-size=12px
  • 手機上最小 font-size=8px

若是小於最小字體,那麼字體默認就是最小字體。

其次,不少早期的文章規範都建議不要使用奇數級單位來定義字體大小(如 13px,15px...),容易在一些低端設備上形成字體模糊,出現鋸齒。

 

字體的選擇展現

在字體適配上面,咱們須要從性能和展現效果兩個維度去考慮。

完整的一個字體資源實在太大了,因此咱們應該儘量的使用用戶設備上已有的字體,而不是額外去下載字體資源,從而使加載時間明顯加快。

而從展現效果層面來講,使用系統字體能更好的與當前操做系統使用的相匹配,獲得最佳的展現效果。因此咱們在字體使用方面,有一個應該儘可能去遵循的原則,也是如今大部分網站在字體適配上使用的策略:

使用各個支持平臺上的默認系統字體。

  

兼顧各個操做系統

常見的操做系統有 Windows、Windows Phone、Mac OS X、iPhone、Android Phone、Linux。固然對於普通用戶而言,無須關注 Linux 系統。

下面就以 CSS-Trick 網站最新的 font-family 爲例,看看他們是如何在字體選擇上作到適配各個操做系統的

{
  font-family: 
    system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,
    Helvetica,Arial,
    sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;
}

 

font-family 關鍵字

對於 CSS 中的 font-family 而言,它有兩類取值。

  1. 一類是相似這樣的具體的字體族名定義:font-family: Arial 這裏定義了一個具體的字體樣式,字體族名爲 Arial;

  2. 一類是通用字體族名,它是一種備選機制,用於在指定的字體不可用時給出較好的字體,相似這樣:font-family: sans-serif 。

其中,sans-serif 表無襯線字體族,例如, "Open Sans", "Arial" "微軟雅黑" 等等。

關於通用字體族名,在 CSS Fonts Module Level 3 -- Basic Font Properties 中,定義了 5 個,也就是咱們熟知的幾個通用字體族名:

  1. serif 襯線字體族
  2. sans-serif 非襯線字體族
  3. monospace 等寬字體,即字體中每一個字寬度相同
  4. cursive 草書字體
  5. fantasy 主要是那些具備特殊藝術效果的字體

 

新增通用字體族關鍵字

而在 CSS Fonts Module Level 4 -- Generic font families 中,新增了幾個關鍵字:

  • system-ui 系統默認字體
  • emoji 用於兼容 emoji 表情符號字符
  • math 適用於數學表達式
  • fangsong 此字體系列用於中文的(仿宋)字體。

咱們看看用的最多的 system-ui

 

system-ui

簡單而言,font-family: system-ui 的目的就是在不一樣的操做系統的 Web 頁面下,自動選擇本操做系統下的默認系統字體。

默認使用特定操做系統的系統字體能夠提升性能,由於瀏覽器或者 webview 沒必要去下載任何字體文件,而是使用已有的字體文件。 font-family: system-ui 字體設置的優點之處在於它與當前操做系統使用的字體相匹配,對於文本內容而言,它能夠獲得最恰當的展現。

 

San Francisco Fonts

OK,簡單瞭解了 system-ui 字體族。可是像 -apple-systemBlinkMacSystemFont 沒有在最新的標準裏出現。它們又表明什麼意思呢?

在此以前,先了解下 San Francisco Fonts 。

San Francisco Fonts 又叫舊金山字體,是一款西文字體。隨着 iOS 9 更新面世,在 WatchOS 中隨 Apple Watch 一塊兒悄然發售,而且還將在 Apple TV 上的新 tvOS 中使用。

San Francisco Fonts 在 iOS 系統上用於替代升級另一款西文字體 Helvetica Neue。Apple 作了一些重要的改變,使其成爲平臺上更好的, 甚至是完美的西文字體。

image

 

-apple-system/BlinkMacSystemFont

話說回來。正如每一個前端開發人員都知道的那樣,將一個功能歸入規範是一回事,將其歸入瀏覽器又是另外一回事。

幸運的是,system-ui 的普及很快。 Chrome 和 Safari 均可以在各類平臺上徹底支持它。只有 Mozilla 和 Windows 相對落後。

看看 system-ui 的兼容性,Can i Use -- system-ui(圖片截取日 2019-08-13):

image

仔細看上圖的最後兩行:

  • Supported as the -apple-system value (only on macOS and iOS)
  • Supported as the BlinkMacSystemFont value (only on macOS)

考慮到不一樣平臺及向後兼容,在 macOS 和 iOS 上,咱們須要使用 -apple-system 及 BlinkMacSystemFont 來兼容適配 system-ui 標準。

 

Segoe UI

Segoe UI 是 Windows 從 Vista 開始的默認西文字體族,只有西文,不支持漢字,屬於無襯線體。

它也表示一個系列而不是某一款單一字體。使用 font-family: Segoe UI 能夠在 Windows 平臺及 Windows Phone 上選取最佳的西文字體展現。

 

Roboto

Roboto 是爲 Android 操做系統設計的一個無襯線字體家族。Google 描述該字體爲「現代的、但平易近人」和「有感情」的。

這個字體家族包含Thin、Light、Regular、Medium、Bold、Black六種粗細及相配的斜體。

 

總結一下

到此,咱們能夠總結一下了。以 CSS-Tricks 網站的 font-family 定義爲例子:

{
  font-family: 
    system-ui,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,
    Helvetica,Arial,
    sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol;
}
  1. system-ui,使用各個支持平臺上的默認系統字體
  2. -apple-system, 在一些稍低版本 Mac OS X 和 iOS 上,它針對舊版上的 Neue Helvetica 和 Lucida Grande 字體,升級使用更爲合適的 San Francisco Fonts
  3. BlinkMacSystemFont,針對一些 Mac OS X 上的 Chrome 瀏覽器,使用系統默認字體
  4. segoe ui,在 Windows 及 Windows Phone 上選取系統默認字體
  5. Roboto,面向 Android 和一些新版的的 Chrome OS
  6. Helvetica,Arial,在針對不一樣操做系統不一樣平臺設定採用默認系統字體後,針對一些低版本瀏覽器的降級方案
  7. sans-serif,兜底方案,保證字體風格統一,至少也得是無襯線字體

上述 5 個字體族定義,優先級由高到底,能夠看到,它們 5 個都並不是某個特定字體,基本的核心思想都是選擇對應平臺上的默認系統字體。

涵蓋了 iOS、MAC OS X、Android、Windows、Windows Phone 基本全部用戶常用的主流操做系統。

使用系統默認字體的主要緣由是性能。字體一般是網站上加載的最大/最重的資源之一。若是咱們可使用用戶機器上已有的字體,咱們就徹底不須要再去獲取字體資源,從而使加載時間明顯加快。

而且系統字體的優勢在於它與當前操做系統使用的相匹配,所以它的文本展現必然也是一個讓人溫馨展現效果。

固然,上述 font-family 的定義不必定是最佳的。譬如天貓移動端在 font-family 最前面添加了 "PingFang SC",miui,..一定也有他們的業務上的考慮。可是一些 fallback 方案向後兼容的思想都是一致的,值得參考學習。

更多的關於字體方面的細節知識,能夠看看這幾篇文章:

 

前端佈局的兼容適配

前端工程師的一大工做內容就是頁面佈局。不管在PC端仍是移動端,頁面佈局的兼容適配都是重中之重。在整個前端發展的歷程中,佈局的方法也在不斷的推陳出新。

佈局發展歷程

簡單來講,前端的佈局發展歷程經歷了下面幾個過程:

表格佈局 --> 定位佈局 --> 浮動佈局 --> flexbox佈局 --> gridbox佈局

每一種佈局在特定時期都發揮了重要的做用,而每一種新的佈局方式的出現,每每都是由於現有的佈局方式已經在該時期已經沒法很好的知足開發者的需求,沒法知足愈來愈潮流的頁面佈局的方式。

以 Flexbox 的出現爲例子,在 Flexbox 被你們廣爲接受使用以前。咱們一直在使用定位+浮動的佈局方式。像下面這個佈局:

flexbox

容器寬度不定,內部三個元素,均分排列且佔滿整個空間,而且垂直居中。若是使用定位+浮動的佈局方式,你沒法很快想到最佳的解決方式。三個元素並排那麼必然須要浮動或者絕對定位,容器寬度不定且中間元素始終居中,須要顧慮的方面就不少了。也許使用 text-align: justufy 能夠 hack 實現,等等等等。

然而,使用 flexbox 佈局的話,只須要: 

.container {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

flexbox 的出現,一次性解決了流動佈局,彈性佈局,排列方式等多個問題。而且它是簡潔的,可控的。

再來看一個例子,水平垂直居中一個元素。使用 flexbox 也許是最便捷的:

.container {
    display: flex;
}

.item {
    margin: auto;
}

最便捷的垂直居中方式

 

CSS Grid Layout

OK,flexbox 已經足夠優秀了,爲何 gird 網格佈局的出現又是爲何?它解決了什麼 flex 佈局沒法很好解決的問題?

看看下面這張圖:

css grid layout

flexbox 是一維佈局,他只能在一條直線上放置你的內容區塊;而grid是一個二維佈局。它除了能夠靈活的控制水平方向以外,還能輕易的控制垂直方向的佈局模式。對於上圖那樣的九宮格佈局,它就能夠垂手可得的完成。

一圖以蔽之,flexbox:

flexbox

gridbox:

gridbox

圖片截取自陳慧晶老師在 2019 第五屆 CSS 大會上的分享 -- 新時代CSS佈局

在現階段,移動端佈局應當更多使用 flexbox 去完成(相對那些還在使用 float 佈局的),而考慮到將來頁面佈局的推陳出新。對於 Grid 佈局咱們應當像前幾年對待 flexbox 同樣,重視起來,隨着兼容性的普及,Grid 佈局也會慢慢成爲主流。

 

最後

好了,本文到此結束,但願對你有幫助 :)

更多精彩技術文章彙總在個人 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。

若是還有什麼疑問或者建議,能夠多多交流,原創文章,文筆有限,才疏學淺,文中如有不正之處,萬望告知。

相關文章
相關標籤/搜索