探讨移动端布局解决方案

·  阅读 2742

前言

做了两三个移动端布局的h5项目,觉得收获颇多,就总结一下移动端布局的几种解决方案吧。

概念

在探讨一些方案之前,先了解一些概念。

物理像素:相当于屏幕分辨率。如:4.7寸iPhone是750*1334,这个所指的就是物理像素。

设备独立像素:此为逻辑像素,计算机设备中的一个点,css中设置的px单位像素指的就是该像素。老早在没有 retina 屏之前,设备独立像素与物理像素是相等的。如:4.7寸iPhone是375*667,这个所指的就是设备独立像素。

设备像素比:设备像素比(dpr) = 物理像素/设备独立像素。如:4.7寸的iPhone设备像素比是2。

适配方案

方案一:rem适配(不改变屏幕缩放比)

const MAX_FONT_SIZE = 42;

document.addEventListener('DOMContentLoaded', () => {
    const html = document.querySelector('html');
    let fontSize = window.innerWidth / 10;
    fontSize  = fontSize > MAX_FONT_SIZE ? MAX_FONT_SIZE : fontSize;
    html.style.fontSize = fontSize + 'px';
});
复制代码
// 以 Iphone 6、6s、7、8 为设计基础。750px
// 定义预计根元素 fontSize。
$rootFontSize: 375 / 10;
// 定义像素转化为 rem 函数
@function px2rem ($px) {
    @return $px / 2 / $rootFontSize + rem;
}
复制代码

方案二:rem适配(动态设置屏幕缩放比)

function setHtmlFontSize(baseFontSize) {
    
    const _baseFontSize = baseFontSize || 75;//设计htmlfotnszie
    const ua = navigator.userAgent;
    const matches = ua.match(/Android[\S\s]+AppleWebkit\/(\d{3})/i);
    const isIos = navigator.appVersion.match(/(iphone|ipad|ipod)/gi);
    let dpr = window.devicePixelRatio || 1;
    if (!isIos && !(matches && matches[1] > 534)) {
        // 如果非iOS, 非Android4.3以上, dpr设为1;
        dpr = 1;
    }
    const scale = 1 / dpr;//设备像素比
    let 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';
};
复制代码
// 以 Iphone 6、6s、7、8 为设计基础。750px
// 定义预计根元素 fontSize。
$rootFontSize: 375 / 10;
// 定义像素转化为 rem 函数
@function px2rem ($px) {
    @return $px / 2 / $rootFontSize + rem;
}
复制代码

注:此时因为scale的缩放比,css的像素单位px不再是以设备独立像素为参照物,而是物理像素。与一相比解决了1px像素问题。但同时这对于开源库的适配不友好

方案三:vue-cli适配

const autoprefixer = require('autoprefixer')
const pxtorem = require('postcss-pxtorem')
module.exports = { 
  // ...
  css: {
    sourceMap: true,
    loaderOptions: {
      postcss: {
        plugins: [
          autoprefixer(),
          pxtorem({
            rootValue: 37.5,
            propList: ['*']
          })
        ]
      }
    }
  }
}
复制代码

此方案多用于解决开源组件库使用px问题,如vant。

方案四:媒体查询

html{
    font-size: 16px;
}

@media only screen and (max-width: 414px){
 html{
        font-size: 64px;
    }
}
@media only screen and (max-width: 375px){
    html{
        font-size: 58px;
    }
}
@media only screen and (max-width: 360px){
    html{
        font-size: 56px;
    }
}
@media only screen and (max-width: 320px){
    html{
        font-size: 50px;
    }
}
复制代码

最后针对每个页面进行采用媒体查询 (由于meta标签scale =1,此时对于移动端而言,css的像素单位px的参照物是设备独立像素) 适配,当屏幕大于414px统一采用px单位,小于414px采用rem单位。

优点:rem单位的使用和媒体查询配合能够达到pc端和移动端布局的响应式。

缺点:由于通过css手动设置fontsize,在显示细节方面难免没有那么统一,而且需要对不同移动设备的不同min-widh进行设置,稍微比较繁琐一点。

方案五:视口单位适配

vw+vh单位已被大多设备所兼容,是最简单的一种适配方案。

以vw作为布局单位,方法如下。(使用sass函数编译 ) //750px作为设计稿基准

$vm_base: 750; 
@function vm($px) {
    @return ($px / $vm_base) * 100vw;
}

//通过代码,假如设计稿中元素的宽度是 40px ,那么就可以在样式中写
.test{
    width:vm(40)
}
复制代码

1px像素问题

除了设置viewprot方法之外,还可以通过transform设置。 如:

  .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);
            }
        }
复制代码

如有不足之处,欢迎指正

分类:
前端
标签:
分类:
前端
标签: