最新国产亚洲无码精品视频_亚洲欧洲日韩精品视频_日韩在线视精品在亚洲_国产91丝袜老师喷水_美女胸18下看禁止免费网站_男男videos視頻歐美_91成人超碰在线_亚洲精品一级在线上播放_久久亚洲国产精品三级_在线播放欧美日韩一区二区

首頁 / 創(chuàng)意H5定制/H5資訊

前端 H5 開發(fā)中你一定曉得的基礎(chǔ)知識

06.08

2020

2020.06.08

634

634
分享至

本文是內(nèi)部的一次分享沉淀,偏向基礎(chǔ)但是涉及了一些有意思的細(xì)節(jié),文筆有限,才疏學(xué)淺,文中若有不正之處,萬望告知。

前端的一大工作內(nèi)容就是去兼容頁面在不同內(nèi)核的瀏覽器,不同的設(shè)備,不同的分辨率下的行為,使頁面的能正常工作在各種各樣的宿主環(huán)境當(dāng)中。

而本文的主題 -- 移動端開發(fā)的兼容適配與性能優(yōu)化,就是希望能從一些常見的移動端開發(fā)問題出發(fā),厘清 Web 移動端開發(fā)的前前后后,一些技術(shù)的發(fā)展過程,一些問題的優(yōu)化手段以及給出一些常見的兼容性問題的解決方案。

什么是響應(yīng)式設(shè)計

首先先聊聊響應(yīng)式設(shè)計,這個與移動端開發(fā)有著密切的聯(lián)系。

響應(yīng)式設(shè)計即是 RWD,Responsive Web Design。

這里百度或者谷歌一下會有各種各樣的答案。這里一段摘自知乎上我覺得很棒的一個答案:什么是響應(yīng)式布局設(shè)計?[1]

根據(jù)維基百科及其參考文獻(xiàn),理論上,響應(yīng)式界面能夠適應(yīng)不同的設(shè)備。描述響應(yīng)式界面最著名的一句話就是“Content is like water”,翻譯成中文便是“如果將屏幕看作容器,那么內(nèi)容就像水一樣”。

為什么要設(shè)計響應(yīng)式界面

為什么要費(fèi)神地嘗試統(tǒng)一所有設(shè)備呢?

即便是 PC 或 Mac 用戶,有數(shù)據(jù)顯示只有一半的人會將瀏覽器全屏顯示,而剩下的一般人使用多大的瀏覽器,很難預(yù)知;臺式機(jī)、投影、電視、筆記本、手機(jī)、平板、手表、VR……智能設(shè)備正在不斷增加,“主流設(shè)備”的概念正在消失;屏幕分辨率正飛速發(fā)展,同一張圖片在不同設(shè)備上看起來,大小可能天差地別;鼠標(biāo)、觸屏、筆、攝像頭手勢……不可預(yù)期的操控方式正在不斷出現(xiàn)。

響應(yīng)式界面的四個層次

同一頁面在不同大小和比例上看起來都應(yīng)該是舒適的;同一頁面在不同分辨率上看起來都應(yīng)該是合理;同一頁面在不同操作方式(如鼠標(biāo)和觸屏)下,體驗應(yīng)該是統(tǒng)一的;同一頁面在不同類型的設(shè)備(手機(jī)、平板、電腦)上,交互方式應(yīng)該是符合習(xí)慣的。

響應(yīng)式界面的基本規(guī)則

可伸縮的內(nèi)容區(qū)塊:內(nèi)容區(qū)塊的在一定程度上能夠自動調(diào)整,以確保填滿整個頁面

可自由排布的內(nèi)容區(qū)塊:當(dāng)頁面尺寸變動較大時,能夠減少/增加排布的列數(shù)

適應(yīng)頁面尺寸的邊距:到頁面尺寸發(fā)生更大變化時,區(qū)塊的邊距也應(yīng)該變化

能夠適應(yīng)比例變化的圖片:對于常見的寬度調(diào)整,圖片在隱去兩側(cè)部分時,依舊保持美觀可用

能夠自動隱藏/部分顯示的內(nèi)容:如在電腦上顯示的的大段描述文本,在手機(jī)上就只能少量顯示或全部隱藏

能自動折疊的導(dǎo)航和菜單:展開還是收起,應(yīng)該根據(jù)頁面尺寸來判斷

放棄使用像素作為尺寸單位:用dp(對于前端來說,這里可能是rem)尺寸等方法來確保頁面在分辨率相差很大的設(shè)備上,看起來也能保持一致。同時也要求提供的圖片應(yīng)該比預(yù)想的更大,才能適應(yīng)高分辨率的屏幕

