輕鬆搞定移動端適配

2021-03-02 高富帥程式設計師

作者:code秘密花園 公號 / ConardLi

導讀

移動端適配,是我們在開發中經常會遇到的,這裡面可能會遇到非常多的問題:

1px問題

UI圖完美適配方案

iPhoneX適配方案

橫屏適配

高清屏圖片模糊問題

...

上面這些問題可能我們在開發中已經知道如何解決,但是問題產生的原理,以及解決方案的原理可能會模糊不清。在解決這些問題的過程中,我們往往會遇到非常多的概念:像素、解析度、 PPI、 DPI、 DP、 DIP、 DPR、視口等等,你真的能分清這些概念的意義嗎?

本文將從移動端適配的基礎概念出發,探究移動端適配各種問題的解決方案和實現原理。

一、英寸

一般用英寸描述屏幕的物理大小,如電腦顯示器的 17、 22,手機顯示器的 4.8、 5.7等使用的單位都是英寸。

需要注意,上面的尺寸都是屏幕對角線的長度:

英寸( inch,縮寫為 in)在荷蘭語中的本意是大拇指,一英寸就是指甲底部普通人拇指的寬度。

英寸和釐米的換算:1英寸=2.54釐米

二、解析度2.1 像素

像素即一個小方塊,它具有特定的位置和顏色。

圖片、電子屏幕(手機、電腦)就是由無數個具有特定顏色和特定位置的小方塊拼接而成。

像素可以作為圖片或電子屏幕的最小組成單位。

下面我們使用 sketch打開一張圖片:

將這些圖片放大即可看到這些像素點:

通常我們所說的解析度有兩種,屏幕解析度和圖像解析度。

2.2 屏幕解析度

屏幕解析度指一個屏幕具體由多少個像素點組成。

下面是 apple的官網上對手機解析度的描述:

iPhone XSMax 和 iPhone SE的解析度分別為 2688x1242和 1136x640。這表示手機分別在垂直和水平上所具有的像素點數。

當然解析度高不代表屏幕就清晰,屏幕的清晰程度還與尺寸有關。

2.3 圖像解析度

我們通常說的 圖片解析度其實是指圖片含有的 像素數,比如一張圖片的解析度為 800x400。這表示圖片分別在垂直和水平上所具有的像素點數為 800和 400。

同一尺寸的圖片,解析度越高,圖片越清晰。

2.4 PPI

PPI(PixelPerInch):每英寸包括的像素數。

PPI可以用於描述屏幕的清晰度以及一張圖片的質量。

使用 PPI描述圖片時, PPI越高,圖片質量越高,使用 PPI描述屏幕時, PPI越高,屏幕越清晰。

在上面描述手機解析度的圖片中,我們可以看到:iPhone XSMax 和 iPhone SE的 PPI分別為 458和 326,這足以證明前者的屏幕更清晰。

由於手機尺寸為手機對角線的長度,我們通常使用如下的方法計算 PPI:

$$ \frac{\sqrt{水平像素點數^2+垂直像素點數^2}}{尺寸}$$

iPhone6的 PPI為 $ \frac{\sqrt{1334^2+750^2}}{4.7}=325.6$,那它每英寸約含有 326個物理像素點。

2.5 DPI

DPI(DotPerInch):即每英寸包括的點數。

這裡的點是一個抽象的單位,它可以是屏幕像素點、圖片像素點也可以是印表機的墨點。

平時你可能會看到使用 DPI來描述圖片和屏幕,這時的 DPI應該和 PPI是等價的, DPI最常用的是用於描述印表機,表示印表機每英寸可以列印的點數。

一張圖片在屏幕上顯示時,它的像素點數是規則排列的,每個像素點都有特定的位置和顏色。

當使用印表機進行列印時,印表機可能不會規則的將這些點列印出來,而是使用一個個列印點來呈現這張圖像,這些列印點之間會有一定的空隙,這就是 DPI所描述的:列印點的密度。

在上面的圖像中我們可以清晰的看到,印表機是如何使用墨點來列印一張圖像。

所以,印表機的 DPI越高,列印圖像的精細程度就越高,同時這也會消耗更多的墨點和時間。

三、設備獨立像素

實際上,上面我們描述的像素都是 物理像素,即設備上真實的物理單元。

下面我們來看看 設備獨立像素究竟是如何產生的:

智慧型手機發展非常之快,在幾年之前,我們還用著解析度非常低的手機,比如下面左側的白色手機,它的解析度是 320x480,我們可以在上面瀏覽正常的文字、圖片等等。

但是,隨著科技的發展,低解析度的手機已經不能滿足我們的需求了。很快,更高解析度的屏幕誕生了,比如下面的黑色手機,它的解析度是 640x940,正好是白色手機的兩倍。

理論上來講,在白色手機上相同大小的圖片和文字,在黑色手機上會被縮放一倍,因為它的解析度提高了一倍。這樣,豈不是後面出現更高解析度的手機,頁面元素會變得越來越小嗎?

