网上很多都说会pc网页开发,也就会了mobile网页开发。那么实际呢也是如此,但是对于新手来说却摸不着头脑无从下手,一直纠结于适配的问题,那么这里就来展示下rem适配。
展示rem适配代码
//rem适配
(function () {
var styleN = document.createElement("style");
var width = document.documentElement.clientWidth/16;
styleN.innerHTML = 'html{font-size:'+width+'px!important}';
document.head.appendChild(styleN);
})();
这什么意思呢?就是把手机屏幕分成16份,每份设置为font-size,就是每份代表1rem。
那我们要怎么用呢?直接在代码中引入普通js一样就可以了。
那写css的时候要怎么写呢?写css的时候根据设计师给的图 宽度/16 就是1rem了,这又是什么意思呢?可以这么理解:
如果设计师给的图是750px;那么1rem就是750/16=46.875px;也就是1rem代表46.875px;那如果在css中要写
.box{
width:60px;
}
要怎么写呢?这么写
.box{
width:1.28rem;
}
呃呃,这个1.28怎么来的?60px/46.875px*1rem = 1.28rem就是这么来的。
晓得没呢,那这样是不是每一个px转rem都要这么算呢?
没错,就是都要这么算,那是不是很麻烦呢,哈哈,不要着急,这个时候呢就有了less编译等
这里就以less编译举个例子:
index.less
@rem:46.875rem;
body{
width: 60/@rem;
}
编译后
index.css
body {
width: 1.28rem;
}
其他适配方案:
第一种方法:考虑了m端屏幕旋转的问题.对兼容性做出了一定的处理,具体看代码
export function rem (doc, win) {
let docEl = doc.documentElement; //考虑以及兼容了 屏幕旋转的事件
let resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
let recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if (clientWidth >= 750) {
docEl.style.fontSize = '100px';
} else {
docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';
}
}; if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false); // 屏幕大小以及旋转变化自适应
doc.addEventListener('DOMContentLoaded', recalc, false); // 页面初次打开自适应
recalc();
};
第二种方法:采用html标签的offsetWidth长度计算
export function rem() {
var fz = document.querySelector('html').offsetWidth / 7.5; //设计图 750 1rem=100px
document.querySelector('html').style.fontSize =
fz <= 100 ? fz + 'px' : '100px'; window.onresize = function() {
rem();
};
};
第三种方法:采用window.innerWidth计算,设置了body fontSize防止字体继承,使页面字体过大
export function rem() {
document.documentElement.style.fontSize = window.innerWidth / 7.5 + 'px'; //1rem = 100px
document.body.style.fontSize = '14px';// 在body上将字体还原大小,避免页面无样式字体超大
}
现在回过头来看,感觉自己以前写复杂了,其实道理很简单;
就是利用vw,rem随屏幕,或者跟字体正比变化的特性;
1.就是开发的时候用的750设计稿的尺寸;单位是px;
2.然后编译工具,如postcss 会自动将px单位转成对应rem和vw单位;
3.如果是vw很好转转行,比如写的40px;40/750 vw就完了;
4.如果是rem就多一步罢了;要用js计算出根字体大小,并设置给html;
*正常是 375 ,16px;所以比例常数就是 : 屏幕尺寸/75032 ,也就是html 根字体 大小;
e.g : postcss将40px转化成rem单位; 1rem/(屏幕尺寸/75032) = x/40*
x 就等于 40/(屏幕尺寸/75032) rem;*
*动态改变(屏幕尺寸/75032) 这个 根字体 就可以动态适应屏幕了!
看了一周的rem手机适配方案;搞的脑壳痛;现在总于搞明白了!建议一次性看完本片文章再去百度相关知识点!不要离开!
基础点:rem相对根节点字体的大小。所以不用px;
根字体:字体的大小px;
px:你就当成cm(厘米)这样的东西吧;
基准:750设计稿;
这是方案的基础理论,在这个基础上,我们还要搞明白,到底要干一件什么事情!
目标一 、手机适配:就是页面上的尺寸,无论高度,还是宽度,还有字体,随屏幕的宽度变化!这里是屏幕宽度!是不是想到了vw,对,就是这个意思;——最大程度在各个尺寸屏幕上还原设计稿
目标二、px转换成rem:一般UI给的设计稿宽度大小是750,所以,我们想直接写上面UI标记的尺寸;——最大程度减少工作
为什么选择rem?
很久之前没有vw,怕vw的兼容问题,就用了rem;也就是:rem的兼容性>vw的兼容性;(vw的适配方案!非常简单!);
还有一种就是自己写百分比,不但要自己算哭,而且很不优雅(我以前就是这样干的,有时候为了让高度和宽度的百分比一样,我还把高度写成0,{padding:40%,width:40%,height:0})。
一、理论基础!
实现目标一
用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: 建议自行百度;
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代码去动态获取屏幕宽度!
超级麻烦的一种方案推荐:(可以自己用淘宝弹性布局方案lib-flexible实践; 或者看flexible.js 移动端自适应方案 - 简书;其实这js的作用就是帮你根据屏幕大小——动态改变根字体大小和data-dpr值!但是rem的值还是要你自己算哦,或者用其他工具!)
三、rem——开始干!
第一步,先用vue-cli快速构建出一个项目,然后,安装postcss,postcss-pxtorem,postcss-loader,postcss-import,postcss-url;看不懂的同学看这个吧(如何在Vue项目中使用vw实现移动端适配(转) - 简书)
第二步,在项目根目录下添加.postcssrc.js文件,在里面写上
module.exports = { plugins: { 'postcss-pxtorem': { rootValue: 32, propList: ['*'], minPixelValue: 2 } }};
就完了。简单解释下,免得你们百度半天,建议自己在npm官网上看postcss-pxtorem的文档。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大小和屏幕大小成正比变化!是不是很简单 } window.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;看不懂的同学看这个吧(如何在Vue项目中使用vw实现移动端适配(转) - 简书)
第二步,在项目根目录下添加.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.5*16=40px; 实际上也是40px;
——得到元素实际大小 40✖️40(px), 屏宽是375;比例是40/375=0.10667;
在iphone5上的尺寸(审查元素的大小!px单位):
根字体:13.6533px; postcss算出来的rem值是2.5rem; 2.5*13.6533=34.13px; 实际上也是34.13px;
——得到元素实际大小 34.13✖️34.13(px), 屏宽是320;比例是34.13/320=0.10665;