上面一段我覺得已經(jīng)涵蓋了響應(yīng)式設(shè)計的絕大部分,簡單總結(jié)起來,可以概括為:

媒體查詢,邊界斷點的規(guī)則設(shè)定(Media queries && break point)內(nèi)容的可伸縮性效果(Flexibel visuals)流式網(wǎng)格布局(Fluid grids)主要內(nèi)容呈現(xiàn)及圖片的高質(zhì)量(Main content and high quality)

響應(yīng)式 vs. 自適應(yīng)

響應(yīng)式設(shè)計是 Responsive Web Design(RWD),自適應(yīng)設(shè)計是 Adaptive Web Design(AWD)。經(jīng)常有人會將兩者混為一談,或者其實根本也區(qū)分不了所謂的響應(yīng)式與自適應(yīng)。

其實在我寫這篇文章的時候,我也無法很好的去區(qū)分兩者。

RWD 和 AWD 兩者都是為了適配各種不同的移動設(shè)備,致力于提升用戶體驗所產(chǎn)生的的技術(shù)。核心思想是用技術(shù)來使網(wǎng)頁適應(yīng)從小到大(現(xiàn)在到超大)的不同分辨率的屏幕。通常認(rèn)為,RWD 是 AWD 的子集。

RWD:Ethan Marcote 的文章是大家認(rèn)為 RWD 的起源。他提出的 RWD 方案是通過 HTML 和 CSS 的媒體查詢技術(shù),配合流體布局實現(xiàn)。RWD 傾向于只改變元素的外觀布局,而不大幅度改變內(nèi)容。Jeffrey Zeldman 總結(jié)說,我們就把 RWD 定義為一切能用來為各種分辨率和設(shè)備性能優(yōu)化視覺體驗的技術(shù)。

AWD:Adaptive Design 是 Aaron Gustafson 的書的標(biāo)題。他認(rèn)為 AWD 在包括 RWD 的 CSS 媒體查詢技術(shù)以外,也要用 Javascript 來操作 HTML 來更適應(yīng)移動設(shè)備的能力。AWD 有可能會針對移動端用戶減去內(nèi)容,減去功能。AWD 可以在服務(wù)器端就進(jìn)行優(yōu)化,把優(yōu)化過的內(nèi)容送到終端上。

一圖勝千言。

image

從定義上而言,RWD 是一套代碼,適用于所有屏幕。而 AWD 則是多端多套代碼。本文不會過多去糾結(jié)響應(yīng)式與自適應(yīng)區(qū)別,我覺得這兩者的本質(zhì)都是致力于適配不同設(shè)備,更好地提升用戶體驗。

Quora - Responsive Design vs. Adaptive Design?[2]zhihu -- Responsive design 和 Adaptive design 的區(qū)別[3]

漸進(jìn)增強(qiáng) vs. 優(yōu)雅降級

漸進(jìn)增強(qiáng)(progressive enhancement):針對低版本瀏覽器進(jìn)行構(gòu)建頁面,保證最基本的功能,然后再針對高級瀏覽器進(jìn)行效果、交互等改進(jìn)和追加功能達(dá)到更好的用戶體驗。

優(yōu)雅降級(graceful degradation):一開始就構(gòu)建完整的功能,然后再針對低版本瀏覽器進(jìn)行兼容。

區(qū)別:優(yōu)雅降級是從復(fù)雜的現(xiàn)狀開始,并試圖減少用戶體驗的供給,而漸進(jìn)增強(qiáng)則是從一個非?;A(chǔ)的,能夠起作用的版本開始,并不斷擴(kuò)充,以適應(yīng)未來環(huán)境的需要。降級(功能衰減)意味著往回看;而漸進(jìn)增強(qiáng)則意味著朝前看,同時保證其根基處于安全地帶。

漸進(jìn)增強(qiáng)/優(yōu)雅降級通常是 AWD 會牽扯到的另一個技術(shù)術(shù)語。本質(zhì)上而言即是隨著屏幕的大小的改變,功能會一點一點增強(qiáng)。

也通常會用在一些高級 CSS3 屬性上,我們對一些 CSS 屬性進(jìn)行特性檢測,甚至不進(jìn)行特性檢測直接使用。后果是在支持它的網(wǎng)頁上該屬性正常展示,而不支持它的網(wǎng)頁該屬性不生效,但也不影響用戶的基本使用。

