关于移动端页面适配性的摸索
第一次写这种技术博客,感觉自己语言组织地很混乱,排版也不够清晰,不知道到底表达出来我的意思没有...
看了这篇文章的朋友,请多多包涵,有问题的地方也烦请指出。感谢!
对于刚开始接触前端的程序猿来说,写页面的适配性估计是最头痛的一件事。
现在市面上有众多的手机种类,也就存在众多不同的手机分辨率。所以一个页面要想适配所有手机的分辨率,在我当时看来,真的是一件很难的事情。当时公司为了这个,专门买了几款比较经典的手机用来作为测试机,专门测试页面的适配性。但是即使这样,也不可能照顾得到市面上的所有手机。
我们大概是这样一路走过来的:
一、入门方法
写页面的适配性,最入门的方法应该就是媒体查询了。针对不同分辨率的手机,专门写一条媒体查询去针对性的调整某些css样式。这种方法很容易就会产生出大量的媒体查询代码块,使得页面的可读性变差,并且容量也大了很多。
@media (min-width: 320px) and (max-height: 416px) { /*iphone4*/ ... } @media(max-width: 320px) and (min-height: 504px) { /*iphone5*/ ... } @media (min-width: 375px) and (max-height: 603px) { /*iPhone 6*/ ... } @media (min-width: 414px) and (max-height: 672px) { /*iPhone 6p*/ ... } @media (min-width: 360px) and (max-height: 519px) { /*Android*/ ... }
二、进阶方法
上面的办法我们一直用了很长时间,那段时间的前端效率确实低到一种境界了。直到后来我对rem这个css单位的深入研究之后,才开始有了转机。
什么是rem单位。简单的说,rem就是一种相对长度单位,它是相对于页面根元素(html)的font-size来计算出的长度单位。举个栗子吧:
<html> <head> <style> div { width: 1rem; height: 1rem; } </style> </head> <body> <div></div> </body> </html>
在这个例子中,div的长宽会被浏览器设置为16px。
好了,那么原理是什么呢?因为rem是以根元素(html)的font-size属性为基础计算出来的长度,那么在这个例子中,html元素的font-size我们并没有设置,所以默认为16px,然后因为width和height都设置为1rem,所以最终长度为 16(px) * 1(rem) = 16(px)。
到这里,我们就有了解决适配性的思路:只要让html的font-size属性跟随页面宽度进行成比例变化,那么元素中设置的rem长度换算出来的px长度可以跟随页面宽度也成比例变化。公式为:f(font-size) = a(比例) * W(页面宽度),length = f * rem。
上面的描述比较抽象,还是来举个栗子吧:
假设前端设计图的宽度是640px,其中有一个长度为200px的输入框。我们设定当页面宽度为640px时,html的font-size属性值为40px,即上述f=aW公式中a的值为f / W = 0.0625。那么这个输入框的长度用rem表示就应该是rem = length / f = length / aW = 200(px) / (0.0625 * 640(px)) = 5rem。
如果页面宽度变成了320px,则我们让html的font-size属性也跟随变化为f = aW = 0.0625 * 320 = 20px,对于这个长度为5rem的输入框来说,实际计算出来的长度为20(px) * 5(rem) = 100(px)。这样就可以看到,设置为固定rem长度的输入框,在不同页面宽度下,实现了等比例缩放的效果。
上个效果图吧。
在实际项目中,为了让html的font-size属性能够跟随页面宽度变化,我找了一个js来达到这个效果。
自动计算font-size的js代码:
(function (doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize', recalc = function () { var clientWidth = docEl.clientWidth; if (!clientWidth) return; docEl.style.fontSize = 20 * (clientWidth / 320) + 'px'; }; if (!doc.addEventListener) return; win.addEventListener(resizeEvt, recalc, false); doc.addEventListener('DOMContentLoaded', recalc, false); })(document, window);
三、高阶方法
在采用了上面这种方法之后,项目的大部分页面都不再存在适配性的问题了。但是在个别比较特殊的页面上,由于px长度只能是整数,就会刚好因为取整时产生的1px的差距,导致整个页面的显示出现错位的现象。所以我个人认为应该还有一种高阶的方法,这种方法需要UI同事的配合,在设计页面上,尽量预先划分好各个板块的功能,在某些内容会变动、可能需要弹性伸缩的地方预留空间;而在另外一些必须按原比例显示的地方,就不要设计有可能变动的内容。同时也要求前端同事在分析页面的布局时,尽量能针对不同的内容来选择不同的布局方式。