這篇文章將為大家詳細(xì)講解有關(guān)如何實(shí)現(xiàn)基于rem的移動(dòng)端響應(yīng)式適配方案,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
目前創(chuàng)新互聯(lián)公司已為上千多家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)絡(luò)空間、網(wǎng)站改版維護(hù)、企業(yè)網(wǎng)站設(shè)計(jì)、前進(jìn)網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
視口
在前一段時(shí)間,我曾經(jīng)寫過一篇關(guān)于viewport的文章。最近由于在接觸移動(dòng)端開發(fā),對(duì)viewport有了新的理解。于是,打算重新寫一篇文章,介紹移動(dòng)端視口的相關(guān)概念。
關(guān)于這篇文章說到的所有知識(shí),本質(zhì)上離不開以下代碼
@media all and (max-width: 320px) { // do something }
了解過移動(dòng)端開發(fā)的朋友,其實(shí)對(duì)以上的代碼就不會(huì)陌生。上面的代碼,主要涉及到meta視口標(biāo)簽與媒體查詢。單單以上簡短的代碼就需要明白:
像素(pixel)
視口(viewport)
分辨率(resolution)
meta視口標(biāo)簽
媒體查詢(media query)
JavaScript相關(guān)的屬性和方法
如何實(shí)現(xiàn)移動(dòng)端響應(yīng)式適配的問題
那就進(jìn)入主題吧:)
像素
在移動(dòng)端上,所謂的像素分為兩種
CSS像素:CSS像素就是我們?cè)诰帉慍SS代碼時(shí)的像素。
設(shè)備像素:設(shè)備屏幕的物理像素,任何設(shè)備的物理像素的數(shù)量都是固定的。
1個(gè)CSS像素等于多少個(gè)設(shè)備像素取決于屏幕特性(是否是高清屏)和用戶縮放的比例。當(dāng)用戶將屏幕從100%放大到200%時(shí),1個(gè)CSS像素等于2個(gè)設(shè)備像素,反之相反;當(dāng)屏幕為Retina高清屏(如iPhone6,dpr=2)時(shí),1個(gè)CSS像素就等于2個(gè)設(shè)備像素,反之相反。
需要明白一點(diǎn)的是,2個(gè)設(shè)備像素并不是說它擴(kuò)大了兩倍,而是說在頁面上仍然顯示的是1px(1個(gè)CSS像素),但是這1px是由2個(gè)設(shè)備像素組成。像素點(diǎn)變多了,因此圖像會(huì)變得更加清晰。下面這幅圖大致說明了CSS像素和設(shè)備像素的區(qū)別。
視口
在移動(dòng)端上,存在三種不同的視口。
布局視口:在PC端上,布局視口等于瀏覽器窗口的寬度。而在移動(dòng)端上,由于要使為PC端瀏覽器設(shè)計(jì)的網(wǎng)站能夠完全顯示在移動(dòng)端的小屏幕里,此時(shí)的布局視口會(huì)遠(yuǎn)大于移動(dòng)設(shè)備的屏幕。在移動(dòng)端,默認(rèn)情況下,布局視口等于瀏覽器窗口寬度。布局視口限制了CSS的布局。在JavaScirpt上獲取布局視口的寬度可以通過document.documentElement.clientWidth | document.body.clientWidth得到。
視覺視口:視覺視口是用戶正在看到的區(qū)域。用戶可以縮放來操作視覺視口,而不影響視覺視口的寬度。視覺視口決定了用戶看到了什么。在JavaScript上獲取視覺視口的寬度可以通過`window.innerWidth得到。
在PC端上,視覺視口等于布局視口的寬度,無論用戶是放大屏幕還是縮小屏幕,這兩個(gè)視口的寬度仍然相等。但是,在移動(dòng)端上,并非如此??s放屏幕的過程實(shí)質(zhì)上就是CSS像素縮放的過程。當(dāng)用戶將屏幕放到到兩倍時(shí),視覺視口變小了(因?yàn)橐曈X視口中CSS像素變少了),而每單位的CSS像素卻變大了,因此1px(1個(gè)CSS像素)等于2個(gè)設(shè)備像素。同理,當(dāng)為iPhone6(dpr=2)時(shí),視覺視口中CSS像素變少了,但是1px等于2個(gè)設(shè)備像素。當(dāng)用戶縮小屏幕時(shí)也是同樣的道理??s放的過程并不會(huì)影響布局視口的大小。
也就是說,高清屏(dpr>=2)或屏幕放大時(shí),視覺視口變小(CSS像素變少),每單位的CSS像素等于更多的設(shè)備像素;非高清屏(dpr<2)
或屏幕縮小時(shí),視覺視口變大(CSS像素變多),每單位的CSS像素等于更少的設(shè)備像素。
但是無論放大或縮小屏幕,布局視口的寬度仍然保持不變。
理想視口:由于默認(rèn)情況下布局視口等于瀏覽器窗口寬度,因此在移動(dòng)端上需要通過放大或縮小視覺視口來查看頁面內(nèi)容,這當(dāng)然體驗(yàn)糟糕?。∫虼嗽谝苿?dòng)端引入了理想視口的概念。理想視口的出現(xiàn)必須需要設(shè)置meta視口標(biāo)簽,此時(shí)布局視口等于理想視口的寬度。常見的,iPhone6的理想視口為375px * 667px,iPhon6 plus的理想視口為414px * 736px。在JavaScript上獲取視覺視口的寬度window.screen.width得到。
當(dāng)設(shè)置了meta視口標(biāo)簽之后,iPhone6的布局視口寬度將等于375px,iPhone6plus布局視口的寬度等于414px。其他移動(dòng)設(shè)備相似。
理想視口會(huì)隨著屏幕的旋轉(zhuǎn)而改變。當(dāng)iPhone6為肖像模式時(shí)(即豎屏),此時(shí)理想視口為375px * 667px;但為橫屏模式時(shí),此時(shí)理想視口為667px * 375px。
分辨率與設(shè)備像素比
分辨率是指每英寸內(nèi)點(diǎn)的個(gè)數(shù),單位是dpi或者dppx。設(shè)備像素比是指設(shè)備像素與理想視口寬度的比值,沒有單位。
分辨率在CSS上可以通過resolution屬性設(shè)置。一般情況下會(huì)使用dpi作為分辨率的單位,因?yàn)閐ppx并非所有瀏覽器都支持。
而設(shè)備像素比在CSS上可以通過device-device-pixel-ratio屬性設(shè)置,而在JavaScript上可以通過window.devicePixelRatio屬性獲取。
同時(shí),1dpr=96dpi。舉個(gè)例子。在iPhon6下,理想視口寬度為375px,而設(shè)備像素為750px,因此此時(shí)設(shè)備像素比為2,分辨率為192dpi。因此如果為iPhon6以下的設(shè)備寫某個(gè)特定樣式,可以這樣寫
// 注意,device-pixel-ratio需要帶上-webkit-前綴,保證瀏覽器兼容性問題。 @media all and (max-width: 375px) and (-webkit-max-device-pixel-ratio: 2) { body { background-color: red; } } 或者 @media all and (max-width: 375px) and (max-resolution: 192dpi) { body { background-color: red; } }
meta視口標(biāo)簽
meta視口標(biāo)簽是是設(shè)置理想視口的重要元素,主要用于將布局視口的尺寸和理想視口的尺寸相匹配。meta視口標(biāo)簽存在5個(gè)指令
width:設(shè)置布局視口的寬度,一般設(shè)為device-width。
initial-scale:初始縮放比例。1即100%,2即200%,以此類推
maximum=scale:最大縮放比例。
minimum-scale:最小縮放比例。
user-scalable:是否靜止用戶進(jìn)行縮放,默認(rèn)為no。
需要注意的是,縮放是根據(jù)理想視口進(jìn)行計(jì)算的。縮放程度與視覺視口的寬度是逆相關(guān)的。也就是說,當(dāng)你將屏幕放到到2倍時(shí),視覺視口為理想視口的一半,此時(shí)每單位的CSS像素等于2個(gè)設(shè)備像素??s小時(shí)則相反。
響應(yīng)式適配問題
理解了一些基本概念之后,我們來看看如何實(shí)現(xiàn)響應(yīng)式適配。
一般情況下,前端開發(fā)工程師會(huì)根據(jù)設(shè)計(jì)師給的設(shè)計(jì)稿進(jìn)行開發(fā)。而設(shè)計(jì)稿一般是根據(jù)iPhon6手機(jī)進(jìn)行頁面的設(shè)計(jì)的。我們知道iPhone6的理想視口寬度為375px,同時(shí)iPhone6的設(shè)備像素比為2,設(shè)備像素為750px。我們需要在只有一份設(shè)計(jì)稿的情況下寫出適應(yīng)各種屏幕不一的終端設(shè)備,因此需要一些移動(dòng)端響應(yīng)式適配的方案。此時(shí)需要用到的一個(gè)單位是REM。簡單的說,REM會(huì)根據(jù)HTML元素的font-size進(jìn)行設(shè)置。當(dāng)HTML元素的font-size: 16px時(shí),1rem = 16px, 1.5rem = 24px
個(gè)人總結(jié)出了兩套響應(yīng)式適配的方案(前提是設(shè)置meta視口標(biāo)簽)。兩套方案由一個(gè)共同點(diǎn):給定一個(gè)基準(zhǔn)值。
假如現(xiàn)在拿到的設(shè)計(jì)稿是根據(jù)iPhone6進(jìn)行設(shè)計(jì)的。
方案一
方案一是設(shè)計(jì)稿給什么尺寸,我們就將其縮小100倍,最后換算成rem單位。比如,設(shè)計(jì)稿上某個(gè)title的font-size為32px,此時(shí)寫CSS樣式時(shí)就直接縮小100倍,即0.32rem。
由于rem是根據(jù)根元素進(jìn)行設(shè)置的,所以我們需要設(shè)置根元素的font-size。
給HTML設(shè)置font-size的基本思路:
通過window.screen.width獲取不同移動(dòng)設(shè)備的理想視口寬度。
規(guī)定基準(zhǔn)值為750px(此值為iPhon6的設(shè)備像素)。
(1) / (2) * 100即得到HTML元素的font-size。(乘于100是因?yàn)槲覀冊(cè)谇懊鎸⒆煮w縮小了100倍,此時(shí)要乘回來)
換算成公式即:設(shè)計(jì)稿尺寸 / 100 * (不同設(shè)備的理想視口寬度 / 基準(zhǔn)值 * 100)
舉個(gè)例子。
// 根據(jù)不同設(shè)備的理想視口寬度動(dòng)態(tài)設(shè)置根元素的`font-size`。 let idealViewWidth = window.screen.width; const BASICVALUE = 750; document.documentElement.style.fontSize = (idealViewWidth / BASICVALUE) * 100 + 'px';
因此,在不同設(shè)備下的HTML元素的font-size大小和實(shí)際像素如下
iPhone5 : (320 / 750) * 100 = 42.667px iPhone6 : (375 / 750) * 100 = 50px iPhone6+: (414 / 750) * 100 = 55.2px 假如設(shè)計(jì)稿上標(biāo)注.title類上的字體為32px,此時(shí)有 iPhone5上的某字體: 42.667 * 0.32rem = 13.653px iPhone6上的某字體: 50 * 0.32rem = 16px iPhone6+上的某字體: 55.2 * 0.32rem = 17.664px
可以看出,在不同設(shè)備下,同一字號(hào)的字體使用rem單位可以實(shí)現(xiàn)不同設(shè)備的響應(yīng)式適配。不單單在字體上可以使用,在移動(dòng)端上的width、height等涉及單位的都可以使用。這樣的話,就可以在不同設(shè)備下完美的復(fù)現(xiàn)設(shè)計(jì)稿的要求。
方案二
此方案使用了SASS預(yù)處理器?;舅悸罚?/p>
設(shè)置根元素的font-size。通過獲取不同設(shè)備的理想視口寬度,再除以10。(除以10是因?yàn)椴幌雈ont-size太大。)
給定基準(zhǔn)值,此時(shí)給的基準(zhǔn)值為75px(此值為iPhone6的設(shè)備像素除以10)
寫SASS Function
代碼如下
SASS @function px2rem ($value) { $para: 75px; @return $value / $para + rem; } JS let idealViewWidth = window.screen.width; document.documentElement.style.fontSize = idealViewWidth / 10 + 'px'; 在不同設(shè)備下根元素的`font-size`: iPhone5 : 320px / 10 = 32px iPhone6 : 375px / 10 = 37.5px iPhone6+: 414px / 10 = 41.4px 根據(jù)以上,可以看一個(gè)例子。某設(shè)計(jì)稿下5個(gè)li,橫向排布,每個(gè)的寬度為200px CSS @import (路徑名) iPhone5: li { width: px2rem(200px) } => width: 85.333px // 此時(shí)(200px / 75px = 2.667rem) 2.667rem = 2.667 * (320 / 10) = 85.3333px iPhone6: li { width: px2rem(200px) } => width: 100px // 此時(shí)(200px / 75px = 2.667rem) 2.667rem = 2.667 * (375 / 10) = 100px iPhone6+: li { width: px2rem(200px) } => width: 4138px // 此時(shí)(200px / 75px = 2.667rem) 2.667rem = 2.667 * (414 / 10) = 110.4138px 因此,一個(gè)200px的(實(shí)際只有100px)的li元素的寬度在不同設(shè)備下顯示了不同的寬度,實(shí)現(xiàn)了響應(yīng)式適配的問題。
方案三
方案三與前兩個(gè)方案不相同,此方案并不需要給根元素設(shè)置font-size,不需要基準(zhǔn)值。此方案是根據(jù)不同設(shè)備的dpr來實(shí)現(xiàn)頁面的縮放的。
基本思路如下:
通過window.devicePixelRatio獲取設(shè)備的dpr
根據(jù)不同的dpr縮放頁面,動(dòng)態(tài)設(shè)置meta視口標(biāo)簽。(縮放是放大或縮小CSS的過程,根據(jù)理想視口進(jìn)行縮放,與視覺視口方向相反)
代碼如下:
let dpr = window.devicePixelRatio; let meta = document.createElement('meta'); let initialScale = 1 / dpr; let maximumScale = 1 / dpr; let minimumScale = 1 / dpr; meta.setAttribute('name', 'viewport'); meta.setAttribute('content', `width=device-width, user-scalable=no, initial-scale=${initialScale}, maximum-scale=${maximumScale}, minimum-scale=${minimumScale}`); document.head.appendChild(meta); 因此,可以直接根據(jù)設(shè)計(jì)稿的尺寸寫CSS樣式,如設(shè)計(jì)稿下有5個(gè)li元素,寬度為200px,此時(shí)不同設(shè)備下li的寬度 iPhone5 : li { width: 200px } 實(shí)際寬度為:100px iPhone6 : li { width: 200px } 實(shí)際寬度為:100px iPhone6+: li { width: 200px } 實(shí)際寬度為:66.667px
關(guān)于“如何實(shí)現(xiàn)基于rem的移動(dòng)端響應(yīng)式適配方案”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。