典型的例子是 CSS3 逐漸被大眾認(rèn)可并被使用,PC端頁面開始由 IE678 向兼容性更好的IE9+,chrome,firefox瀏覽器轉(zhuǎn)變的時期。我們可以對頁面元素直接使用陰影,圓角等屬性。對于不支持它的低版本 IE 而言,沒有什么損失,而對于支持它的高級瀏覽器而言,帶給了用戶更好的交互視覺體驗,這就是漸進(jìn)增強(qiáng)。

移動端屏幕適配方案

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

通常而言,設(shè)計師只會給出單一分辨率下的設(shè)計稿,而我們要做的,就是以這個設(shè)計稿為基準(zhǔn),去適配所有不同大小的移動端設(shè)備。

在此之前,有一些基礎(chǔ)概念需要理解。

一些概念性的東西,大部分人很難一次性記住,或者記了又忘,我覺得記憶這個東西比較看技巧,比如關(guān)聯(lián)法,想象法,把這些生硬的概念與一些符合我們常識的知識關(guān)聯(lián)在一起記憶,往往能夠事半功倍。

設(shè)備獨立像素

以 iPhone6/7/8為例,這里我們打開 Chrome 開發(fā)者工具:

image

這里的 375 * 667 表示的是什么呢,表示的是設(shè)備獨立像素(DIP),也可以理解為 CSS 像素,也稱為邏輯像素:

設(shè)備獨立像素 = CSS 像素 = 邏輯像素

如何記憶呢?這里使用 CSS 像素來記憶,也就是說。我們設(shè)定一個寬度為 375px 的 div,剛好可以充滿這個設(shè)備的一行,配合高度 667px ,則 div 的大小剛好可以充滿整個屏幕。

物理像素

OK,那么,什么又是物理像素呢。我們到電商網(wǎng)站購買手機(jī),都會看一看手機(jī)的參數(shù),以 JD 上的 iPhone7 為例:

image

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

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

設(shè)備像素 = 物理像素

DPR(Device Pixel Ratio) 設(shè)備像素比

OK,有了上面兩個概念,就可以順理成章引出下一個概念。DPR(Device Pixel Ratio) 設(shè)備像素比,這個與我們通常說的視網(wǎng)膜屏(多倍屏,Retina屏)有關(guān)。

設(shè)備像素比描述的是未縮放狀態(tài)下,物理像素和設(shè)備獨立像素的初始比例關(guān)系。

簡單的計算公式:

DPR = 物理像素 / 設(shè)備獨立像素

我們套用一下上面 iPhone7 的數(shù)據(jù)(取設(shè)備的物理像素寬度與設(shè)備獨立像素寬度進(jìn)行計算):

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

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

可以得到 iPhone7 的 dpr 為 2。也就是我們常說的視網(wǎng)膜屏幕。

視網(wǎng)膜(Retina)屏幕是蘋果公司"發(fā)明"的一個營銷術(shù)語。蘋果公司將 dpr > 1 的屏幕稱為視網(wǎng)膜屏幕。

image

在視網(wǎng)膜屏幕中,以 dpr = 2 為例,把 4(2x2) 個像素當(dāng) 1 個像素使用,這樣讓屏幕看起來更精致,但是元素的大小本身卻不會改變:

image

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

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

image

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

上面三個概念(CSS像素、設(shè)備獨立像素、DPR)是我覺得比較重要的,還有一些其他比較重要的概念 PPI、DPI 不影響后續(xù)的內(nèi)容,可以自行去加深理解。

OK,到這里我們就完成了一個小的里程碑。我們通常說的H5手機(jī)適配也就是指的這兩個維度:

適配不同屏幕大小,也就是適配不同屏幕下的 CSS 像素適配不同像素密度,也就是適配不同屏幕下 dpr 不一致導(dǎo)致的一些問題

適配不同屏幕大小

適配不同屏幕大小,也就是適配不同屏幕下的 CSS 像素。最早移動端屏幕 CSS 像素適配方案是CSS媒體查詢。但是無法做到高保真接近 100% 的還原。

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

假設(shè)我們現(xiàn)在拿到標(biāo)注為 375*667 的大小的設(shè)計稿,其中一個元素的標(biāo)注如下:

以頁面寬度為基準(zhǔn)的話,那么,

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

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

然而,理想很豐滿,現(xiàn)實很骨感。實現(xiàn)上述百分比方案的核心需要一個全局通用的基準(zhǔn)單位,讓所有百分比展示以它為基準(zhǔn),但是在 CSS 中,根據(jù)CSS Values and Units Module Level 4[4]的定義:

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

具體來說:

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

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

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

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

文本大?。╢ont-size)支持百分比值,但相對參考值是父元素的font-size的值;

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

首先,支持百分比單位的度量屬性有其各自的參照基準(zhǔn),其次并非所有度量屬性都支持百分比單位。所以我們需要另辟蹊徑。

