移动端适配大总结
一、前言
大家都知道现在市面上的手机尺寸越来越多,对于一名前端开发来说,面临着开发上的挑战。要使各个手机上的UI达成一致效果,就需要我们采用各种方案规避差距。
二、rem方案
最常见的就是利用手淘的flexible.js,包含amfe-flexible和lib-flexible两种,
amfe-flexible是lib-flexible的升级版。
2.1 实现原理
2.1.1 使用rem实现尺寸自适应
flexible的核心思想是利用rem单位,rem单位是基于html的font-size来做计算的,例如font-size为100px,那么200px就可以用2rem表示
// 在手淘里认为1rem = 屏幕尺寸 / 10
function setRem () {var rem = docEl.clientWidth / 10document.documentElement.style.fontSize = rem + 'px'
}
setRem ();
如上代码所示,Flexible将整个页面的宽度切成了10份,然后将计算出来的页面宽度的1/10设置为html节点的fontSize,也就意味着,页面上以 rem为单位的元素的尺寸 都是和 页面宽度 息息相关的
2.1.2 rem解决1px问题
设置viewport的width为device-width,改变浏览器viewport(布局视口和视觉视口)的默认宽度为理想视口宽度,从而使得用户可以在理想视口内看到完整的布局视口的内容。
等比设置viewport的initial-scale、maximum-scale、minimum-scale的值,从而实现1物理像素=1css像素,以适配高倍屏的显示效果(就是在这个地方规避了大家熟知的“1px问题”)
var metaEL= doc.querySelector('meta[name="viewport"]');
var dpr = window.devicePixelRatio;
var scale = 1 / dpr
metaEl.setAttribute('content', 'width=device-width, initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
2.2 使用教程
2.2.1 使用flexible
项目前提是基于Vue Cli3.x的Webpack项目,flexible可以动态改变 根元素的 font-size
cnpm intall amfe-flexible -D // 安装amfe-flexible
import ‘amfe-flexible’ // 在 src\main.js 中引入 amfe-flexible
2.2.2 px2rem 配置
作用: 可以让根元素fontSize根据屏幕宽度自动变化
// px自动转rem
cnpm intall postcss-px2rem -D
在项目根目录下创建postcss.config.js文件
plugins: {...,'postcss-pxtorem': {// 750设计标准,rootValue为设计图宽度/10rootValue: 75,// 转换成的rem后,保留小数点后几位unitPrecision: 5,/*** 将会被转换的css属性列表,* 设置为*表示全部,['*','*position*','!letter-spacing','!font*']* *position* 表示所有包含 position 的属性* !letter-spacing 表示非 letter-spacing 属性* !font* 表示非font-size font-weight ... 等的属性* */propList: ['*', '!letter-spacing'],// 不会被转换的class选择器名,支持正则selectorBlackList: ['.rem-'],replace: true,// 允许在媒体查询中转换`px`mediaQuery: false,// 小于1px的将不会被转换minPixelValue: 1}
}
2.3 现有问题
2.3.1 无法兼容安卓手机视网膜屏
市面上的安卓手机的dpr比较杂乱,1 到 4 甚至到 5,更甚者1.75、2.6、3.5,所以flexible放弃了对安卓手机多倍屏的适配,直接把dpr=1。
2.3.2 使用iframe引用也会出现问题。
iframe中的css单位还是px
三、viewport
viewport适配是现在 很主流 且 更完美 的适配方案,兼容性也很不错
3.1 实现原理
我们都知道屏幕的宽度可以用 100vw 表示,所以对于 750px 的设计图来说, 100vw =750px,代表 1vw = 7.5px,在使用中直接用vw作为单位,就可以实现 容器和文字 的适配。
3.2 使用教程
3.2.1 安装px-to-viewport
主要用来把 px 单位转换为 vw、vh、vmin 或者 vmax 这样的视窗单位(推荐转换为 vw,其他单位兼容性问题比较多)。项目前提是基于Vue Cli3.x的Webpack项目。
cnpm install postcss-px-to-viewport -D
3.2.2 px-to-viewport配置
在项目根目录下创建postcss.config.js文件,px会自动转换为vw
module.exports = {plugins: {"postcss-px-to-viewport": {unitToConvert: "px", // 需要转换的单位,默认为"px"viewportWidth: 750, // 设计稿的视口宽度unitPrecision: 5, // 单位转换后保留的精度propList: ["*"], // 能转化为vw的属性列表viewportUnit: "vw", // 希望使用的视口单位fontViewportUnit: "vw", // 字体使用的视口单位selectorBlackList: [], // 需要忽略的CSS选择器minPixelValue: 1, // 最小的转换数值,如果为1的话,只有大于1的值会被转换mediaQuery: false, // 媒体查询里的单位是否需要转换单位replace: true, // 是否直接更换属性值,而不添加备用属性exclude: [], // 忽略某些文件夹下的文件或特定文件include: undefined, // 如果设置了include,那将只有匹配到的文件才会被转换,例如只转换 'src/mobile' 下的文件 (include: /\/src\/mobile\//)landscape: false, // 是否添加根据 landscapeWidth 生成的媒体查询条件 @media (orientation: landscape)landscapeUnit: "vw", // 横屏时使用的单位},"postcss-preset-env": {browsers: "last 2 versions", //指定只对最近 2 个版本的浏览器进行兼容性处理。},},
};
3.3 存在问题
3.3.1 边框1px问题
-
border-image
安卓低端机和部分ios存在兼容性问题,而且无法实现圆角 -
background-image
background-image方案,在机型上都能比较好的展现,但是在背景图方案中需要提供2像素的图片。 -
渐变背景图
虽然无法实现圆角,但使用率还是挺高的 -
伪类+transform
我认为最值得灵活,最值得提倡的方案,既可以实现圆角,兼容性也好
border-1px($color = #ccc, $radius = 2PX, $direction = all)position: relative&::aftercontent: ""pointer-events: nonedisplay: blockposition: absoluteborder-radius: $radiusbox-sizing border-boxwidth 100%height 100%left: 0top: 0transform-origin: 0 0if $direction == allborder: 1PX solid $colorelseborder-{$direction}: 1PX solid $color@media only screen and (-webkit-min-device-pixel-ratio:2)width: 200%height: 200%border-radius: $radius * 2transform: scale(.5)@media only screen and (-webkit-min-device-pixel-ratio:3)width: 300%height: 300%border-radius: $radius * 3transform: scale(.333)
3.3.2 宽度大于100vw问题
如果 容器 用vw作为单位,margin用px的话,宽度容易超过100vw,出现滚动问题
解决方式可以用padding代替margin,或者用calc算margin
四 多倍屏图片问题
多倍屏的1px问题,Flexible默认就可以实现适配,viewport可以自己写伪类解决。但是无论是rem还是viewport,图片适配都需要单独处理。
4.1 媒体查询+预编译语言
直接写死不灵活,可以结合预编译语言实现
@mixin bg-image($url) {background-image: url($url + "@2x.png");@media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3) {background-image: url($url + "@3x.png");}
}
.div{width:30px;height:20px;background-size:30px 20px;background-repeat:no-repeat;//在这里相当于调用了上面媒体查询的方法 ,传入图片url@include bg-image('special_1');
}
4.2 image-set
仅支持背景图
.avatar {background-image: -webkit-image-set( "conardLi_1x.png" 1x, "conardLi_2x.png" 2x );
}
4.3 srcset
仅仅支持img图片
4.4 svg
可伸缩矢量图,放大缩小都不会失真
参考大神知乎的文章
https://zhuanlan.zhihu.com/p/291013307
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