然而,事實並不是這樣的,我們現在使用的智慧型手機,不管解析度多高,他們所展示的界面比例都是基本類似的。賈伯斯在 iPhone4的發布會上首次提出了 RetinaDisplay(視網膜屏幕)的概念,它正是解決了上面的問題,這也使它成為一款跨時代的手機。

在 iPhone4使用的視網膜屏幕中,把 2x2個像素當 1個像素使用,這樣讓屏幕看起來更精緻,但是元素的大小卻不會改變。

如果黑色手機使用了視網膜屏幕的技術,那麼顯示結果應該是下面的情況,比如列表的寬度為 300個像素,那麼在一條水平線上,白色手機會用 300個物理像素去渲染它,而黑色手機實際上會用 600個物理像素去渲染它。

我們必須用一種單位來同時告訴不同解析度的手機,它們在界面上顯示元素的大小是多少,這個單位就是設備獨立像素( DeviceIndependentPixels)簡稱 DIP或 DP。上面我們說,列表的寬度為 300個像素,實際上我們可以說:列表的寬度為 300個設備獨立像素。

打開 chrome的開發者工具,我們可以模擬各個手機型號的顯示情況,每種型號上面會顯示一個尺寸,比如 iPhone X顯示的尺寸是 375x812,實際 iPhone X的解析度會比這高很多,這裡顯示的就是設備獨立像素。

3.1 設備像素比

設備像素比 device pixel ratio簡稱 dpr,即物理像素和設備獨立像素的比值。

在 web中,瀏覽器為我們提供了 window.devicePixelRatio來幫助我們獲取 dpr。

在 css中,可以使用媒體查詢 min-device-pixel-ratio,區分 dpr:

@media(-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2){ }

在 ReactNative中,我們也可以使用 PixelRatio.get()來獲取 DPR。

當然,上面的規則也有例外, iPhone6、7、8Plus的實際物理像素是 1080x1920,在開發者工具中我們可以看到:它的設備獨立像素是 414x736,設備像素比為 3,設備獨立像素和設備像素比的乘積並不等於 1080x1920,而是等於 1242x2208。

實際上,手機會自動把 1242x2208個像素點塞進 1080*1920個物理像素點來渲染,我們不用關心這個過程,而 1242x2208被稱為屏幕的 設計像素。我們開發過程中也是以這個 設計像素為準。

實際上,從蘋果提出視網膜屏幕開始,才出現設備像素比這個概念,因為在這之前,行動裝置都是直接使用物理像素來進行展示。

緊接著, Android同樣使用了其他的技術方案來實現 DPR大於 1的屏幕,不過原理是類似的。由於 Android屏幕尺寸非常多、解析度高低跨度非常大,不像蘋果只有它自己的幾款固定設備、尺寸。所以,為了保證各種設備的顯示效果, Android按照設備的像素密度將設備分成了幾個區間:

當然,所有的 Android設備不一定嚴格按照上面的解析度,每個類型可能對應幾種不同解析度,所以,每個 Android手機都能根據給定的區間範圍,確定自己的 DPR,從而擁有類似的顯示。當然,僅僅是類似,由於各個設備的尺寸、解析度上的差異,設備獨立像素也不會完全相等,所以各種 Android設備仍然不能做到在展示上完全相等。

3.2 移動端開發

在 iOS、 Android和 ReactNative開發中樣式單位其實都使用的是設備獨立像素。

iOS的尺寸單位為 pt, Android的尺寸單位為 dp, ReactNative中沒有指定明確的單位,它們其實都是設備獨立像素 dp。

在使用 ReactNative開發 App時, UI給我們的原型圖一般是基於 iphone6的像素給定的。

為了適配所有機型,我們在寫樣式時需要把物理像素轉換為設備獨立像素:例如:如果給定一個元素的高度為 200px(這裡的 px指物理像素,非 CSS像素), iphone6的設備像素比為 2,我們給定的 height應為 200px/2=100dp。

當然,最好的是,你可以和設計溝通好,所有的 UI圖都按照設備獨立像素來出。

我們還可以在代碼( ReactNative)中進行 px和 dp的轉換:

import{PixelRatio} from 'react-native';

const dpr = PixelRatio.get();

/**

* px轉換為dp

*/

exportfunction pxConvertTodp(px) {

return px / dpr;

}

/**

* dp轉換為px

*/

exportfunction dpConvertTopx(dp) {

returnPixelRatio.getPixelSizeForLayoutSize(dp);

}

3.3 WEB端開發

在寫 CSS時,我們用到最多的單位是 px,即 CSS像素,當頁面縮放比例為 100%時,一個 CSS像素等於一個設備獨立像素。

但是 CSS像素是很容易被改變的,當用戶對瀏覽器進行了放大, CSS像素會被放大,這時一個 CSS像素會跨越更多的物理像素。

頁面的縮放係數=CSS像素/設備獨立像素。

3.4 關於屏幕

這裡多說兩句 Retina屏幕,因為我在很多文章中看到對 Retina屏幕的誤解。

Retina屏幕只是蘋果提出的一個營銷術語:

在普通的使用距離下,人的肉眼無法分辨單個的像素點。

為什麼強調 普通的使用距離下呢?我們來看一下它的計算公式:

$$ a=2arctan(h/2d) $$

a代表人眼視角, h代表像素間距, d代表肉眼與屏幕的距離,符合以上條件的屏幕可以使肉眼看不見單個物理像素點。

它不能單純的表達解析度和 PPI,只能一種表達視覺效果。

讓多個物理像素渲染一個獨立像素只是 Retina屏幕為了達到效果而使用的一種技術。而不是所有 DPR>1的屏幕就是 Retina屏幕。

比如:給你一塊超大尺寸的屏幕,即使它的 PPI很高, DPR也很高,在近距離你也能看清它的像素點,這就不算 Retina屏幕。

我們經常見到用 K和 P這個單位來形容屏幕:

P代表的就是屏幕縱向的像素個數, 1080P即縱向有 1080個像素,解析度為 1920X1080的屏幕就屬於 1080P屏幕。

我們平時所說的高清屏其實就是屏幕的物理解析度達到或超過 1920X1080的屏幕。

K代表屏幕橫向有幾個 1024個像素,一般來講橫向像素超過 2048就屬於 2K屏,橫向像素超過 4096就屬於 4K屏。

四、視口

視口( viewport)代表當前可見的計算機圖形區域。在 Web瀏覽器術語中,通常與瀏覽器窗口相同,但不包括瀏覽器的 UI, 菜單欄等——即指你正在瀏覽的文檔的那一部分。

一般我們所說的視口共包括三種:布局視口、視覺視口和理想視口,它們在屏幕適配中起著非常重要的作用。

4.1 布局視口

布局視口( layout viewport):當我們以百分比來指定一個元素的大小時,它的計算值是由這個元素的包含塊計算而來的。當這個元素是最頂級的元素時,它就是基於布局視口來計算的。

所以,布局視口是網頁布局的基準窗口,在 PC瀏覽器上,布局視口就等於當前瀏覽器的窗口大小(不包括 borders 、 margins、滾動條)。

在移動端,布局視口被賦予一個默認值,大部分為 980px,這保證 PC的網頁可以在手機瀏覽器上呈現,但是非常小,用戶可以手動對網頁進行放大。

我們可以通過調用 document.documentElement.clientWidth/clientHeight來獲取布局視口大小。

4.2 視覺視口

視覺視口( visual viewport):用戶通過屏幕真實看到的區域。

視覺視口默認等於當前瀏覽器的窗口大小(包括滾動條寬度)。

當用戶對瀏覽器進行縮放時,不會改變布局視口的大小,所以頁面布局是不變的,但是縮放會改變視覺視口的大小。

例如:用戶將瀏覽器窗口放大了 200%,這時瀏覽器窗口中的 CSS像素會隨著視覺視口的放大而放大,這時一個 CSS像素會跨越更多的物理像素。

所以,布局視口會限制你的 CSS布局而視覺視口決定用戶具體能看到什麼。

我們可以通過調用 window.innerWidth/innerHeight來獲取視覺視口大小。

4.3 理想視口

布局視口在移動端展示的效果並不是一個理想的效果,所以理想視口( ideal viewport)就誕生了:網站頁面在移動端展示的理想大小。

如上圖,我們在描述設備獨立像素時曾使用過這張圖,在瀏覽器調試移動端時頁面上給定的像素大小就是理想視口大小,它的單位正是設備獨立像素。

上面在介紹 CSS像素時曾經提到 頁面的縮放係數=CSS像素/設備獨立像素,實際上說 頁面的縮放係數=理想視口寬度/視覺視口寬度更為準確。

所以,當頁面縮放比例為 100%時, CSS像素=設備獨立像素, 理想視口=視覺視口。

我們可以通過調用 screen.width/height來獲取理想視口大小。

4.4 Meta viewport

<meta> 元素表示那些不能由其它 HTML元相關元素之一表示的任何元數據信息,它可以告訴瀏覽器如何解析頁面。

我們可以藉助 <meta>元素的 viewport來幫助我們設置視口、縮放等,從而讓移動端得到更好的展示效果。

<metaname="viewport"content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">

上面是 viewport的一個配置,我們來看看它們的具體含義:

Value| 可能值| 描述-|-|- width| 正整數或 device-width | 以 pixels(像素)為單位, 定義布局視口的寬度。height| 正整數或 device-height | 以 pixels(像素)為單位, 定義布局視口的高度。initial-scale| 0.0-10.0|定義頁面初始縮放比率。minimum-scale| 0.0-10.0|定義縮放的最小值;必須小於或等於 maximum-scale的值。maximum-scale| 0.0-10.0|定義縮放的最大值;必須大於或等於 minimum-scale的值。user-scalable| 一個布爾值( yes或者 no)| 如果設置為 no,用戶將不能放大或縮小網頁。默認值為 yes。