rem 適配方案

在 vw 方案出來之前,最被大眾接受的就是使用 rem 進(jìn)行適配的方案,因為 rem 滿足上面說的,可以是一個全局性的基準(zhǔn)單位。

rem(font size of the root element),在 CSS Values and Units Module Level 3[5]中的定義就是, 根據(jù)網(wǎng)頁的根元素來設(shè)置字體大小,和 em(font size of the element)的區(qū)別是,em 是根據(jù)其父元素的字體大小來設(shè)置,而 rem 是根據(jù)網(wǎng)頁的跟元素(html)來設(shè)置字體大小。

flexible

基于此,淘寶早年推行的一套以 rem 為基準(zhǔn)的適配方案:lib-flexible[6]。其核心做法在于:

根據(jù)設(shè)備的 dpr 動態(tài)改寫 <meta> 標(biāo)簽,設(shè)置 viewport 的縮放給 <html> 元素添加 data-dpr 屬性,并且動態(tài)改寫 data-dpr 的值根據(jù) document.documentElement.clientWidth 動態(tài)修改 <html> 的 font-size ,頁面其他元素使用 rem 作為長度單位進(jìn)行布局,從而實現(xiàn)頁面的等比縮放

關(guān)于頭兩點,其實現(xiàn)在的 lib-flexible 庫已經(jīng)不這樣做了,不再去縮放 Viewport,字體大小的設(shè)定也直接使用了 rem

hotcss

hotcss[7] 不是一個庫,也不是一個框架。它是一個移動端布局開發(fā)解決方案。使用 hotcss 可以讓移動端布局開發(fā)更容易。本質(zhì)的思想與 flexible 完全一致。

對于 rem 方案的一些總結(jié)

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

動態(tài)修改 Viewport 存在一定的風(fēng)險的,譬如通過 Viewport 改變了頁面的縮放之后,獲取到的 innerWidth/innerHeight 也會隨之發(fā)生變化,如果業(yè)務(wù)邏輯有獲取此類高寬進(jìn)行其他計算的,可能會導(dǎo)致意想不到的錯誤;

到今天,其實存在很多在 flexible 基礎(chǔ)上演化而來的各種 rem 解決方案,有的不會對 Viewport 進(jìn)行縮放處理,自行處理 1px 邊框問題。

flexible/hotcss 都并非純 CSS 方案,需要引入一定的 Javascript 代碼rem 的設(shè)計初衷并非是用于解決此類問題,用 rem 進(jìn)行頁面的寬度適配多少有一種 hack 的感覺存在一定的兼容性問題,對于安卓 4.4 以下版本系統(tǒng)不支持 viewport 縮放(當(dāng)然,flexible 處理 Android 系列時,始終認(rèn)為其 dpr 為 1,沒有進(jìn)行 viewport 縮放)

vw 適配方案

嚴(yán)格來說,使用 rem 進(jìn)行頁面適配其實是一種 hack 手段,rem 單位的初衷本身并不是用來進(jìn)行移動端頁面寬度適配的。

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

百分比適配方案的核心需要一個全局通用的基準(zhǔn)單位,rem 是不錯,但是需要借助 Javascript 進(jìn)行動態(tài)修改根元素的 font-size,而 vw/vh(vmax/vmin) 的出現(xiàn)則很好彌補(bǔ) rem 需要 JS 輔助的缺點。

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

1vw 等于 window.innerWidth 的數(shù)值的 1%1vh 等于window.innerHeight 的數(shù)值的 1%

再以上面設(shè)計稿圖的元素為例,那么,

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

根據(jù)相關(guān)的測試,可以使用 vw 進(jìn)行長度單位的有:

容器大小適配,可以使用 vw文本大小的適配,可以使用 vw大于 1px 的邊框、圓角、陰影都可以使用 vw內(nèi)距和外距,可以使用 vw

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


vw

CodePen Demo(移動端打開):使用 vw 進(jìn)行頁面適配[8]

自動轉(zhuǎn)換插件

當(dāng)我們使用 rem 作為長度單位的時,通常會有借助 Sass/Less 實現(xiàn)一個轉(zhuǎn)換函數(shù),像是這樣:

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

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

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

// 假設(shè)設(shè)計稿的寬度是 375px

@function px2vw($px) {
 @return $px / 375 * 100vw;
}

當(dāng)然,我們還可以借助一些插件包去實現(xiàn)這個自動轉(zhuǎn)換,提高效率,譬如 postcss-px-to-viewport[9]

vw polyfill

vw 現(xiàn)在畢竟還是存在兼容問題的,看看兼容性:

