问题背景
由于我司是使用的大屏,且设计稿尺寸为19201080。但是需要适配各种分辨率, 比如12801024(5:4)、1366768(16:10)、16801050(16:10)。在尝试了多种方法之后,最终确定主要的适配方法为rem方案。
尝试方法的对比
1.使用scale方法:优点是代码最少,缺点是可惜为了网页等比例的显示,会将浏览器的上下,或者左右进行留白。导致效果不是很好(其实是因为产品说这里都有空白的,为什么不占满????无奈, 只能放弃解释)。第二个情况就是我们项目用了地图,缩放比例过大时会导致事件热区偏移。
2.rem方法:灵活性强,可以使用px来开发,缺点是也会留白,但是后续通过一些其他的响应式方法可以规避。
两种方法的适用场景:
1.scale方法:如果你的项目没有地图(或者大屏没什么点击事件),只是大屏项目,然后要求等比缩放,允许有一些留白。那么就优先使用这种方法。因为较为简单,整体效果也不错。
2.rem方法:适合有地图,不允许留白。
由于我们项目带了大量的地图,且需要适配5:4比例的,还不能留白(不能留白,那么只能是非等比缩放了),所以我们使用的是rem方案配合其他响应式方法。接下来就整体介绍下rem方案的实现步骤
两种方法的效果:
scale效果(只用了scale,会有留白,但是保证了等比缩放):
rem效果(这里是使用了rem+百分比布局,基本都是全屏了,这里是非等比缩放了。很小的时候看着有滚动条,实际点一下或者刷新一下都没有,估计是我浏览器卡)
效果解释说明:
1.在项目要求浏览器各分辨率都要等比缩放时,无论是rem/scale都会有相应的留白!!!
2.在项目要求浏览器各分辨率都要铺满全屏时,只使用rem/scale都无法完成需求(需要各分辨率还铺满全屏,肯定不是等比例)。你需要搭配其他的响应式方法。例如:a.媒体查询 b.vh和vw c.flex d.百分比布局等
rem方案实现步骤:
1.安装 flexible.js (建议放到本地)
2.使用 postcss-pxtorem插件
1.安装 flexible.js (建议放到本地)
javascript">(function flexible(window, document) {
var docEl = document.documentElement;
var dpr = window.devicePixelRatio || 1;
// 调整 body 字体大小
function setBodyFontSize() {
if (document.body) {
// body 字体大小默认为 16px
document.body.style.fontSize = 16 * dpr + "px";
} else {
document.addEventListener("DOMContentLoaded", setBodyFontSize);
}
}
setBodyFontSize();
// 移动端默认平均分成 10 等分(适用移动端)
// pc端默认平均分成 24 等分(适用 pc 端)
function setRemUnit() {
var splitNum = /Mobi|Android|iPhone/i.test(navigator.userAgent) ? 10 : 24;
var rem = docEl.clientWidth / splitNum; // 1920 / 24 = 80
docEl.style.fontSize = rem + "px"; // 设置 html 字体的大小 80px
}
setRemUnit();
// 页面调整大小时重置 rem 单位
window.addEventListener("resize", setRemUnit);
window.addEventListener("pageshow", function (e) {
if (e.persisted) {
setRemUnit();
}
});
// 检测 0.5px 支持
if (dpr >= 2) {
var fakeBody = document.createElement("body");
var testElement = document.createElement("div");
testElement.style.border = ".5px solid transparent";
fakeBody.appendChild(testElement);
docEl.appendChild(fakeBody);
if (testElement.offsetHeight === 1) {
docEl.classList.add("hairlines");
}
docEl.removeChild(fakeBody);
}
})(window, document);
2.使用 postcss-pxtorem 插件
安装命令 npm i postcss-pxtorem@5.1.1 (注意版本号,高版本会报错)
在与src同级的目录下添加postcss.config.js文件
module.exports = {
plugins: {
autoprefixer: {},
"postcss-pxtorem": {
rootValue: 80, // 根元素的字体大小
unitPrecision: 5, // 小数点后精度
propList: ["*"], // 可以从px改变为rem的属性
exclude: /node_modules/i, // 要忽略并保留为px的文件路径
minPixelValue: 0, // 最小的px转化值(小于这个值的不转化)
mediaQuery: false, // 允许在媒体查询中转换px
selectorBlackList: [], // 要忽略并保留为px的选择器
replace: true, // 直接在css规则上替换值而不是添加备用
},
},
};
这两步之后,你就可以使用px进行开发了。
但是需要注意的是:
1.postcss-pxtorem 插件不能把行内样式转换成rem,所以尽量少些行内样式,否则不会转成rem,还是px。你这里也可以自己写一个loader去把行内样式转成rem,也可以使用插件,或者少些行内样式,都可以。
2.另外就是UI库中的单位还是px,这也是需要注意的,如果需要更改,那就写样式覆盖下。
补充:rem可以作为主方案来实施,但是由于项目要铺满全屏,需要搭配其他响应式方法
例如:a.媒体查询 b.vh和vw c.flex d.百分比布局
其中媒体查询又属于是比较适合的,有超多网站都使用了媒体查询。
例如我们自己写的时候也是搭配了媒体查询。因为缩放到1200宽度的时候,虽然能显示下4个盒子。但是感觉太紧凑了,不如利用媒体查询变成3个盒子或者两个
1920*1080
宽1000px
各类需求适合适配的主方案:
移动端: rem(lib-flexible+postcss-pxtorem) 或者 vw方案 参考vant官方文档:https://vant-ui.github.io/vant/#/zh-***/advanced-usage#liu-lan-qi-gua-pei
PC大屏: scale优先
PC端(官网主页/购物网站/类似知乎,淘宝,小米等主页):使用版心布局
PC端(有地图或不允许留白(设计稿完全占满了1920*1080)):rem(lib-flexible+postcss-pxtorem)+其他响应式方法
本文项目源码地址:https://github.***/rui-rui-an/rem