日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

移动端适配 - 小结

發(fā)布時(shí)間:2024/3/13 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 移动端适配 - 小结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在前端的世界里,移動(dòng)終端和 PC 的響應(yīng)式適配是我們常見的適配,在適配的過程中有些都可以起作用,有些有不同,經(jīng)過不斷地實(shí)踐總結(jié),我想總結(jié)一下。

1. 視口 viewport

1.1 viewport 基礎(chǔ)

viewport 解釋為中文就是‘視口’的意思,也就是瀏覽器中用于顯示網(wǎng)頁的區(qū)域。在 PC 端,其大小也就是瀏覽器可視區(qū)域的大小,所以我們也不會(huì)太關(guān)注此概念;而在移動(dòng)端,絕大多數(shù)情況下 viewport 都大于瀏覽器可視區(qū),保證 PC 頁面在移動(dòng)瀏覽器上面的可視性。為提升可視性體驗(yàn),針對(duì)移動(dòng)端有了對(duì) viewport 的深入研究。

1.2 viewport 詳解

在移動(dòng)端有三種類型的 viewport: layoutviewport、visualviewport、idealviewport。具體解釋如下:

  • layoutviewport: 大于實(shí)際屏幕, 元素的寬度繼承于 layoutviewport,用于保證網(wǎng)站的外觀特性與桌面瀏覽器一樣。layoutviewport 到底多寬,每個(gè)瀏覽器不同。iPhone 的 safari 為 980px,通過 document.document.clientWidth 獲取。
  • visualviewport: 當(dāng)前顯示在屏幕上的頁面,即瀏覽器可視區(qū)域的寬度。
  • idealviewport: 為瀏覽器定義的可完美適配移動(dòng)端的理想 viewport,固定不變,可以認(rèn)為是設(shè)備視口寬度。比如 iphone 7 為 375px, iphone 7p 為 414px。

1.3 viewport 設(shè)置

我們通過對(duì)幾種 viewport 設(shè)置可以對(duì)網(wǎng)頁的展示進(jìn)行有效的控制,在移動(dòng)端我們經(jīng)常會(huì)在 head 標(biāo)簽中看到這段代碼:

<meta name='viewport' content='width=device-width,initial-scale=1,user-scale=no' />

通過對(duì) meta 標(biāo)簽三個(gè) viewport 的設(shè)置,最終使頁面完美展示。下面詳細(xì)的闡釋其具體含義:

  • width 設(shè)置的是 layoutviewport 的寬度
  • initial-scale 設(shè)置頁面的初始縮放值,并且這個(gè)初始縮放值是相對(duì)于 idealviewport 縮放的,最終得到的結(jié)果不僅會(huì)決定 visualviewport,還會(huì)影響到 layoutviewport
  • user-scalable 是否允許用戶進(jìn)行縮放的設(shè)置

對(duì)上面的說明通過公式推導(dǎo)進(jìn)行進(jìn)一步的解釋:

// 設(shè)定兩個(gè)變量: viewport_1 = width; viewport_2 = idealviewport / initial-scale;// 則: layoutviewport = max{viewport_1, viewport_2}; visualviewport = viewport_2;