image

其實已經(jīng)覆蓋了絕大部分設(shè)備,那么如果業(yè)務(wù)使用了且又真的出現(xiàn)了兼容問題,應(yīng)該怎么處理呢?有兩種方式可以進(jìn)行降級處理:

CSS Houdini:通過CSS Houdini針對vw做處理,調(diào)用CSS Typed OM Level1 提供的 CSSUnitValue API。CSS Polyfill:通過相應(yīng)的Polyfill做相應(yīng)的處理,目前針對于 vw 單位的 Polyfill 主要有:vminpoly、Viewport Units Buggyfill、vunits.js和 Modernizr

對于 vw 方案的一些總結(jié)

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

也沒能很好的解決 1px 邊框在高清屏下的顯示問題,需要自行處理由于 vw 方案是完全的等比縮放,在完全等比還原設(shè)計稿的同時帶來的一個問題是無法很好的限定一個最大最小寬度值,由于 rem 方案是借助 Javascript 的,所以這一點 rem 比 vw 會更加的靈活

當(dāng)然,兩個方案現(xiàn)階段其實都可以使用甚至一起搭配使用,更多詳情可以讀讀:

再聊移動端頁面的適配[10]H5必知必會之像素級還原設(shè)計稿Responsive And Fluid Typography With vh And vw Units[11]使用VH和VW實現(xiàn)真正的流體排版[12]

1px線

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

設(shè)計師想要的 retina 下 border: 1px,其實是 1 物理像素寬度,而不是 1 CSS 像素寬度,對于 CSS 而言:

在 dpr = 1 時,此時 1 物理像素等于 1 CSS 像素寬度;在 dpr = 2 時,此時 1 物理像素等于 0.5 CSS 寬度像素,可以認(rèn)為 border-width: 1px 這里的 1px 其實是 1 CSS像素寬度,等于 2 像素物理寬度,設(shè)計師其實想要的是 border-width: 0.5px;在 dpr = 3 時,此時 1 物理像素等于 0.33 CSS 寬度像素,設(shè)計師其實想要的是 border-width: 0.333px

然而,并不是所有手機(jī)瀏覽器都能識別 border-width: 0.5px,在 iOS7 以下,Android 等其他系統(tǒng)里,小于 1px 的單位會被當(dāng)成為 0px 處理,那么如何實現(xiàn)這 0.5px、0.33px 呢?

這里介紹幾種方法:

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

Retina 屏幕下 1px 線的實現(xiàn)[13]

圖片適配及優(yōu)化

圖像通常占據(jù)了網(wǎng)頁上下載資源的絕大部分。優(yōu)化圖像通??梢宰畲笙薅鹊販p少從網(wǎng)站下載的字節(jié)數(shù)以及提高網(wǎng)站性能。

通??梢裕幸恍┩ㄓ玫膬?yōu)化手段:

消除多余的圖像資源盡可能利用 CSS3\SVG 矢量圖像替代某些光柵圖像謹(jǐn)慎使用字體圖標(biāo),使用網(wǎng)頁字體取代在圖像中進(jìn)行文本編碼選擇正確的圖片格式為不同 DPR 屏幕提供最適合的圖片尺寸

本文重點關(guān)注如何在不同的 dpr 屏幕下,讓圖片看起來都不失真。

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

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

無腦多倍圖

在移動端假設(shè)我們需要一張 CSS 像素為 300 x 200 的圖像,考慮到現(xiàn)在已經(jīng)有了 dpr = 3 的設(shè)備,那么要保證圖片在 dpr = 3 的設(shè)備下也正常高清展示,我們最大可能需要一張 900 x 600 的原圖。

這樣,不管設(shè)備的 dpr 是否為 3,我們統(tǒng)一都使用 3 倍圖。這樣即使在 dpr = 1,dpr = 2 的設(shè)備上,也能非常好的展示圖片。

當(dāng)然這樣并不可取,會造成大量帶寬的浪費(fèi)?,F(xiàn)代瀏覽器,提供了更好的方式,讓我們能夠根據(jù)設(shè)備 dpr 的不同,提供不同尺寸的圖片。

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

簡單來說,srcset 可以根據(jù)不同的 dpr 拉取對應(yīng)尺寸的圖片:

<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 表示 像素密度描述符,表示

當(dāng)屏幕的 dpr = 1 時,使用 images/illustration-small.png 這張圖當(dāng)屏幕的 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 = “[email protected] 300w,
                       [email protected] 600w,
                       [email protected] 1200w,
>

解析一下:

