这是要为一个vue项目做自适应,设计稿是1920*1080的,要适应各种手机、ipad、3840*2160的超大屏,所以就选择了rem,包用的是 postcss-pxtorem
在适配的时候遇到了很多问题,初版是这样的:
// 设计稿以1920px为宽度 function setRem() { const htmlWidth = document.documentElement.clientWidth || document.body.clientWidth; const htmlHeight = document.documentElement.clientHeight || document.body.clientHeight; let baseSize = 192; let scale = htmlWidth / 1920; document.documentElement.style.fontSize = (baseSize * scale) + 'px'; } setRem(); window.addEventListener('resize', () => { setRem(); });
.postcssrc.js文件是这样配置的:
module.exports = { "plugins": { // to edit target browsers: use "browserslist" field in package.json "autoprefixer": {}, "postcss-pxtorem": { "rootValue": 192, "propList": ["*"], "selectorBlackList": ["weui-"] } } }
rootValue的值就是设计稿的宽度/10。
我以为大功告成了,各种想不到的问题就出现了:
1.页面一打开就出现高度滚动条,复现条件:pc端
这个原因是因为rem布局是以宽度为基准的,比如我电脑的屏幕是1920*1080的,但是往往浏览页面的时候,浏览器给的宽度都是给够的,但是高度不够,比如浏览器的头部、电脑任务栏,这些都会抢占页面的高度。而rem计算又是以宽度为基准的,滚动条就出现了:
解决办法:计算设计稿跟实际的宽高比
const designRatio = 1920 / 1080; const realRatio = htmlWidth / htmlHeight; // 存在宽度够了,高度不够的情况 if (realRatio > designRatio) { document.documentElement.style.fontSize = (baseSize * Math.min(scale, 2)) * (designRatio / realRatio) + 'px' }
好了,现在 在各种iPhone7、8,以及pc端都没问题,结果又出问题了:
在部分安卓手机会出现样式错乱:
原因:用户设置了系统字体大小
这一部分可以参考这个博客解决: rem在webview中错乱
整体代码:
/** * 以1920设计稿为准 */ function setRem() { const htmlWidth = document.documentElement.clientWidth || document.body.clientWidth; const htmlHeight = document.documentElement.clientHeight || document.body.clientHeight; const designRatio = 1920 / 1080; const realRatio = htmlWidth / htmlHeight; let baseSize = 192; let scale = htmlWidth / 1920; document.documentElement.style.fontSize = (baseSize * Math.min(scale, 2)) + 'px'; // 防止用户设置系统字体大小 let computedFontSize = parseFloat(window.getComputedStyle(document.documentElement).fontSize); let configFontSize = parseFloat(document.documentElement.style.fontSize); document.documentElement.style.fontSize = (configFontSize * configFontSize / computedFontSize) + 'px'; // 存在宽度够了,高度不够的情况 if (realRatio > designRatio) { document.documentElement.style.fontSize = (baseSize * Math.min(scale, 2)) * (designRatio / realRatio) + 'px' } } setRem(); window.addEventListener('resize', () => { setRem(); });