結(jié)合上面對(duì)不同 viewport 分析補(bǔ)充如下兩個(gè)結(jié)論:

  • 若 layoutviewport === idealviewport && visualviewport === idealviewport,則三個(gè)值一致時(shí),頁面會(huì)完美展示。
  • 若 layoutviewport === visualviewport 且它們不等于 visualviewport,頁面下面不會(huì)出現(xiàn)滾動(dòng)條,瀏覽器默認(rèn)只是把頁面放大或縮小。
  • 1.4 viewport 舉例

    以下是通過改變 meta viewport 的幾個(gè)參數(shù)的值來算取不同的 viewport:

    widthinitial-scalelayoutviewportvisualviewportidealviewport是否滾動(dòng)
    --980px980px375px
    device-width1375px375px375px
    device-width2375px188px375px
    device-width0.5750px750px375px
    480px1480px375px375px
    480px2480px188px375px
    480px0.5750px750px375px

    以上是針對(duì) iphone 6/7/8 的測(cè)試數(shù)據(jù),且無論怎么設(shè)置 viewport 都具有臨界值,即:75 <= layoutviewport <= 10000,75 <= visualviewport <= 1500。

    1.5 為什么要設(shè)置 viewport

    viewport 的設(shè)置不會(huì)對(duì) PC 頁面產(chǎn)生影響,但對(duì)于移動(dòng)頁面卻很重要。下面我們舉例來說明:

  • 媒體查詢 @media 響應(yīng)式布局中,會(huì)根據(jù)媒體查詢功能來適配多端布局,必須對(duì) viewport 進(jìn)行設(shè)置,否則根據(jù)查詢到的尺寸無法正確匹配視覺寬度而導(dǎo)致布局混亂。如不設(shè)置 viewport 參數(shù),多說移動(dòng)端媒體查詢的結(jié)果將是 980px 這個(gè)節(jié)點(diǎn)布局的參數(shù),而非我們通常設(shè)置的 768px 范圍內(nèi)的這個(gè)布局參數(shù)
  • 由于目前多數(shù)手機(jī)的 dpr 都不再是 1,為了產(chǎn)出高保真頁面,我們一般會(huì)給出 750px 的設(shè)計(jì)稿,那么就需要通過設(shè)置 viewport 的參數(shù)來進(jìn)行整體換算,而不是在每次設(shè)置尺寸時(shí)進(jìn)行長度的換算。
  • 2. 設(shè)備像素比 dpr 與 1px 物理像素

    2.1 物理像素(physical pixel)

    手機(jī)屏幕上顯示的最小單元,該最小單元具有顏色及亮度的屬性可供設(shè)置,iphone6、7、8 為:750 * 1334,iphone6+、7+、8+ 為 1242 * 2208

    2.2 設(shè)備獨(dú)立像素(density-indenpendent pixel)

    此為邏輯像素,計(jì)算機(jī)設(shè)備中的一個(gè)點(diǎn),css 中設(shè)置的像素指的就是該像素。老早在沒有 retina 屏之前,設(shè)備獨(dú)立像素與物理像素是相等的。

    2.3 設(shè)備像素比(device pixel ratio)

    設(shè)備像素比(dpr) = 物理像素/設(shè)備獨(dú)立像素。如 iphone 6、7、8 的 dpr 為 2,那么一個(gè)設(shè)備獨(dú)立像素便為 4 個(gè)物理像素,因此在 css 上設(shè)置的 1px 在其屏幕上占據(jù)的是 2個(gè)物理像素,0.5px 對(duì)應(yīng)的才是其所能展示的最小單位。這就是 1px 在 retina 屏上變粗的原因,目前有很多辦法來解決這一問題。

    ?

    ?

    ?

    2.4 1px的物理像素的解決方案

    從第一部分的討論可知 viewport 的 initial-scale 具有縮放頁面的效果。對(duì)于 dpr=2 的屏幕,1px壓縮一半便可與1px的設(shè)備像素比匹配,這就可以通過將縮放比 initial-scale 設(shè)置為 0.5=1/2 而實(shí)現(xiàn)。以此類推 dpr=3的屏幕可以將 initial-scale設(shè)置為 0.33=1/3 來實(shí)現(xiàn)。

    3. 設(shè)備像素比 dpr 與 rem 的適配方案

    結(jié)合 2、3 部分可以實(shí)現(xiàn) 1px 的物理像素這一最小屏幕單位,那在此基礎(chǔ)上如可讓設(shè)計(jì)通常提供的 750px 設(shè)計(jì)稿來完美的適配到多種機(jī)型上,使用 rem 是一種解決方式。

    3.1 rem 如何設(shè)置

    rem 是相對(duì)于根元素 html 的 font-size 來做計(jì)算。通常在頁面初始化時(shí)加載時(shí)通過對(duì)document.documentElement.style.fontSize 設(shè)置來實(shí)現(xiàn)。

    3.2 rem 適配規(guī)則

    通過對(duì) initial-scale = 1/dpr 的設(shè)置,已將對(duì)屏幕的描述從物理像素轉(zhuǎn)化到了物理像素上了,這將是后續(xù)推導(dǎo)的基礎(chǔ),且設(shè)計(jì)稿為 750px。

  • 物理像素為 750 = 375 * 2,若屏幕等分為 10 份,那么 1rem = 75px,10rem = 750px;
  • 物理像素為 1125 = 375 * 3,若屏幕等分為 10 份,那么 1rem = 112.5px, 10rem = 1125px;
  • 物理像素為 1242 = 414 * 3, 若屏幕等分為 10 份,那么 1rem = 124.2px, 10rem = 1242px;
  • 因此可推導(dǎo)出 rem 的設(shè)定方式:

    document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';

    下面我們將 750px 下,1rem 代表的像素值用 baseFont 表示,則在 baseFont = 75 的情況下,是分成 10 等份的。因此可以將上面的公式通用話一些:

    document.documentElement.style.fontSize = document.documentElement.clientWidth / ( 750 / 75 ) + 'px';

    整體設(shè)置可參考如下代碼:

    (function (baseFontSize) {const _baseFontSize = baseFontSize || 75;const ua = navigator.userAgent;const matches = ua.match(/Android[\S\s]+AppleWebkit\/(\d{3})/i);const isIos = navigator.appVersion.match(/(iphone|ipad|ipod)/gi);const dpr = window.devicePixelRatio || 1;if (!isIos && !(matches && matches[1] > 534)) {// 如果非iOS, 非Android4.3以上, dpr設(shè)為1;dpr = 1;}const scale = 1 / dpr;const metaEl = document.querySelector('meta[name="viewport"]');if (!metaEl) {metaEl = document.createElement('meta');metaEl.setAttribute('name', 'viewport');window.document.head.appendChild(metaEl);}metaEl.setAttribute('content', 'width=device-width,user-scalable=no,initial-scale=' + scale + ',maximum-scale=' + scale + ',minimum-scale=' + scale);document.documentElement.style.fontSize = document.documentElement.clientWidth / (750 / _baseFontSize) + 'px'; })();

    同時(shí)為了書寫方便可以直接通過 px 布局,然后在打包時(shí)利用 pxtorem 庫轉(zhuǎn)化為基于 rem 的布局。

    4. 視口單位適配方案

    將視口寬度 window.innerWidth 和視口高度 window.innerHeight 等分為 100 份,且將這里的視口理解成 idealviewport 更為貼切,并不會(huì)隨著 viewport 的不同設(shè)置而改變。

    • vw : 1vw 為視口寬度的 1%
    • vh : 1vh 為視口高度的 1%
    • vmin : vw 和 vh 中的較小值
    • vmax : 選取 vw 和 vh 中的較大值

    如果設(shè)計(jì)稿為 750px,那么 1vw = 7.5px,100vw = 750px。其實(shí)設(shè)計(jì)稿按照設(shè)么都沒多大關(guān)系,最終轉(zhuǎn)化過來的都是相對(duì)單位,上面講的 rem 也是對(duì)它的模擬。這里的比例關(guān)系也推薦不要自己換算,使用 pxtoviewport 的庫就可以幫我們轉(zhuǎn)換。當(dāng)然每種方案都會(huì)有其弊端,這里就不展開討論。

    5. iphoneX的適配

    倍圖其實(shí)就是像素尺寸和開發(fā)尺寸的倍率關(guān)系,但這只是外在的表現(xiàn)。倍圖核心的影響因素在于PPI(DPI),了解屏幕密度與各尺寸的關(guān)系有助于我們深度理解倍率的概念:《基礎(chǔ)知識(shí)學(xué)起來!為設(shè)計(jì)師量身打造的DPI指南》

    iPhone8在本次升級(jí)中,屏幕尺寸和分辨率都遺傳了iPhone6以后的優(yōu)良傳統(tǒng);

    然而iPhone X 無論是在屏幕尺寸、分辨率、甚至是形狀上都發(fā)生了較大的改變,下面以iPhone 8作為參照物,看看到底iPhone X的適配我們要怎么考慮。

    我們看看iPhone X尺寸上的變化:

    5.1. ?iPhoneX的適配---安全區(qū)域(safe area)

    蘋果對(duì)于 iPhone X 的設(shè)計(jì)布局意見如下:

    ?

    核心內(nèi)容應(yīng)該處于 Safe area 確保不會(huì)被設(shè)備圓角(corners),傳感器外殼(sensor housing,齊劉海) 以及底部的 Home Indicator 遮擋。也就是說 我們?cè)O(shè)計(jì)顯示的內(nèi)容應(yīng)該盡可能的在安全區(qū)域內(nèi);

    5.3. ?iPhoneX的適配---適配方案viewport-fit

    ? ? 5.3.1 ?PhoneX的適配,在iOS 11中采用了viewport-fit的meta標(biāo)簽作為適配方案;viewport-fit的默認(rèn)值是auto。

      ? viewport-fit取值如下:

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? auto默認(rèn):viewprot-fit:contain;頁面內(nèi)容顯示在safe area內(nèi)
    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? coverviewport-fit:cover,頁面內(nèi)容充滿屏幕

      ? ? viewport-fit meta標(biāo)簽設(shè)置(cover時(shí))

    <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"> ?

    ? ? 5.3.2 ?css constant()函數(shù) 與safe-area-inset-top &?safe-area-inset-left &?safe-area-inset-right &?safe-area-inset-bottom的介紹

    ?

    ?

    ?

    ? ?如上圖所示 在iOS 11中的WebKit包含了一個(gè)新的CSS函數(shù)constant(),以及一組四個(gè)預(yù)定義的常量:safe-area-inset-left,?safe-area-inset-right,?safe-area-inset-top和?safe-area-inset-bottom。當(dāng)合并一起使用時(shí),允許樣式引用每個(gè)方面的安全區(qū)域的大小。

    ? ? 5.3.1當(dāng)我們?cè)O(shè)置viewport-fit:contain,也就是默認(rèn)的時(shí)候時(shí);設(shè)置safe-area-inset-left,?safe-area-inset-right,?safe-area-inset-top和?safe-area-inset-bottom等參數(shù)時(shí)不起作用的。

    ? ? 5.3.2當(dāng)我們?cè)O(shè)置viewport-fit:cover時(shí):設(shè)置如下

    body {padding-top: constant(safe-area-inset-top); //為導(dǎo)航欄+狀態(tài)欄的高度 88px padding-left: constant(safe-area-inset-left); //如果未豎屏?xí)r為0 padding-right: constant(safe-area-inset-right); //如果未豎屏?xí)r為0 padding-bottom: constant(safe-area-inset-bottom);//為底下圓弧的高度 34px }

    ?

    ?

    5.4. ? iPhoneX的適配---高度統(tǒng)計(jì)

    ? ? viewport-fit:cover + 導(dǎo)航欄

      

    ?

    5.5.iPhoneX的適配---媒體查詢

    注意這里采用的是690px(safe area高度),不是812px;

    @media only?screen?and (width:?375px) and (height:?690px){body {background:?blue;}}

    5.6.iphoneX viewport-fit ?問題總結(jié)


    1.關(guān)于iphoneX 頁面使用了漸變色時(shí);如果viewport-fit:cover;

    ????1.1在設(shè)置了背景色單色和漸變色的區(qū)別,如果是單色時(shí)會(huì)填充整個(gè)屏幕,如果設(shè)置了漸變色 那么只會(huì)更加子元素的高度去渲染;而且頁面的高度只有690px高度,上面使用了padding-top:88px;

      

    body固定為:

    <body><div?class="content">this is subElement</div></body>

    1.單色時(shí):

    * {padding: 0;margin: 0; } body {background:green;padding-top: constant(safe-area-inset-top); //88px /*padding-left: constant(safe-area-inset-left);*/ /*padding-right: constant(safe-area-inset-right);*/ /*padding-bottom: constant(safe-area-inset-bottom);*/ }

    ?

    2.漸變色

    * {padding: 0;margin: 0;}body {background:-webkit-gradient(linear, 0 0, 0 bottom, from(#ffd54f), to(#ffaa22));padding-top: constant(safe-area-inset-top); //88px/*padding-left: constant(safe-area-inset-left);*//*padding-right: constant(safe-area-inset-right);*//*padding-bottom: constant(safe-area-inset-bottom);*/}

    ?

    解決使用漸變色 仍舊填充整個(gè)屏幕的方法;CSS設(shè)置如下

    <!DOCTYPE html> <html> <head><meta name="viewport" content="initial-scale=1, viewport-fit=cover"><title>Designing Websites for iPhone X: Respecting the safe areas</title><style> * {padding: 0;margin: 0;}html, body {height: 100%;}body {padding-top: constant(safe-area-inset-top);padding-left: constant(safe-area-inset-left);padding-right: constant(safe-area-inset-right);padding-bottom: constant(safe-area-inset-bottom);}.content {background: -webkit-gradient(linear, 0 0, 0 bottom, from(#ffd54f), to(#ffaa22));width: 100%;height: 724px;} </style> </head> <body> <div class="content">this is subElement</div> </body> </html>

    ?

    2.頁面元素使用了固定定位的適配即:{position:fixed;}

    ????????2.1 子元素頁面固定在底部時(shí);使用viewport-fit:contain時(shí);可以看到bottom:0時(shí)只會(huì)顯示在安全區(qū)域內(nèi);

    <!DOCTYPE html> <html> <head><meta name="viewport" content="initial-scale=1"><!--<meta name="viewport" content="initial-scale=1, viewport-fit=cover">--><title>Designing Websites for iPhone X: Respecting the safe areas</title><style>* {padding: 0;margin: 0;}/*html,body {*//*height: 100%;*//*}*/body {background: grey;/*padding-top: constant(safe-area-inset-top);*//*padding-left: constant(safe-area-inset-left);*//*padding-right: constant(safe-area-inset-right);*//*padding-bottom: constant(safe-area-inset-bottom);*/}.top {width: 100%;height: 44px;background: purple;}.bottom {position: fixed;bottom: 0;left: 0;right: 0;height: 44px;color: black;background: green;}</style> </head> <body><div class="top">this is top</div><div class="bottom">this is bottom</div> </body> </html>

    ?

    2.1 子元素頁面固定在底部時(shí);使用viewport-fit:cover時(shí);可以看到bottom:0時(shí)只會(huì)顯示在安全區(qū)域內(nèi);

    ?

    * {padding: 0;margin: 0;}/*html,body {*//*height: 100%;*//*}*/body {background: grey;padding-top: constant(safe-area-inset-top);/*padding-left: constant(safe-area-inset-left);*//*padding-right: constant(safe-area-inset-right);*//*padding-bottom: constant(safe-area-inset-bottom);*/}.top {width: 100%;height: 44px;background: purple;}.bottom {position: fixed;bottom: 0;left: 0;right: 0;height: 44px;color: black;background: green;}

    添加html,body ? {width:100%;heigth:100%}

    ?

    圖1:

    * {padding: 0;margin: 0;}html,body {height: 100%;}body {background: grey;padding-top: constant(safe-area-inset-top);padding-left: constant(safe-area-inset-left);padding-right: constant(safe-area-inset-right);padding-bottom: constant(safe-area-inset-bottom);}.top {width: 100%;height: 44px;background: purple;}.bottom {position: fixed;bottom: 0;left: 0;right: 0;height: 44px;color: black;background: green;}

    圖2:

    * {padding: 0;margin: 0;}html,body {height: 100%;}body {background: grey;padding-top: constant(safe-area-inset-top);padding-left: constant(safe-area-inset-left);padding-right: constant(safe-area-inset-right);/*padding-bottom: constant(safe-area-inset-bottom);*/}.top {width: 100%;height: 44px;background: purple;}.bottom {position: fixed;bottom: 0;left: 0;right: 0;height: 44px;color: black;background: green;}

    ?

    ?

    2.3 關(guān)于alertView彈框 遮罩層的解決方案

    ?

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><!--<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">--><meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"><title>alertView</title><script data-res="eebbk">document.documentElement.style.fontSize = window.screen.width / 7.5 + 'px';</script><style>* {margin: 0;padding: 0;}html,body {width: 100%;height: 100%;}body {font-size: 0.32rem;padding-top: constant(safe-area-inset-top);padding-left: constant(safe-area-inset-left);padding-right: constant(safe-area-inset-right);padding-bottom: constant(safe-area-inset-bottom);}.content {text-align: center;}.testBut {margin: 50px auto;width: 100px;height: 44px;border: 1px solid darkgray;outline:none;user-select: none;background-color: yellow;}</style><link href="alertView.css" rel="stylesheet" type="text/css"> </head> <body><section class="content"><button class="testBut" onclick="showLoading()">彈框加載</button></section><script type="text/javascript" src="alertView.js"></script><script>function showLoading() {UIAlertView.show({type:"input",title:"溫馨提示", //標(biāo)題content:"VIP會(huì)員即將到期", //獲取新的isKnow:false});var xx = new UIAlertView();console.log(xx);}</script> </body> </html>

    ?

    參考資料:

     iPhone X的Web設(shè)計(jì)

    ? ?iPhone X適配沒那么復(fù)雜,但也不是看上去這么簡(jiǎn)單

    總結(jié)

    在移動(dòng)端開發(fā)中,理解視口對(duì)適配至關(guān)重要。因此本文先從視口展開討論,從而引出 1px、rem 及 vw/vh 這些和適配相關(guān)的主要話題。下面提供的參考文章會(huì)在某些點(diǎn)上更加細(xì)化,以供參考。

    總結(jié)

    以上是生活随笔為你收集整理的移动端适配 - 小结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。