sizes = “(min-width: 600px) 600px, 300px"的意思是,如果屏幕當(dāng)前的 CSS 像素寬度大于或者等于 600px,則圖片的 CSS 寬度為 600px,反之,則圖片的 CSS 寬度為 300px。

也就是 sizes 屬性聲明了在不同寬度下圖片的 CSS 寬度表現(xiàn)。這里可以理解為,大屏幕下圖片寬度為 600px,小屏幕下圖片寬度為 300px。(具體的媒體查詢代碼由 CSS 實現(xiàn))

這里的 sizes 屬性只是聲明了在不同寬度下圖片的 CSS 寬度表現(xiàn),而具體使圖片在大于600px的屏幕上展示為600px寬度的代碼需要另外由 CSS 或者 JS 實現(xiàn),有點繞。

srcset = “[email protected] 300w, [email protected] 600w, [email protected] 1200w 里面的 300w,600w,900w 叫寬度描述符。怎么確定當(dāng)前場景會選取哪張圖片呢?

當(dāng)前屏幕 dpr = 2 ,CSS 寬度為 375px。

當(dāng)前屏幕 CSS 寬度為 375px,則圖片 CSS 寬度為 300px。分別用上述 3 個寬度描述符的數(shù)值除以 300。

300 / 300 = 1600 / 300 = 21200 / 300 = 4

上面計算得到的 1、 2、 4 即是算出的有效的像素密度,換算成和 x 描述符等價的值 。這里 600w 算出的 2 即滿足 dpr = 2 的情況,選擇此張圖。

當(dāng)前屏幕 dpr = 3 ,CSS 寬度為 414px。

當(dāng)前屏幕 CSS 寬度為 414px,則圖片 CSS 寬度仍為 300px。再計算一次:

300 / 300 = 1600 / 300 = 21200 / 300 = 4

因為 dpr = 3,2 已經(jīng)不滿足了,則此時會選擇 1200w 這張圖。

當(dāng)前屏幕 dpr = 1 ,CSS 寬度為 1920px。

當(dāng)前屏幕 CSS 寬度為 1920px,則圖片 CSS 寬度變?yōu)榱?600px。再計算一次:

300 / 600 = .5600 / 600 = 11200 / 600 = 2

因為 dpr = 1,所以此時會選擇 600w 對應(yīng)的圖片。

具體的可以試下這個 Demo:CodePen Demo -- srcset屬性配合w寬度描述符配合sizes屬性[14]

此方案的意義在于考慮到了響應(yīng)性布局的復(fù)雜性與屏幕的多樣性,利用上述規(guī)則,可以一次適配 PC 端大屏幕和移動端高清屏,一箭多雕。

CSS 有個類似的屬性,image-set(),搭配使用,效果更佳。

了解更多細(xì)節(jié),推薦看看:

Google Web Fundamentals -- Web Responsive Images[15]響應(yīng)式圖片srcset全新釋義sizes屬性w描述符[16]

字體適配方案

字體大小

字體是很多前端開發(fā)同學(xué)容易忽略的一個點,但是其中也是有很多小知識點。

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

PC上最小 font-size=12px手機(jī)上最小 font-size=8px

如果小于最小字體,那么字體默認(rèn)就是最小字體。

其次,很多早期的文章規(guī)范都建議不要使用奇數(shù)級單位來定義字體大?。ㄈ?13px,15px...),容易在一些低端設(shè)備上造成字體模糊,出現(xiàn)鋸齒。

字體的選擇展示

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

完整的一個字體資源實在太大了,所以我們應(yīng)該盡可能的使用用戶設(shè)備上已有的字體,而不是額外去下載字體資源,從而使加載時間明顯加快。

而從展示效果層面來說,使用系統(tǒng)字體能更好的與當(dāng)前操作系統(tǒng)使用的相匹配,得到最佳的展示效果。所以我們在字體使用方面,有一個應(yīng)該盡量去遵循的原則,也是現(xiàn)在大部分網(wǎng)站在字體適配上使用的策略:

使用各個支持平臺上的默認(rèn)系統(tǒng)字體。

兼顧各個操作系統(tǒng)

常見的操作系統(tǒng)有 Windows、Windows Phone、Mac OS X、iPhone、Android Phone、Linux。當(dāng)然對于普通用戶而言,無須關(guān)注 Linux 系統(tǒng)。

下面就以 CSS-Trick[17] 網(wǎng)站最新的 font-family 為例,看看他們是如何在字體選擇上做到適配各個操作系統(tǒng)的

