学了移动端适配,写了一些我对移动端适配的思考和推导的过程,如有不对,欢迎指正~
什么是移动端适配?
在不同的移动端屏幕下,页面中的内容都和设计稿一致,都可以按照正常的比例显示,且不失真。
为什么需要进行移动端适配?
以显示一张图片为例,在移动端中,我们可以通过width:100%使图片的宽度适应屏幕的宽度,但高度很难通过百分比设置,如果使用像素px设置,高度则会保持不变,这样就会发生宽度过宽而失真的情况。
如何实现移动端适配?
1. 保证缩放前后的比值为1 : 1
- 缩放前的高度/缩放后的高度=缩放前的宽度/缩放后的宽度
- 缩放前的宽度/缩放前的高度=缩放后的宽度/缩放后的高度
2. rem单位 --> 让其他元素的高度能够随着html的字体大小而改变
- html的字体大小等于1rem --> 例如html的字体大小是20px,1rem=20px
- 其他元素的高度根据html的字体大小进行换算 --> 例如1rem=20px,元素的高度=50px,换算成rem=2.5rem
rem开拓了很好的适配方式,使用rem,即使我们使用的是固定比值的rem,但是只要改变html的字体大小,页面的其他高度就会随之改变。例如我们将高度设置为2.5rem,虽然这个2.5的比值是固定的,但只要rem代表的值不同,那么最终的高度就是不同的。
然而屏幕的宽度多种多样,我们不可能使用固定的html字体大小,因此html的字体大小应该使用JavaScript来动态生成。
那么问题来了:html的字体大小应该设置成多少?或者说,应该设置成什么?这里,我们可以通过保证缩放前后的比值为1 : 1的规律来入手。
适配的逻辑推导——html的字体大小应该设置成什么?
在推理之前,需要知道的是,当前屏幕的宽度是可以通过JavaScript来获取到的。具体方法如下:
- window.innerWidth
- document.documentElement.clientWidth
- document.documentElement.getBoundingClientRect().width
接下来是推导过程:
首先使用 a. 缩放前的高度/缩放后的高度=缩放前的宽度/缩放后的宽度 的思路进行推理(后面简写为高高比值和宽宽比值):
这个思路的核心是,使用宽宽比值来代替高高比值。因为屏幕的宽度能够通过js的方法来获取,而高度很难。既然两者比值相同,就没必要计算高度的比值了。
假设:设计稿的宽度是375px,html的字体大小为20px,设计稿的高度设为2.5rem(也就是50px)。改变后,屏幕为750px,也就是原来的两倍。
问题:750px宽的屏幕,html的字体大小是多少?
这里要强调一下,高度依然是2.5rem,这是不变的,但是此时的2.5rem应该代表100px。所以html的字体大小应该变为20px*高高比值。又因为宽宽比值等于高高比值,也就是说改变后的html的字体大小等于宽宽比值*20,根据以上的假设,可以得到宽宽比值=2。html字体大小等于40。
可以得到公式:document.documentElement.style.fontSize(js设置html的字体大小)=window.innerWidth(当前屏幕宽度)/375*20+'px'
注意:这里不一定要使用375,但是不管使用什么值,得到的比值都是相同的,这一点是不会改变的。
直接将html的字体大小设置成375px,那么就可以进一步简化公式,得到:document.documentElement.style.fontSize=window.innerWidth
也就是说,设置html的字体大小等于当前屏幕宽度就OK了,只是页面中高度的设置,要根据375计算出rem的比值,不方便计算。这个很好解决,我们让375/18.75,得到20,就方便计算了。注意:这个18.75是任意的,可以使用任何的值。
最终的公式:document.documentElement.style.fontSize=window.innerWidth/Ratio(任意数值)
使用 b. 缩放前的宽度/缩放前的高度=缩放后的宽度/缩放后的高度 的思路进行推理(后面简写为前宽高比和后宽高比):
假设:设计稿的宽度是375px,html的字体大小为20px,设计稿的高度设为2.5rem(也就是50px)。改变后,屏幕为750px。
问题:750px宽的屏幕,html的字体大小是多少?
一样的题目,不一样的解法~
和之前一样,高度依然是2.5rem,这是不变的,只是此时的2.5rem应该代表100px。将需要求的html字体大小设为fontSize。因为前宽高比等于后宽高比,可以带入公式并计算:
375/2.5*20=750/2.5*fontSize --> 375*2.5*fontSize=2.5*20*750 --> 得到fontSize=40
将window.innerWidth代替750带入公式,可以推导出window.innerWidth和fontSize的关系:
公式运算:375/2.5*20=window.innerWidth/2.5*fontSize --> 交叉相乘 -->
375*2.5*fontSize=2.5*20*widow.innerWidth
最终可以得到:fontSize=(20*widow.innerWidth)/ 375
和之前一样,将html的字体大小设置为375,可以简化公式,得到:document.documentElement.style.fontSize=window.innerWidth
同样的,375并不方便计算,除以一个数值方便计算。
最终的公式是一样的:document.documentElement.style.fontSize=window.innerWidth/Ratio(任意数值)
适配单位rem转换工具
在GitHub上搜索cssrem,根据提示进行下载安装,可以自动将px转为rem。
配置参数:px_to_rem - px转rem的单位比例,默认为40。这个参数需要自己根据需求手动设置。例如设计稿是375的,除以18.75后,设计稿html字体大小等于20,那这个就设置成20。
注意:这里20的比例,只是当前的设计稿页面,px转rem的比例是20,其他页面的比例依然是不同的,只是js会进行适配。
适配的具体代码
function setRemUnit(){
var docuElem=document.documentElement,
//minWidth和maxWidth用于设置屏幕适配的范围
minWidth=320,
maxWidth=840,
ratio=18.75;
viewWidth=docuElem.clientWidth || docuElem.getBoundingClientRect().width;
/*设置当屏幕宽度大于最大值或小于最小值时不再适配。
因为viewWidth获取到的是css像素而不是物理像素,因此除以dpr才能得到实际的物理像素进行比较。*/
if(maxWidth&&(viewWidth/dpr>maxWidth)){
//最终的viewWidth要用物理像素乘以dpr还原回css像素的值
viewWidth=maxWidth*dpr;
}else if(minWidth&&(viewWidth/dpr<minWidth)){
viewWidth=minWidth*dpr;
}
//设置html的font-size
docuElem.style.fontSize=(viewWidth/ratio)+'px';
}
setRemUnit();
window.addEventListener('resize',setRemUnit);