移動端適配方案

  • 【序】今天刷到一篇公眾號的文章主題是移動端適配的相關基礎概念,那么就通過閱讀基礎概念,從業務的角度來做個總結,文章地址

問題一

  • 【疑惑】 當我們拿到移動端的設計稿,應該從何處下手?
  • 【解惑】 設計稿往往是使用px單位進行標注的,要完全呈現設計稿在不同手機上的適配,首先需要了解一下動態單位,動態單位有,vh,vw,vm,rem,%,接下來細數一下各個單位的基本概念。
  1. px
    用的最多的px,其意義就是,一個像素點
  • 【缺點】設計稿往往只針對某一個分辨率,一旦分辨率縮小或者變大,就會導致樣式變形
  • 【優點】無須計算,便于開發
  1. viewport unit
    vh與vw都是css3才出的單位,vh代表視口高度總像素比,vw代表視口寬度總像素比,例如一個1300*800像素的屏幕,1vh就是1/800,1vw就是1/1300
    此外還有兩者取一的vmin和vmax,
    vmin表示高度和寬度誰小取誰的,配合padding使用padding: 10vmin 1rem;能夠獲得較合適的頂部和底部展示
    vmax表示高度和寬度誰大取誰,可以使元素保持寬高比(用于圖片固定寬高比展示比較有用)

    vh與vw兼容性也挺不錯

  2. rem,em
    rem,em是通過對字體大小來計算寬度的單位,em假設父級的font-size是16px,那么1em=16px,而rem和em相當,但是對標html標簽上設置的font-size

  3. %
    %分號就是父級寬度/高度的百分比,如果父級沒有給定寬度/高度,那么就會失效
    【缺點】 不夠精確
    【優點】 簡單易用,能夠保持元素的原始比例,通常在pc端可以保證布局在一定范圍內適應分辨率

問題二

  • 【疑惑】 接下來我們要學習像素的概念,像素分為物理像素,設備獨立像素,css像素
  • 【解惑】
  1. 物理像素
    即設備橫向有多少個像素,縱向有多少個像素,是非常直觀,單位的px

  2. 設備獨立像素( DeviceIndependentPixels 簡稱 DIP或DP)
    同樣的1單位物理像素,假設手機屏幕物理寬度相同,但是其中一個手機相同的寬度上比其他手機多一倍的像素,那么這1 單位物理像素,在物理像素多的手機上的顯示就會變得更小,但是由于手機物理寬度不同&物理像素的不同,那就需要一個單位來告訴所有設備某個圖形的寬度到底是在這個手機大小是多少?這個單位就DP,此時1DP在所有設備上的大小都相等了。

【延申】在Chrome的模擬器中顯示的設備大小單位其實就是DP

Chrome的手機模擬

  1. css像素
    css像素,css像素 = 頁面的縮放系數*設備獨立像素

  2. 設計像素
    設計像素是實際展示的內容的像素,通常是UI提供的設計稿的像素參照,詳細概念看問題三

問題三

  • 【疑惑】 既然擁有了設備獨立像素的概念,那么只需要將物理像素轉化為設備獨立像素,就可以完美適配全部機型了嗎?
  • 【解惑】 并不夠,設備獨立像素是通過物理寬度與物理像素計算出來的,但是有的設備,物理像素上就是要展示更高分辨率的展示的效果,例如iPhone6、7、8Plus的實際物理像素是 1080 * 1920,設備獨立像素是414DP * 736DP,但是實際上展示1242PX * 2208PX分辨率的內容(稱為設計像素),此時僅靠設備獨立像素就不夠了,還需要設備像素比 (device pixel ratio簡稱 dpr)
    此時,1dp=1px/dpr,1px = 1dp*dpr
  • 【延申】設備像素比在瀏覽器中可以通過window.devicePixelRatio來獲取,但是devicePixelRatio的兼容性IE,firefox兼容問題不推薦使用

問題四

  • 【疑惑】 手機上網剛出現的時候,是如何針對電腦屏幕開發的網頁的?
  • 【解惑】 此時就要學習 視口 的概念,視口分為布局視口視覺視口理想視口
  1. 布局視口(layout viewport)
    就是我們的css內容的大小
  2. 視覺視口(visual viewport)
    就是手機屏幕所展現出來的大小


    image.png