{
  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 關(guān)鍵字

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

一類是類似這樣的具體的字體族名定義:font-family: Arial 這里定義了一個具體的字體樣式,字體族名為 Arial;

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

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

關(guān)于通用字體族名,在 CSS Fonts Module Level 3 -- Basic Font Properties[18] 中,定義了 5 個,也就是我們熟知的幾個通用字體族名:

serif 襯線字體族sans-serif 非襯線字體族monospace 等寬字體,即字體中每個字寬度相同cursive 草書字體fantasy 主要是那些具有特殊藝術(shù)效果的字體

新增通用字體族關(guān)鍵字

而在  CSS Fonts Module Level 4 -- Generic font families[19] 中,新增了幾個關(guān)鍵字:

system-ui 系統(tǒng)默認(rèn)字體emoji 用于兼容 emoji 表情符號字符math 適用于數(shù)學(xué)表達(dá)式fangsong 此字體系列用于中文的(仿宋)字體。

我們看看用的最多的 system-ui。

system-ui

簡單而言,font-family: system-ui 的目的就是在不同的操作系統(tǒng)的 Web 頁面下,自動選擇本操作系統(tǒng)下的默認(rèn)系統(tǒng)字體。

默認(rèn)使用特定操作系統(tǒng)的系統(tǒng)字體可以提高性能,因為瀏覽器或者 webview 不必去下載任何字體文件,而是使用已有的字體文件。font-family: system-ui 字體設(shè)置的優(yōu)勢之處在于它與當(dāng)前操作系統(tǒng)使用的字體相匹配,對于文本內(nèi)容而言,它可以得到最恰當(dāng)?shù)恼故尽?/p>

San Francisco Fonts

OK,簡單了解了 system-ui 字體族。但是像 -apple-system、BlinkMacSystemFont 沒有在最新的標(biāo)準(zhǔn)里出現(xiàn)。它們又代表什么意思呢?

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

San Francisco Fonts 又叫舊金山字體,是一款西文字體。隨著 iOS 9 更新面世,在 WatchOS 中隨 Apple Watch 一起悄然發(fā)售,并且還將在 Apple TV 上的新 tvOS 中使用。

San Francisco Fonts 在 iOS 系統(tǒng)上用于替代升級另外一款西文字體 Helvetica Neue。Apple 做了一些重要的改變,使其成為平臺上更好的, 甚至是完美的西文字體。

image

-apple-system/BlinkMacSystemFont

話說回來。正如每個前端開發(fā)人員都知道的那樣,將一個功能納入規(guī)范是一回事,將其納入瀏覽器又是另一回事。

幸運(yùn)的是,system-ui 的普及很快。Chrome 和 Safari 都可以在各種平臺上完全支持它。只有 Mozilla 和 Windows 相對落后。

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

image

仔細(xì)看上圖的最后兩行:

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 標(biāo)準(zhǔn)。

Segoe UI

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

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

Roboto

Roboto 是為 Android 操作系統(tǒng)設(shè)計的一個無襯線字體家族。Google 描述該字體為“現(xiàn)代的、但平易近人”和“有感情”的。

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

總結(jié)一下

到此,我們可以總結(jié)一下了。以 CSS-Tricks[21] 網(wǎng)站的 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;
}
system-ui,使用各個支持平臺上的默認(rèn)系統(tǒng)字體-apple-system, 在一些稍低版本 Mac OS X 和 iOS 上,它針對舊版上的 Neue Helvetica 和 Lucida Grande 字體,升級使用更為合適的 San Francisco FontsBlinkMacSystemFont,針對一些 Mac OS X 上的 Chrome 瀏覽器,使用系統(tǒng)默認(rèn)字體segoe ui,在 Windows 及 Windows Phone 上選取系統(tǒng)默認(rèn)字體Roboto,面向 Android 和一些新版的的 Chrome OSHelvetica,Arial,在針對不同操作系統(tǒng)不同平臺設(shè)定采用默認(rèn)系統(tǒng)字體后,針對一些低版本瀏覽器的降級方案sans-serif,兜底方案,保證字體風(fēng)格統(tǒng)一,至少也得是無襯線字體

上述 5 個字體族定義,優(yōu)先級由高到底,可以看到,它們 5 個都并非某個特定字體,基本的核心思想都是選擇對應(yīng)平臺上的默認(rèn)系統(tǒng)字體。

涵蓋了 iOS、MAC OS X、Android、Windows、Windows Phone 基本所有用戶經(jīng)常使用的主流操作系統(tǒng)。

使用系統(tǒng)默認(rèn)字體的主要原因是性能。字體通常是網(wǎng)站上加載的最大/最重的資源之一。如果我們可以使用用戶機(jī)器上已有的字體,我們就完全不需要再去獲取字體資源,從而使加載時間明顯加快。