4.5 移動端適配

為了在移動端讓頁面獲得更好的顯示效果,我們必須讓布局視口、視覺視口都儘可能等於理想視口。

device-width就等於理想視口的寬度,所以設置 width=device-width就相當於讓布局視口等於理想視口。

由於 initial-scale=理想視口寬度/視覺視口寬度,所以我們設置 initial-scale=1;就相當於讓視覺視口等於理想視口。

這時,1個 CSS像素就等於1個設備獨立像素,而且我們也是基於理想視口來進行布局的,所以呈現出來的頁面布局在各種設備上都能大致相似。

4.6 縮放

上面提到 width可以決定布局視口的寬度,實際上它並不是布局視口的唯一決定性因素,設置 initial-scale也有肯能影響到布局視口,因為布局視口寬度取的是 width和視覺視口寬度的最大值。

例如:若手機的理想視口寬度為 400px,設置 width=device-width, initial-scale=2,此時 視覺視口寬度=理想視口寬度/initial-scale即 200px,布局視口取兩者最大值即 device-width 400px。

若設置 width=device-width, initial-scale=0.5,此時 視覺視口寬度=理想視口寬度/initial-scale即 800px,布局視口取兩者最大值即 800px。

4.7 獲取瀏覽器大小

瀏覽器為我們提供的獲取窗口大小的 API有很多,下面我們再來對比一下:

window.innerHeight:獲取瀏覽器視覺視口高度(包括垂直滾動條)。

window.outerHeight:獲取瀏覽器窗口外部的高度。表示整個瀏覽器窗口的高度,包括側邊欄、窗口鑲邊和調正窗口大小的邊框。

window.screen.Height:獲取獲屏幕取理想視口高度,這個數值是固定的, 設備的解析度/設備像素比

window.screen.availHeight:瀏覽器窗口可用的高度。

document.documentElement.clientHeight:獲取瀏覽器布局視口高度,包括內邊距,但不包括垂直滾動條、邊框和外邊距。

document.documentElement.offsetHeight:包括內邊距、滾動條、邊框和外邊距。

document.documentElement.scrollHeight:在不使用滾動條的情況下適合視口中的所有內容所需的最小寬度。測量方式與 clientHeight相同:它包含元素的內邊距,但不包括邊框,外邊距或垂直滾動條。

五、1px問題

為了適配各種屏幕,我們寫代碼時一般使用設備獨立像素來對頁面進行布局。

而在設備像素比大於 1的屏幕上,我們寫的 1px實際上是被多個物理像素渲染,這就會出現 1px在有些屏幕上看起來很粗的現象。

5.1 border-image

基於 media查詢判斷不同的設備像素比給定不同的 border-image:

.border_1px{

border-bottom: 1px solid #000;

}

@media only screen and(-webkit-min-device-pixel-ratio:2){

.border_1px{

border-bottom: none;

border-width: 001px0;

border-image: url(../img/1pxline.png) 0020 stretch;

}

}

5.2 background-image

和 border-image類似,準備一張符合條件的邊框背景圖,模擬在背景上。

.border_1px{

border-bottom: 1px solid #000;

}

@media only screen and(-webkit-min-device-pixel-ratio:2){

.border_1px{

background: url(../img/1pxline.png) repeat-x left bottom;

background-size: 100% 1px;

}

}

上面兩種都需要單獨準備圖片,而且圓角不是很好處理,但是可以應對大部分場景。

5.3 偽類 + transform

基於 media查詢判斷不同的設備像素比對線條進行縮放:

.border_1px:before{

content: '';

position: absolute;

top: 0;

height: 1px;

width: 100%;

background-color: #000;

transform-origin: 50% 0%;

}

@media only screen and(-webkit-min-device-pixel-ratio:2){

.border_1px:before{

transform: scaleY(0.5);

}

}

@media only screen and(-webkit-min-device-pixel-ratio:3){

.border_1px:before{

transform: scaleY(0.33);

}

}

這種方式可以滿足各種場景,如果需要滿足圓角,只需要給偽類也加上 border-radius即可。

5.4 svg

上面我們 border-image和 background-image都可以模擬 1px邊框,但是使用的都是位圖,還需要外部引入。

藉助 PostCSS的 postcss-write-svg我們能直接使用 border-image和 background-image創建 svg的 1px邊框:

@svg border_1px {

height: 2px;

@rect{

fill: var(--color, black);

width: 100%;

height: 50%;

}

}

