<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          社區(qū)精選|談?wù)?H5 移動端適配原理

          共 13006字,需瀏覽 27分鐘

           ·

          2023-09-08 03:04

          今天小編為大家?guī)淼氖巧鐓^(qū)作者 熊的貓 的文章,讓我們一起來學(xué)習(xí) H5 移動端適配原理。




          H5 移動端 開發(fā)的必不可少的一個環(huán)節(jié)就是 移動端網(wǎng)頁的適配,因為 UI 通常只會提供 大小固定的設(shè)計稿,而各種不同移動設(shè)備具有不同的頁面分辨率和大小,所以適配的目的就是讓一份設(shè)計稿在不同移動設(shè)備上表現(xiàn)出一致性。


          雖然現(xiàn)如今各種插件都可以幫助我們快速配置完成,例如 lib-flexiblepostcss-pxtorempostcss-px-to-viewport 等等,但不少小伙伴在被問及相關(guān)原理時卻很難說清楚,那么本篇文章我們就一起來探究一下其中原理吧!!!


          文中有不當(dāng)之處,歡迎在評論區(qū)指正


          CSS 中的尺寸單位

          在了解具體的適配方案之前,我們先把 CSS 中適配會涉及到的相關(guān)尺寸單位進行一個了解吧,總結(jié)起來就是一句話:CSS 中的尺寸單位都是 相對長度單位,只是相對的目標(biāo)不同。

          px 像素單位


          px 全稱為 pixel(像素),它是相對于 屏幕顯示器分辨率(桌面設(shè)定的分辨率,不是顯示器的物理分辨率) 而言的,在 相同/不同 的設(shè)備上 1px 表示多個 設(shè)備像素。

          當(dāng) 一個像素點越大 時, 呈現(xiàn)的圖像就會 越模糊;當(dāng)一個像素點越小時, 像素點就會 越密集, 呈現(xiàn)的圖像就會 越清晰。

          em 相對單位


          好多人都認(rèn)為 em 就是相對于 父元素 font-size,實際上在不同的 CSS 屬性當(dāng)中使用 em 其相對的目標(biāo)也是不同,如下:

          用于 font-size 中則是相對于 父元素 font-size 大小


          用于 其他屬性(如 width,height) 中使用是相對于 自身 font-size 大小

          值得注意的是,若 當(dāng)前元素/父元素 的 font-size 未設(shè)置,由于 font-size 屬性值可被繼承的原因,可逐級向上查找,最終找不到則相對于瀏覽器默認(rèn)字體大小,即 font-size = 16px。

          rem (root em) 相對單位


          rem 是 CSS3 新增的一個相對單位,它只相對于 根元素 html 的 font-size 字體大小,rem 與 em 的區(qū)別在于:
          • rem 相對于 html 根元素的,因此在 body 標(biāo)簽里面設(shè)置 font-size 是不起作用的
          • 因此 rem 就可做到 目標(biāo)元素 與 根元素 間保持 成比例 的大小關(guān)系,又可以避免字體大小逐層復(fù)合的連鎖反應(yīng)等,例如公共的字體大小可以在 body 中設(shè)置即可

          vw 和 vh


          • vw 全稱是 viewport width,代表的是 視口的寬度,相對于 視口 viewport 的 寬度
          • vh 全稱是 viewport height,代表的是 視口的高度,相對于 視口 viewport 的 高度
          • vw 和 vh 是將 視口 寬/高 都分成 100 份,因此 100vw = 視口寬、100vh = 視口高

          與之相關(guān)的還有 vmin 和 vmax 兩個單位
          • vmin 和 vmax 代表的是 視口寬度 和 視口高度 中的 最小值 和 最大值
          • vmin = 視口高度 vh 和 寬度 vw 間的最小值
          • vmax = 視口高度 vh 和 寬度 vw 間的最大值


          適配方案

          rem 適配(等比適配)

          核心原理

          • 將 設(shè)備視口 劃分成 n 份, n 可以是 任何正確的值(如 flexible.js 中的 n = 10)

            • 設(shè)置 設(shè)備視口 根元素 html 的 font-size = 設(shè)備視口寬 ÷ 份數(shù) n,即得到 設(shè)備視口 1 rem 到底表示 多少設(shè)備視口 px

          • 將 設(shè)計稿 也同樣劃分成 n 份,此時 設(shè)計稿中的 a px 對應(yīng) 設(shè)備視口 b rem 的計算方式為

            • 設(shè)備視口 b rem = 設(shè)計稿 a px ÷ (設(shè)計稿 寬 ÷ n 份)

          舉個例子


          設(shè)備視口寬為 375px

          將設(shè)備視口分成 10 份,設(shè)置 根元素 html 的 font-size = 375 ÷ 10 = 37.5 px,即 1 rem = 37.5 px
          (function (n = 10){
              const dEl = document.documentElement;
              function setRem(){
                  const rem = dEl.clientWidth / n;
                  dEl.style.fontSize = rem  + 'px';
              }
              // 初始化執(zhí)行
              setRem()
              // 視口大小變動時執(zhí)行
              window.onresize = setRem
          })()
          設(shè)計稿寬為 750px

          • 將 設(shè)計稿 也分成 10 份,每份大小 = 750 ÷ 10 = 75 px
          • 此時 設(shè)計稿 上的 "點我拍照"(font-size: 34px) 的文案轉(zhuǎn)換成符合 設(shè)備視口 對應(yīng)的 rem 就為:


            設(shè)備視口 中 文字 font-size = 34 ÷ 75 = 0.4533333333333333 rem ≈ 0.45 rem



          【注意】 一般計算結(jié)果(人為計算、插件自動化自動化計算)都不會使用這么長的小數(shù)位,比如 0.4533333333333333 rem ≈ 0.45 rem,此時:
          • 原始值 0.4533333333333333 rem = 0.4533333333333333 * 37.5 = 17 px
          • 保留兩位小數(shù)后的值 0.45 rem = 0.45 * 37.5 = 16.875 px
          而在肉眼觀察下 16.875 px 和 17 px 是沒有差別的,因此可以忽略不計

          用 amfe-flexible 和 postcss-pxtorem 驗證


          文本和原始樣式


          amfe-flexible 和 postcss-pxtorem 配置


          最終展示效果



          早期 rem 適配優(yōu)化(過期方案,了解即可)

          在早期還沒有各種 CSS 預(yù)處理器 和 自動化計算的插件 時(即 還需要人為計算時),上述 rem 適配的方案 有一個缺點,那就是針對 設(shè)計稿中不同的 px 的轉(zhuǎn)換為 設(shè)備視口 rem 的計算過程還是比較繁瑣,特別是一些比較難算的數(shù)值。

          例如,上述將 設(shè)計稿 34px 轉(zhuǎn)換為 設(shè)備視口 0.9rem 的例子,對大部分人來說是不能 直接/快速 看到設(shè)計稿中 px 的數(shù)值就能直接算出其對應(yīng)的 rem 單位的數(shù)值的,因此需要進行優(yōu)化。

          而 優(yōu)化 的核心就是 將 復(fù)雜計算 變成 簡單計算,例如在 寬 750 px 的設(shè)計稿中:
          • 34px 轉(zhuǎn)換成 rem = 34 ÷ 75,這種不直觀的計算叫 復(fù)雜計算,若可以實現(xiàn) 34 ÷ 100 即可得到相應(yīng)的 rem 的方式,就稱為 簡單計算(任何數(shù)除以 10 或 100 都很容易口算)
          也就是說,如果我們希望所有設(shè)計稿上 px 的計算都是 簡單計算,那么我們就需要保證其 渲染結(jié)果 是正確的即可,換句話說,就是我們需要調(diào)整設(shè)備視口的 1 rem = n px 中 n 的值讓其能夠滿足 34 ÷ 100 = 0.34 rem 的情況下還能夠被正常渲染為 17 px 即可,這無非就涉及到一個數(shù)學(xué)倍數(shù)計算而已,就不過多展開了。

          vw/vh 適配


          前面說過,vw 和 vh 是將 視口 寬/高 都分成 100 份,相對于 設(shè)備視口 375px 來說 1vw = 375 ÷ 100 = 3.75px。

          經(jīng)過了 rem 適配方案 的介紹,vw/vh 這種適配方式就是相當(dāng)于把替換了原本的 rem 單位,因此,這個方式的計算方式和 rem 的方式 如出一轍,區(qū)別就在于:
          • rem 的適配方式支持自定義將設(shè)備視口劃分為 n 份,n 可以是任何正確值
          • vw/vh 就是將設(shè)備視口劃分為 100 份,不支持自定義
          因此,假設(shè)將 設(shè)計稿 750px 中的 34px 轉(zhuǎn)換為 設(shè)備視口 n vw 就等于 n = 34 ÷ 7.5 = 4.533333333333333 vw ≈ 4.53 vw。

          CSS 預(yù)處理器 — 簡化計算


          如果使用的是 CSS 預(yù)處理器(Less、Sass),那么就可以通過定義一個全局的 函數(shù) 來幫助我們進行運算,例如:

          Less 中 px2vw() 的定義:
          // plugin.js
          module.exports = {
            install: function (less, pluginManager, functions) {
              functions.add('px2vw', (param, perVW) => {
                if (!param.value) return '0vw'
                if (!perVW.value) return param.value + 'px'
                return Number(param.value) / perVW.value + 'vw'
              })
            },
          }
          // 具體使用
          <style lang="less">
            @plugin './plugin.js';
            @design-width: 750;
            @per-vw: @design-width / 100;
            .text {
              font-size: px2vw(34, @per-vw);
              color: #457fff;
            }
          </style>

          Sass 中 px2vw() 的定義:
          <style lang="scss">
            $design-width: 750;
            $per-vw: $design-width / 100;
            @function px2vw($param) {
              @return $param / $per-vw + 'px';
            }
            .text {
              font-size: px2vw(34);
              color: #457fff;
            }
          </style>

          使用 postcss-px-to-viewport 進行驗證


          文本和原始樣式

          postcss-px-to-viewport 配置


          最終展示效果


          等比縮放 — viewport <meta> 標(biāo)記


          所謂 等比縮放 也就是我們不需要關(guān)注 設(shè)計稿 px 到底對應(yīng)多少 設(shè)備視口 rem 或 vw,在開發(fā)時,直接使用 設(shè)計稿提供的數(shù)據(jù) px 即可,然后在將整體頁面按照 設(shè)備視口 / 設(shè)計稿 的比例進行 整體縮放。

          而縮放就需要使用到 使用 "viewport" <meta> 標(biāo)記 來控制視口的大小和形狀了,例如常見的 <meta> 標(biāo)記如下:

          很明顯,我們只需要控制其中的 width 和 initial-scale 的值即可,它們分別是代表當(dāng)前設(shè)備視口寬度和縮放比的值。

          還是用 設(shè)計稿 750px 和 設(shè)備視口 375px 舉例子,因為我們是直接只用設(shè)計稿提供的數(shù)據(jù)來開發(fā),那么上面的 width = 設(shè)備視口寬、initial-scale = 設(shè)備視口 / 設(shè)計稿。
          (function (designWidth) {
            const dEl = document.documentElement;
            let meta = document.querySelector("meta[name=viewport]");
            // 頁面中不存在 <meta name="viewport" /> 時,手動創(chuàng)建一個   
            if(!meta) {
              meta = document.createElement('meta');
              meta.setAttribute('name''viewport');
              document.head.appendChild(meta);
            }
            function setMetaContent(){
              const deviceWidth = dEl.clientWidth;
              const scale = deviceWidth / designWidth;
              const content = `width=${deviceWidth}, initial-scale=${scale}`;
              meta.setAttribute("content", content);
            }
            setMetaContent();
            window.addEventListener("resize", setMetaContent)
          })(750);


          第三方組件庫如何做適配?

          不知道你是不是會有一些疑問,比如第三方組件庫的適配方式和我們使用的不一致怎么辦?

          不用擔(dān)心,第三方組件庫默認(rèn)都是直接使用 px 的方式來開發(fā)的,因此我們在項目中定義的適配方式就是第三方組件庫的適配方式,不會產(chǎn)生沖突的。

          例如,vant-ui 文檔中很貼心的為你列出了 瀏覽器適配方案(詳情可見文檔):
          • Viewport 布局
            • Vant 默認(rèn)使用 px 作為樣式單位,如果需要使用 viewport 單位 (vw, vh, vmin, vmax),推薦使用 postcss-px-to-viewport 進行轉(zhuǎn)換
          • Rem 布局適配
            • postcss-pxtorem 是一款 PostCSS 插件,用于將 px 單位轉(zhuǎn)化為 rem 單位
            • lib-flexible 用于設(shè)置 rem 基準(zhǔn)值
          • 桌面端適配
            • 若需要在桌面端使用 Vant,可以引入 @vant/touch-emulator,這個庫會在桌面端自動將 mouse 事件轉(zhuǎn)換成對應(yīng)的 touch 事件,使得組件能夠在桌面端使用

          vant-ui:https://vant-ui.github.io/vant/#/zh-CN/advanced-usage

          postcss-px-to-viewport :https://github.com/evrone/postcss-px-to-viewport

          postcss-pxtorem:https://github.com/cuth/postcss-pxtorem

          lib-flexible:https://github.com/amfe/lib-flexible

          @vant/touch-emulator:https://github.com/vant-ui/vant/tree/main/packages/vant-touch-emulator




          最后



          以上就是移動端適配的幾種方式的原理了,知道了這些內(nèi)容之后,其實就不難發(fā)現(xiàn)常用的適配插件不過是幫助我們實現(xiàn)了上述的內(nèi)容和一些細(xì)節(jié),例如 自動計算、自動轉(zhuǎn)換、判斷機型 等等。

          希望本文對你有所幫助!



          點擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開更多互動和交流,“公眾號后臺回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~


          - END -



          往期推薦


          社區(qū)精選|納尼!CSS 也能實現(xiàn)碰撞檢測?


          社區(qū)精選|記一次 Vue-CLI 生產(chǎn)項目的打包優(yōu)化


          社區(qū)精選|TypeScript 玩轉(zhuǎn)類型操作





          瀏覽 488
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色色色大香蕉 | 中国性老太HD大全120 | 日韩人妻人操 | 日本免费黄视频 | 国产中文99|