1, 先看看网上关于移动端适配讲解
再聊移动端页面适配, rem 和 vw 适配方案!
基础点: rem 相对根节点字体的大小. 所以不用 px;
根字体: 字体的大小 px;
px: 你就当成 cm(厘米)这样的东西吧;
基准: 750 设计稿;
这是方案的基础理论, 在这个基础上, 我们还要搞明白, 到底要干一件什么事情!
目标一 , 手机适配: 就是页面上的尺寸, 无论高度, 还是宽度, 还有字体, 随屏幕的宽度变化! 这里是屏幕宽度! 是不是想到了 vw, 对, 就是这个意思;-- 最大程度在各个尺寸屏幕上还原设计稿
目标二, px 转换成 rem: 一般 UI 给的设计稿宽度大小是 750, 所以, 我们想直接写上面 UI 标记的尺寸;-- 最大程度减少工作
为什么选择 rem?
很久之前没有 vw, 怕 vw 的兼容问题, 就用了 rem; 也就是: rem 的兼容性 > vw 的兼容性;
还有一种就是自己写百分比很不优雅
一, 理论基础!
实现目标一
用 rem 就可以了吧! 因为 rem 就可以随根字体大小改变而改变, 从而实现了自适应的功能.
但是, 但是, 重点来, 如果, 根字体的大小默认是 16px; 那么, 我们的 1rem; 就永远是 16px, 懂么? 也就是如果设计稿是 750(放大了一倍, iPhone 是 375pt), 我们想要个 50% 的大小:
50%*357px/16=11.718rem
如果我们写一个 11.718rem 的宽度, 然而这只能在能 iphone6 还原设计稿, 也就是只有在 iphone6 上这样的宽度才刚好占一半;
那么问题来了, 如果在每个屏幕上都是 50% 呢, 直接改变根字体大小 (16px) 不就完了么!!;11.718rem 永远还是那个 11.718rem, 不用担心;
实现目标二,
用工具, webpack,postCSS,postcss-pxtorem
二, 准备主要工具!
viewport: 建议自行百度;
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
vue-cli: 用这个主要是用 webpack, 这个构建工具大大降低了 webpack 的使用难度; 快速构建出一个前端项目.
postcss: 官网解释: PostCSS is a tool for transforming styles with JS plugins, 就是 postcss 用 JS 插件帮你转换 CSS 样式的一个工具. 比如, 这里的把你的文件里面 16px 替换成 1rem(根大小默认 16px 的情况); 这样你就不用自己去算了!
postcss-pxtorem: postcss 的一个插件, 主要是帮你把 px 转换成对应的 rem;
然后: 还要用 JS 代码去动态算根目录应该有的字体大小, 反正就是一段 JS 代码去动态获取屏幕宽度!
三, rem-- 开始干!
第一步, 先用 vue-cli 快速构建出一个项目, 然后, 安装 postcss,postcss-pxtorem,postcss-loader,postcss-import,postcss-url;
第二步, 在项目根目录下添加. postcssrc.JS 文件, 在里面写上
module.exports = { plugins: { 'postcss-pxtorem': { rootValue: 32, propList: ['*'], minPixelValue: 2 } }};
rootValue, 这里就是根目录的字体大小是 32px, 这里为啥设置成 32 呢, 因为一般设计稿是 750, 比 iphone6 的大一倍, 所以设置成 16 的两倍, 就是 32px;proplist 就是那些属性需要转换成 rem, 这里是全部的意思;
比如你可选择设置; propList: ['font', 'font-size', 'line-height', 'letter-spacing']
minPixelValue 就是最小转换单位, 这是最小转换单位是 2px 的意思;
第三步, 动态设置根字体大小! 一段简单的 JS 插入在 head 里面;
- (function() {
- function autoRootFontSize() {
- document.documentElement.style.fontSize = Math.min(screen.width,document.documentElement.getBoundingClientRect().width) / 750 * 32 + 'px';
- // 取 screen.width 和 document.documentElement.getBoundingClientRect().width 的最小值; 除以 750, 乘以 32; 懂的起撒, 就是原本是 750 大小的 32px; 如果屏幕大小变成了 375px, 那么字体就是 16px; 也就是根字体 fontSize 大小和屏幕大小成正比变化! 是不是很简单
- }
- Windows.addEventListener('resize', autoRootFontSize);
- autoRootFontSize();
- })();
这里, 我想说的是完全可以用 vw 去设置根字体大小, 26px/375px=4.267vw; 就不用 JS 去算了!
html{font-size:4.267vw}; // 因为这个字体大小完全是随屏幕正比变化;
四, vw-- 开始干!
vw 的方案就简单多了, 因为 vw 本来就相对屏幕的百分比, 所以我们不用再去动态的改变根字体大小了, 只需要把 750 上的 px 大小转换成对应的 vw 值就完了, 这一步交给 postcss 工具就可以!
所以只需要两步!
第一步, 先用 vue-cli 快速构建出一个项目, 然后, 安装 postcss,postcss-pxtorem,postcss-loader,postcss-import,postcss-url
第二步, 在项目根目录下添加. postcssrc.JS 文件, 在里面写上
module.exports = { "plugins": { "postcss-import": {}, "postcss-url": {}, "postcss-aspect-ratio-mini": {}, "postcss-write-svg": { utf8: false }, "postcss-cssnext": {}, "postcss-px-to-viewport": { viewportWidth: 750, unitPrecision: 3, viewportUnit: 'vw', selectorBlackList: ['.ignore', '.hairlines'], minPixelValue: 1, mediaQuery: false }, "postcss-viewport-units": {}, }}
viewportWidth 是你设计稿的大小 750, 然后 unitPrecision 是 vw 值保留的小数点个数;
五, 总结!
首先明白一件事: px 就像 cm 一样, 1px 永远是 1px;1cm 永远是 1cm;
那么我们从目标再反推一道逻辑:
我们想要的结果很简单: 一个元素的宽度(px) / 屏幕宽度(px) = 定值 (这个定值就是设计稿上面的值比例定值);
-- 所以要做就是: 屏幕变宽, 要让元素宽度就变宽.
然鹅, 我们写的代码里面的 px 是不可能变的(取的 750 设计稿上面的尺寸); 那么 postcss 编译出来的 rem 值也是不变的;
我们是怎么把设计稿里面的 40px 换算成相应 rem 的呢; 你只要记住根字体大小的值 (浏览器的默认是 16px, 现在设置成的 32px) 就是 1rem; 这交给工具同一去算;
得到: 元素的宽度(px) = 元素的宽度(rem) 32; 所以这个 32 是你必须要设置在 postcss-pxtorem 里面的; 这样它就可以帮你算;
又因为: 元素的宽度(rem) 根字体大小(px) = 元素的宽度(px)
元素的宽度(px) 变大, 元素的宽度(rem) 不变, 那就只有改变根字体大小(px) , 变大; 具体怎么变, 上面的 JS 代码已经解释了;
-- 所以我们做的就是: 屏幕变宽, 让根字体大小(px) 变宽, 元素宽度就变宽.
750 屏幕下是写的样式大小是 1:1, 所以
又因为我们想要: 根字体大小(px) / 屏幕宽度(px) = 32 / 750
所以: 根字体大小(px) = 32 / 750 屏幕宽度(px)
一个元素的宽度(px) / 屏幕宽度(px) = 定值
→ 根字体大小(px) 元素的宽度(rem)/ 屏幕宽度(px)
→ 32 / 750 屏幕宽度(px) 元素的宽度(rem)/ 屏幕宽度(px) 等于什么??
得到的的是一个与屏幕大小无关的定值!
化简: 元素的宽度(rem)32 / 750 = 元素的宽度(px) / 750 -- 不就是设计稿上面的比例么!!!
验证以上操作出来的结果是否符合预期也很简单:
比如一个 img 的宽, 高, 在 iphone6 上的尺寸(审查元素的大小! px 单位):
根字体: 16px; postcss 算出来的 rem 值是 2.5rem; 2.516=40px; 实际上也是 40px;
-- 得到元素实际大小 4040(px), 屏宽是 375; 比例是 40/375=0.10667;
在 iphone5 上的尺寸(审查元素的大小! px 单位):
根字体: 13.6533px; postcss 算出来的 rem 值是 2.5rem; 2.513.6533=34.13px; 实际上也是 34.13px;
-- 得到元素实际大小 34.1334.13(px), 屏宽是 320; 比例是 34.13/320=0.10665;
2, 自己项目适配配置(实践)
上的文章讲的理论和方法是可行的, 自己项目的解决方案和他大同小异(主要用 rem):
1, 插件: amfe-flexible + postcss-px2rem
amfe-flexible: 自动根据不同设备改变 data-dpr 的值, 这样就可以根据不同的 data-dpr 设置字体大小不变, 仅放大相应倍数.
postcss-px2rem: 打包的时候把项目里面的 px 统一转换成 rem, 转换的基准值根据配置设置的(.postcssrc.JS)
/ 因为我是以 750px(iphone6)宽度为基准, 所以 remUnit 为 37.5/
经过试验结果:
postcss-px2rem: 只负责把项目里面的 px 按照基准值转换成 rem, 并不负责根节点动态 font-size 的计算.
例如, 代码里面有个高度固定: 180px, 基准值是: 37.5, 那最后界面上的 rem=180/37.5=4.8rem
不管换不同客户端手机, 不同分辨率, 界面上都是固定 4.8rem[rem 的值是固定的, 根据根节点的 font-size 不同, 在界面显示的 px 也不同] , 界面上显示的 px = 16(没有设置 font-size 的话默认是 16px)* 4.8rem = 76.8px
[那么这个基准值: 37.5 怎么来的:
rem 基准值计算
关于 rem 的基准值, 也就是上面那个 37.5px 其实是根据我们所拿到的视觉稿来决定的, 主要有以下几点原因:
1. 由于我们所写出的页面是要在不同的屏幕大小设备上运行的, 所以我们在写样式的时候必须要先以一个确定的屏幕来作为参考, 这个就由我们拿到的视觉稿来定; 假如我们拿到的视觉稿是以 iphone6 的屏幕 width=375px 为基准:
- ar docEl = document.documentElement;
- var width = docEl.getBoundingClientRect().width;
- var rem = width / 10;
这样计算出来的 rem 基准值就是 37.5(iphone6 的视觉稿), 这里为什么要除以 10 呢, 其实这个值是随便定义的, 因为不想让 HTML 的 font-size 太大, 当然也可以选择不除, 只要在后面动态 JS 计算时保证一样的值就可以
]
上面的组件只负责转换 rem, 并没有根据不同设备设置 font-size, 下面再加入这个组件 amfe-flexible:
不同设备下的 font-size 不同.
来源: https://www.cnblogs.com/both-eyes/p/10106021.html