.example { border: 1px solid transparent; border-image: svg(border_1px param(--color #00b1ff)) 2 2 stretch; }

編譯後:

.example { border: 1px solid transparent; border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='2px'%3E%3Crect fill='%2300b1ff' width='100%25' height='50%25'/%3E%3C/svg%3E") 22 stretch; }

上面的方案是大漠在他的文章中推薦使用的,基本可以滿足所有場景,而且不需要外部引入,這是我個人比較喜歡的一種方案。

5.5 設置viewport

通過設置縮放,讓 CSS像素等於真正的物理像素。

例如:當設備像素比為 3時,我們將頁面縮放 1/3倍,這時 1px等於一個真正的屏幕像素。

const scale = 1/ window.devicePixelRatio;

const viewport = document.querySelector('meta[name="viewport"]');

if(!viewport) {

viewport = document.createElement('meta');

viewport.setAttribute('name', 'viewport');

window.document.head.appendChild(viewport);

}

viewport.setAttribute('content', 'width=device-width,user-scalable=no,initial-scale='+ scale + ',maximum-scale='+ scale + ',minimum-scale='+ scale);

實際上,上面這種方案是早先 flexible採用的方案。

當然,這樣做是要付出代價的,這意味著你頁面上所有的布局都要按照物理像素來寫。這顯然是不現實的,這時,我們可以藉助 flexible或 vw、vh來幫助我們進行適配。

六、移動端適配方案

儘管我們可以使用設備獨立像素來保證各個設備在不同手機上顯示的效果類似,但這並不能保證它們顯示完全一致,我們需要一種方案來讓設計稿得到更完美的適配。

6.1 flexible方案

flexible方案是阿里早期開源的一個移動端適配解決方案,引用 flexible後,我們在頁面上統一使用 rem來布局。

它的核心代碼非常簡單:

// set 1rem = viewWidth / 10

function setRemUnit () {

var rem = docEl.clientWidth / 10

docEl.style.fontSize = rem + 'px'

}

setRemUnit();

rem 是相對於 html節點的 font-size來做計算的。

我們通過設置 document.documentElement.style.fontSize就可以統一整個頁面的布局標準。

上面的代碼中,將 html節點的 font-size設置為頁面 clientWidth(布局視口)的 1/10,即 1rem就等於頁面布局視口的 1/10,這就意味著我們後面使用的 rem都是按照頁面比例來計算的。

這時,我們只需要將 UI出的圖轉換為 rem即可。

以 iPhone6為例:布局視口為 375px,則 1rem=37.5px,這時 UI給定一個元素的寬為 75px(設備獨立像素),我們只需要將它設置為 75/37.5=2rem。

當然,每個布局都要計算非常繁瑣,我們可以藉助 PostCSS的 px2rem插件來幫助我們完成這個過程。

下面的代碼可以保證在頁面大小變化時,布局可以自適應,當觸發了 window的 resize和 pageShow事件之後自動調整 html的 fontSize大小。

// reset rem unit on page resize

window.addEventListener('resize', setRemUnit)window.addEventListener('pageshow', function(e) {

if(e.persisted) {

setRemUnit()

}

})

由於 viewport單位得到眾多瀏覽器的兼容,上面這種方案現在已經被官方棄用:

lib-flexible這個過渡方案已經可以放棄使用,不管是現在的版本還是以前的版本,都存有一定的問題。建議大家開始使用viewport來替代此方案。

下面我們來看看現在最流行的 vh、vw方案。

6.2 vh、vw方案

vh、vw方案即將視覺視口寬度 window.innerWidth和視覺視口高度 window.innerHeight 等分為 100 份。

上面的 flexible方案就是模仿這種方案,因為早些時候 vw還沒有得到很好的兼容。

如果視覺視口為 375px,那麼 1vw=3.75px,這時 UI給定一個元素的寬為 75px(設備獨立像素),我們只需要將它設置為 75/3.75=20vw。

這裡的比例關係我們也不用自己換算,我們可以使用 PostCSS的 postcss-px-to-viewport 插件幫我們完成這個過程。寫代碼時,我們只需要根據 UI給的設計圖寫 px單位即可。

當然,沒有一種方案是十全十美的, vw同樣有一定的缺陷:

七、適配iPhoneX

iPhoneX的出現將手機的顏值帶上了一個新的高度,它取消了物理按鍵,改成了底部的小黑條,但是這樣的改動給開發者適配移動端又增加了難度。

7.1 安全區域

在 iPhoneX發布後,許多廠商相繼推出了具有邊緣屏幕的手機。

這些手機和普通手機在外觀上無外乎做了三個改動:圓角( corners)、劉海( sensor housing)和小黑條( HomeIndicator)。為了適配這些手機,安全區域這個概念變誕生了:安全區域就是一個不受上面三個效果的可視窗口範圍。

為了保證頁面的顯示效果,我們必須把頁面限制在安全範圍內,但是不影響整體效果。

7.2 viewport-fit

viewport-fit是專門為了適配 iPhoneX而誕生的一個屬性,它用於限制網頁如何在安全區域內進行展示。

contain: 可視窗口完全包含網頁內容

cover:網頁內容完全覆蓋可視窗口

默認情況下或者設置為 auto和 contain效果相同。

7.3 env、constant

我們需要將頂部和底部合理的擺放在安全區域內, iOS11新增了兩個 CSS函數 env、constant,用於設定安全區域與邊界的距離。

函數內部可以是四個常量:

safe-area-inset-left:安全區域距離左邊邊界距離

safe-area-inset-right:安全區域距離右邊邊界距離

safe-area-inset-top:安全區域距離頂部邊界距離

safe-area-inset-bottom:安全區域距離底部邊界距離

注意:我們必須指定 viweport-fit後才能使用這兩個函數:

<metaname="viewport"content="viewport-fit=cover">

constant在 iOS<11.2的版本中生效, env在 iOS>=11.2的版本中生效,這意味著我們往往要同時設置他們,將頁面限制在安全區域內:

body {

padding-bottom: constant(safe-area-inset-bottom);

padding-bottom: env(safe-area-inset-bottom);

}

當使用底部固定導航欄時,我們要為他們設置 padding值:

{

padding-bottom: constant(safe-area-inset-bottom);

padding-bottom: env(safe-area-inset-bottom);

}

八、橫屏適配

很多視口我們要對橫屏和豎屏顯示不同的布局,所以我們需要檢測在不同的場景下給定不同的樣式:

8.1 JavaScript檢測橫屏

window.orientation:獲取屏幕旋轉方向

window.addEventListener("resize", ()=>{

if(window.orientation === 180|| window.orientation === 0) {

// 正常方向或屏幕旋轉180度

console.log('豎屏');

};

if(window.orientation === 90|| window.orientation === -90){

// 屏幕順時鐘旋轉90度或屏幕逆時針旋轉90度

console.log('橫屏');

}

});

8.2 CSS檢測橫屏

@media screen and (orientation: portrait) {

/*豎屏...*/

}

@media screen and (orientation: landscape) {

/*橫屏...*/

}

九、圖片模糊問題9.1 產生原因

我們平時使用的圖片大多數都屬於位圖( png、jpg...),位圖由一個個像素點構成的,每個像素都具有特定的位置和顏色值:

理論上,位圖的每個像素對應在屏幕上使用一個物理像素來渲染,才能達到最佳的顯示效果。

而在 dpr>1的屏幕上,位圖的一個像素可能由多個物理像素來渲染,然而這些物理像素點並不能被準確的分配上對應位圖像素的顏色,只能取近似值,所以相同的圖片在 dpr>1的屏幕上就會模糊:

9.2 解決方案

為了保證圖片質量,我們應該儘可能讓一個屏幕像素來渲染一個圖片像素,所以,針對不同 DPR的屏幕,我們需要展示不同解析度的圖片。

如:在 dpr=2的屏幕上展示兩倍圖 (@2x),在 dpr=3的屏幕上展示三倍圖 (@3x)。

9.3 media查詢

使用 media查詢判斷不同的設備像素比來顯示不同精度的圖片:

.avatar{

background-image: url(conardLi_1x.png);

}

@media only screen and(-webkit-min-device-pixel-ratio:2){

.avatar{

background-image: url(conardLi_2x.png);

}

}

@media only screen and(-webkit-min-device-pixel-ratio:3){

.avatar{

background-image: url(conardLi_3x.png);

}

}

只適用於背景圖

9.4 image-set

使用 image-set:

.avatar {

background-image: -webkit-image-set( "conardLi_1x.png"1x, "conardLi_2x.png"2x);

}

只適用於背景圖

9.5 srcset

使用 img標籤的 srcset屬性,瀏覽器會自動根據像素密度匹配最佳顯示圖片:

<imgsrc="conardLi_1x.png"

srcset=" conardLi_2x.png 2x, conardLi_3x.png 3x">

9.6 JavaScript拼接圖片url

使用 window.devicePixelRatio獲取設備像素比,遍歷所有圖片,替換圖片地址:

const dpr = window.devicePixelRatio;

const images = document.querySelectorAll('img');

images.forEach((img)=>{

img.src.replace(".", `@${dpr}x.`);

})

9.7 使用svg

SVG的全稱是可縮放矢量圖( ScalableVectorGraphics)。不同於位圖的基於像素, SVG 則是屬於對圖像的形狀描述,所以它本質上是文本文件,體積較小,且不管放大多少倍都不會失真。

除了我們手動在代碼中繪製 svg,我們還可以像使用位圖一樣使用 svg圖片:

<img src="conardLi.svg">

<img src="data:image/svg+xml;base64,[data]">

.avatar {

background: url(conardLi.svg);

}

參考

https://99designs.com/blog/tips/ppi-vs-dpi-whats-the-difference/

https://www.w3cplus.com/css/vw-for-layout.html

https://aotu.io/notes/2017/11/27/iphonex/index.html

Web前端學習交流群 

為了讓大家更加即時地溝通學習,我們建了一個Web前端學習交流群,有想入群的同學,可以添加下面小助手微信,他會拉大家入群哈~

相關焦點

  • 網站不支持移動端適配,則會影響谷歌搜索排名
    搜尋引擎老大哥,谷歌最近在海外的站長大會上發布了一條新規,要求在谷歌上收錄的網站要能夠支持移動端適配,即用戶訪問的頁面和根據PC或移動端的情況進行自適應,從用戶體驗的角度體驗的角度出發是對的,而且若PC站點沒有做移動端適配的話,估計將減少收錄,作為關鍵詞排名的因素之一。
  • 谷歌搜索新規:網站必須支持移動端,僅有PC端不予收錄
    谷歌搜索最近在國外的站長大會發布新規,要求以後所有網站必須同步支持適配移動端,僅有PC端網站將不被谷歌搜索收錄,納入排名索引!了解到,在最近舉辦的2020國外站長大會上,谷歌突然在會上針對網站給出了搜索方面的新規定,新規要求:從「2021年3月份之後,所有網站如果只有PC端,網站所有頁面將全部不被谷歌搜索收錄,網站所有頁面和內容必須支持適配移動端,包括文字、數據、圖片、視頻等。在推出」移動端搜索優先排名之後,搜索流量再一次向移動端傾斜。
  • web端字體兼容性適配
    或許是由移動端等終端字體庫引起的差異引起的,或許是由 Modern Browser 或 IE Browser 直接的解析差異引起的,或許是由字體源設計表現引起的,或許是由所設置的通用字體族字符的編碼格式引起的.來一起來探個究竟吧~body {  font-family: -apple-system, system-ui, BlinkMacSystemFont
  • Adobe推出移動端的Pr
    Adobe公司終於開始在移動端發力了,Adobe Max 2018上Adobe正式宣布明年將會發布完整版Photoshop CC適配iPad Pro,並且還推出了一款移動端的視頻剪輯軟體,PremiereRush CC。
  • 微信授權登錄、適配ipad橫屏,向日葵iOS控制端9.8.6更新升級!
    微信授權登錄、適配ipad橫屏,向日葵iOS控制端9.8.6更新升級! 近日,知名遠程控制品牌向日葵,更新升級了向日葵遠程控制iOS控制端,統一明亮主題UI界面,支持掃碼登錄PC端和微信授權登錄APP,iOS版控制端還適配iPad橫屏,支持跨平臺、跨系統複製粘貼文字等功能,為向日葵iOS主控端用戶帶來新體驗。
  • 「eBay海淘」推出移動端服務
    而在這當中,移動端購物以68.2%的交易比例,攀升成為中國電商的主要消費場景。   面向日益成熟化的海淘市場和消費族群,電商平臺能否提供個性化、本土化、便捷化的購物體驗,是贏得消費者的關鍵。近年來,eBay 見證了中國消費者對進口優質電子產品、時尚和生活用品不斷增長的需求。新上線的「eBay海淘」移動端,是eBay不斷完善並提升消費者從選購、支付到售後的完整購物流程體驗的一次新嘗試。
  • 一招教你輕鬆搞定!
    一招教你輕鬆搞定!淘寶產品詳情頁通常是針對店鋪裝修來說的。對於顧客來說產品詳情頁就是,在店鋪看見一個產品點擊進去的裡面就是寶貝詳情頁面,頁面裡有產品的大圖和產品的詳細介紹。一招教你輕鬆搞定!淘寶商品詳情頁在哪裡設置?步驟是什麼?一招教你輕鬆搞定!
  • 雲適配陳本峰詳解開源HTML5框架Amaze UI
    根據Amaze UI的官網介紹,該框架的特點是mobilefirst,解決Web應用從PC向多屏適配的問題,兼容國內主流瀏覽器和平臺,並且專註解決中文排版優化問題。  InfoQ中文站跟雲適配CEO陳本峰,前微軟美國總部IE瀏覽器核心工程師,進行了交流,了解有關Amaze UI框架的更多細節。
  • 移動端網站設計:它是什麼及其重要性
    除非您最近幾年一直呆在家裡,否則您將知道移動端網站設計已成為許多企業的關鍵任務。還是只是移動端網站的更新? 你甚至需要擔心嗎?---成都雲思禾網絡運營 浪知潮團隊多年來一直在設計適合行動裝置訪問的網站,我們很高興分享對移動所有事物的見解。讓我們從基礎開始:移動設計和常規Web設計有什麼區別,它對您的業務有何影響? 什麼是移動端網站設計?
  • Adobe 移動端一籮筐 APP 究竟有何卵用?
    好了,開始說正經的,Adobe 在不斷完善電腦端設計軟體的操作體驗的同時也沒忘記在移動端「折騰」一下,iOS 與 Android 兩個平臺(隔壁 Windows phone 哭暈在廁所)都開發了與桌面設計軟體相對應的
  • 雲適配籤約三花控股 助力中國「質」造騰飛
    ,雲適配為三花控股構建的移動工作平臺已於近日成功上線,在滿足員工隨時隨地辦公需求的同時,也有效提升了三花控股的整體運營管控效率,從而實現業務協作的「新常態」。雲適配移動信息化解決方案以自主創新的統一移動工作平臺Enterplorer作為三花控股的移動端統一工作平臺和入口,通過採用「API零依賴、業務系統零改動、移動開發零風險」的前端適配技術,先對三花控股目前使用頻率較高的PC端CRM系統進行移動化改造,同時進一步將製造企業「深水區」業務系統如MES等遷移到Enterplorer移動平臺,從而快速實現移動化辦公。
  • Apple Watch首批適配應用曝光 QQ音樂入駐
    作為全球首批入駐AppleWatch的應用,QQ音樂率先適配AppleWatch,音樂達人們即使將手機放在口袋裡也可以隨時隨地掌握最新音樂動態。準確識別,輕鬆播放,帶上耳機,就是這麼簡單!有目共睹,iPhone越來越需要我們的注意力(推送越來越多),這會給我們帶來越來越多的分心。
  • 劍網3雲遊戲首次測試開放 移動端瀏覽器雲遊戲2020實現
    除了PC雲端,在2020年裡劍網3雲遊戲還將陸續開放12M左右的移動版客戶端以及瀏覽器端試玩。據官方透露,劍網3已經在移動端交互上深度展開近300個核心大類界面的梳理改造,百餘界面操作完全重製,使交互操作完全適配行動裝置以實現產品在不同平臺的跨端體驗,滿足遊戲玩家對於遊戲便捷性的需求。劍網3作為國產武俠十年經典IP,曾以獨特的輕功玩法等諸多創新引發廣泛關注。
  • 輕鬆搞定form表單,不再為表單煩惱
    大家好,我是為廣大程式設計師兄弟操碎了心的小編,每天推薦一個小工具/源碼,裝滿你的收藏夾,每天分享一個小技巧,讓你輕鬆節省開發效率
  • 《妙先生》《怪物先生》等多部熱映大片適配愛奇藝TV端家庭影院級...
    在製作方面,《妙先生》的水墨畫風盡顯東方美學,特效場景數量是一般動畫的兩倍以上,為此愛奇藝為《妙先生》獨家適配了TV端家庭影院級音畫標準「幀綺映畫」,讓星鑽VIP會員在家就能盡享4K MAX+超高幀率+HDR+全景聲四重升級所帶來的影院級視頻體驗。除了《妙先生》以外,近期熱播的《徵途》、即將上線的《怪物先生》等院線大片也已適配「幀綺映畫」。
  • 網站PC端跟移動端有哪些不同的區別所在?
    移動時代的來臨,不斷的發展手機、平板等移動端設備,幫助用戶更快更高效的找到有價值的信息,移動端也確實能吸引更大的流量,助力企業高速發展。那麼針對PC端網站和移動端的優化又有哪些區別呢?下面一起來了解一下。 一、點擊率的不同 由於移動端設備獲得更多人們的喜愛,以及使用的普及型,從而移動端網站的點擊率也是遠超PC端的,可見目前的移動端設備也能更好的給用戶提供信息,獲得用戶們的喜愛和認可。
  • 只用微波爐就搞定!節假日在家輕鬆端出7道手作甜點
    導讀:只用微波爐就搞定!節假日在家輕鬆端出7道手作甜點節假日不一定要上高級餐廳,來一份手作甜點,也能讓對方感受到滿滿的心意。今天就別再找藉口了,無論你是平常沒有在下廚烘焙的人,或者煩惱於家裡沒有專業的烤箱,還是忙到沒時間的上班族,都能用微波爐輕鬆做甜點!免烤箱!
  • 網際網路時代線上應用究竟布局在PC端還是移動端
    是布局在PC端還是微信端、小程序、還是APP客戶端。移動網際網路是新世紀全球發展的大趨勢,我堅持認為未來的網際網路是移動終端的世界。任何網際網路產品的推出都必須堅守移動網際網路終端開發這個宗旨原則。下面我從以下幾方面分享我個人的見解。
  • Zen3登陸移動端!AMD移動端首度支持超頻!頂級筆記本處理器登場
    銳龍5000H系列已確定有四款型號,頂級的是銳龍9 5900HX,AMD歷史上第一款可超頻的移動處理器,默認頻率也高達3.3-4.6GHz,對比銳龍9 4900H就是頻率高了200MHz,同時繼續集成Vega 8 GPU,但頻率不詳,熱設計功耗也不知道是否會突破45W。
  • 自帶插頭和轉接頭的移動電源,告別繁瑣,出行充電「一粒」搞定
    / 大容量快充,速度x3作為移動電源,它身材小巧卻有7500mAh大容量。在滿電情況下,可幫手機「滿血」2次以上,完全滿足日常需求。無論居家還是旅行,解放雙手,輕鬆煲劇!/ 可上飛機,價格親民符合航空管理標準,無需託運,直接上飛機。