image.png
  1. 理想視口( ideal viewport)
    也就是說最適合的寬度,即布局視口等于視覺視口的寬度,那些針對idel viewport而設計的網站,不需要用戶手動縮放,也不需要出現橫向滾動條,都可以完美呈現給用戶,布局視口要適應視覺視口,那么就必須先將視覺視口固定下來,一般使用以下代碼,就能夠將默認的layout viewport等同于visual viewport 此時我們就只需要考慮visual viewport即可
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

此時設備物理寬度和我們的頁面寬度為一比一了,接下來就只用考慮物理像素密度dpr了

viewport unit自適應方案

該方案由于采用了視口單位,則viewport的meta設置也不需要了
方案中,我們需要將設計稿中的px按照比例轉換為vw單位,這樣就能保證在不同的寬度中獲得統一的比例

//iPhone 6尺寸作為設計稿基準
$vm_base: 375; 
@function vw($px) {
    @return ($px / $vm_base) * 100vw;
}

接下來就可以愉快的使用該方法按照設計稿去計算寬高,間距,字體大小了

.mod_nav {
    background-color: #fff;
    &_list {
        display: flex;
        padding: vm(15) vm(10) vm(10); // 內間距
        &_item {
            flex: 1;
            text-align: center;
            font-size: vm(10); // 字體大小
            &_logo {
                display: block;
                margin: 0 auto;
                width: vm(40); // 寬度
                height: vm(40); // 高度
                img {
                    display: block;
                    margin: 0 auto;
                    max-width: 100%;
                }
            }
            &_name {
                margin-top: vm(2);
            }
        }
    }
}

高清屏下1px單邊框解決方案原理:

.scale-1px-bottom {
    position: relative;
    &::after {
        // 實現1物理像素的下邊框線
        content: '';
        position: absolute;
        z-index: 1;
        pointer-events: none;
        background-color: #ddd;
        height: 1px;
        left: 0;
        right: 0;
        top: 0;
        @media only screen and (-webkit-min-device-pixel-ratio: 2) {
            -webkit-transform: scaleY(0.5);
            -webkit-transform-origin: 50% 0%;
        }
    }
}

實際項目sass實現參考
保持圖片寬高比實現方案

.mod_banner {
    position: relative;
    padding-top: percentage(100/700); // 使用padding-top,100是稿子上的高度,700是設計稿的比例
    height: 0;
    overflow: hidden;
    img {
        width: 100%;
        height: auto;
        position: absolute;
        left: 0;
        top: 0; 
    }
}

結合rem優化方案

  1. 可以方便的通過改變計算方式過度到viewport unit
  2. 增加了寬度最大值最小值,在ipad等大屏幕上用戶體驗更好

【延伸】手機的實際分辨率是設計稿的兩倍?
答案:因為設計師拿去設計的稿子是按照手機的實際寬度375去設計的,但是程序員去實現時,考慮到相同寬度擁有更多像素點即dpr,因此實際分辨率是1dpdpr,即iPhone6的dpr=2,那么實際分辨率為3752。

// rem 單位換算:定為 75px 只是方便運算,750px-75px、640-64px、1080px-108px,如此類推
// 根元素大小使用 vw 單位
$vm_design: 375;   //設計稿參照iPhone6的大小
$vm_fontsize: $vm_base * 2 / 10; // 因為一般實際分辨率是設計稿的兩倍,所以需要先乘2,再除10獲得設計稿上的實際1rem的值
@function rem($px) {
     @return ($px / $vm_fontsize ) * 1rem;
}
html {
    font-size: ($vm_fontsize / ($vm_design / 2)) * 100vw;   //因為默認需要占用20vw
    // 同時,通過Media Queries 限制根元素最大最小值
    @media screen and (max-width: 320px) {
        font-size: 64px;  //當屏幕寬度小于320px 則1rem = 64px;  該值來源于320*2
    }
    @media screen and (min-width: 540px) { 
        font-size: 108px;  // 當屏幕寬度大于540px 則1rem = 108px; 該值來源于540*2
    }
}
// body 也增加最大最小寬度限制,避免默認100%寬度的 block 元素跟隨 body 而過大過小
body {
    max-width: 540px;
    min-width: 320px;
}

總結

  1. 當我們拿到設計稿,我們要清楚設計稿的分辨率,設計稿是為移動端還是pc端設計的,pc端的dpr為1,移動端一般以dpr=2為主
  2. 第二計算rem,1rem為實際分辨率的1/10
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。