并且系統(tǒng)字體的優(yōu)點在于它與當(dāng)前操作系統(tǒng)使用的相匹配,因此它的文本展示必然也是一個讓人舒適展示效果。

當(dāng)然,上述 font-family 的定義不一定是最佳的。譬如天貓移動端在 font-family 最前面添加了 "PingFang SC",miui,..必定也有他們的業(yè)務(wù)上的考慮。但是一些 fallback 方案向后兼容的思想都是一致的,值得參考學(xué)習(xí)。

更多的關(guān)于字體方面的細(xì)節(jié)知識,可以看看這幾篇文章:

你該知道的字體 -- font-family[22]Web 字體 font-family 再探秘[23]Using UI System Fonts In Web Design: A Quick Practical Guide[24]System Fonts in CSS[25]Apple’s San Francisco Font[26]

前端布局的兼容適配

前端工程師的一大工作內(nèi)容就是頁面布局。無論在PC端還是移動端,頁面布局的兼容適配都是重中之重。在整個前端發(fā)展的歷程中,布局的方法也在不斷的推陳出新。

布局發(fā)展歷程

簡單來說,前端的布局發(fā)展歷程經(jīng)歷了下面幾個過程:

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

每一種布局在特定時期都發(fā)揮了重要的作用,而每一種新的布局方式的出現(xiàn),往往都是因為現(xiàn)有的布局方式已經(jīng)在該時期已經(jīng)無法很好的滿足開發(fā)者的需求,無法滿足越來越潮流的頁面布局的方式。

以 Flexbox 的出現(xiàn)為例子,在 Flexbox 被大家廣為接受使用之前。我們一直在使用定位+浮動的布局方式。像下面這個布局:

容器寬度不定,內(nèi)部三個元素,均分排列且占滿整個空間,并且垂直居中。如果使用定位+浮動的布局方式,你無法很快想到最佳的解決方式。三個元素并排那么必然需要浮動或者絕對定位,容器寬度不定且中間元素始終居中,需要顧慮的方面就很多了。也許使用 text-align: justufy 可以 hack 實現(xiàn),等等等等。

然而,使用 flexbox 布局的話,只需要:

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

flexbox 的出現(xiàn),一次性解決了流動布局,彈性布局,排列方式等多個問題。并且它是簡潔的,可控的。

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

.container {
    display: flex;
}

.item {
    margin: auto;
}

最便捷的垂直居中方式[27]

CSS Grid Layout

OK,flexbox 已經(jīng)足夠優(yōu)秀了,為什么 gird 網(wǎng)格布局的出現(xiàn)又是為什么?它解決了什么 flex 布局無法很好解決的問題?

看看下面這張圖:

flexbox 是一維布局,他只能在一條直線上放置你的內(nèi)容區(qū)塊;而grid是一個二維布局。它除了可以靈活的控制水平方向之外,還能輕易的控制垂直方向的布局模式。對于上圖那樣的九宮格布局,它就可以輕而易舉的完成。

一圖以蔽之,flexbox:

gridbox:

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

在現(xiàn)階段,移動端布局應(yīng)當(dāng)更多使用 flexbox 去完成(相對那些還在使用 float 布局的),而考慮到未來頁面布局的推陳出新。對于 Grid 布局我們應(yīng)當(dāng)像前幾年對待 flexbox 一樣,重視起來,隨著兼容性的普及,Grid 布局也會慢慢成為主流。

最后

好了,本文到此結(jié)束,希望對你有幫助 :)

更多精彩技術(shù)文章匯總在我的 Github -- iCSS[29] ,持續(xù)更新,歡迎點個 star 訂閱收藏。

如果還有什么疑問或者建議,可以多多交流,原創(chuàng)文章,文筆有限,才疏學(xué)淺,文中若有不正之處,萬望告知。




用戶登錄

同意 用戶協(xié)議 或 注冊協(xié)議
我要用驗證碼登錄
還沒有賬戶? 點我申請
南京
上海
廣州
杭州
聯(lián)系電話 025-8481 8352; 8618 9092
電子郵件 [email protected]
微信咨詢 longmeiwangluo   點擊復(fù)制
聯(lián)系電話 137 8891 5955
電子郵件 [email protected]
微信咨詢    點擊復(fù)制
聯(lián)系電話 18927551025
電子郵件 [email protected]
微信咨詢    點擊復(fù)制
聯(lián)系電話 138 6813 5210
電子郵件 [email protected]
微信咨詢    點擊復(fù)制
Copyright ? 2024 南京龍媒網(wǎng)絡(luò)科技有限公司 All Right Reserved 站長統(tǒng)計