前言
在移动端页面设计开发时,遇到最头疼的问题就是字体大小以及各种奇葩累的间距和大小需求了。首先是屏幕问题,现在主流的移动设备以安卓和IOS为主,我们在制作移动端页面也是以兼容这两种设备去布局。就拿说 iPhone,不得不说iPhone的屏幕考虑到了我们开发者的难处,从而给出iPhone屏幕的dpr都是整数值,在6plus出现之 前,iphone的dpr始终是2(物理像素/逻辑像素=2),即使是6plus出现了,iphone到底其实也就只有2,3这两个dpr。其实 6plus的实际dpr并不是整数,而是2.87左右,不过,为了方便开发者来开发,iphone6plus对其做了一个调整,将dpr调整为3,然后在 对屏幕进行了一个缩放。所以我们很容易对其做到兼顾。而安卓的dpr值,并不像iphone那样就只有两个值。安卓的dpr是千奇百怪的,可能是1.5,2,3,4,2.5等等的都有。(甚至我还看到了1.7之类的,安卓的各个设备商,玩的真尼玛high啊。怎么高兴怎么来。)虽然网上有各种各样的解决方案,但是都会有多多少少的BUG或者弊端。最常见的使用就是REM,vw,或者直接以PX来写。以下是个人日常开发总结的经验,不足地方请指正。
rem解决方案最优解
rem 是 根元素 html字体大小的倍数,只跟根元素字体大小有关。如果浏览器默认字体是 16px (根元素html的font-size = 16px),那 1rem = 16px;计算方式是 fontsize(HTML)*值(rem),当然这个数字可以是 小数,但是不能为负数。当然建议最大的字体都需要设置到12以上,切所有的字体尽量设置为双数。以前还遇到过更奇葩的需求,字体是10px。最终参考了澎湃新闻的解决方案使用transform: scale,没办法需求就是如此。这里也多提一嘴,平时多看多读,互联网大厂的代码,可以发现很多意想不到的解决方案。就拿手淘的flexible.js,来说简直是神一样的存在。好用,解决方式简单粗暴,而且手淘现在依旧在使用。解读玩源码,整体思路就是基于不同的drp设置不同的HTML fontsize值。有了值,即可通过计算适应网页布局里面的间距,行高等。至于字体大小,大家知道,现在PC端主流的字体大小都是类似12px、14px、16px,几乎没有13、15、17这样的数字出现,至于为什么,问,就是咱就这么横,这是咱们最后一丝尊严了。如果我们用rem做为字体单位,那么转成px的时候,势必会出现奇数或者小数的情况,为了避免这种情况,我们还是要用px做为字体的单位。那么又如何用px去当作字体大小呢?
div { width: 1rem; height: 0.4rem; font-size: 12px; // 默认写上dpr为1的fontSize } [data-dpr="2"] div { font-size: 24px; } [data-dpr="3"] div { font-size: 36px; }
默认写个dpr为1时的字体大小,然后根据不同dpr下的值去匹配不同的字体大小。flexible会获取设备的dpr值,然后在html标签上自定义data-dpr属性,并放入dpr值,后面的font-size就是动态设置一个rem单位的大小。其实我觉得这种方案挺恶心的,每个牵扯到字体的大小就必须多些几套去兼容,但这也算是个方案。但是flexible中动态设置dpr时,只对iPhone进行了处理,完全没有把安卓放在眼里,那安卓怎么办?这里我又想吐槽安卓那些 厂商,真尼玛瞎搞,dpr设置成各种非主流数值,玩死我们这些码农了,连flexible都不想管了。吐槽到此为止,那么该怎么改良它,让它能对安卓手机 也能动态设置dpr呢?我们将这段代码改一下:
if (!dpr && !scale) { //devicePixelRatio这个属性是可以获取到设备的dpr var devicePixelRatio = win.devicePixelRatio; //判断dpr是否为整数 var isRegularDpr = devicePixelRatio.toString().match(/^[1-9]\d*$/g) if (isRegularDpr) { // 对于是整数的dpr,对dpr进行操作 if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { dpr = 3; } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){ dpr = 2; } else { dpr = 1; } } else { // 对于其他的dpr,人采用dpr为1的方案 dpr = 1; } scale = 1 / dpr; }
我们对这里做了一点点修改,即来判断dpr是否是规则的,也就是是否是我们常见的1,2,3等,然后,我们只对规则的dpr,来进行一个字体的 处理。这样,iphone依然还是用之前的匹配方案。而其实目前安卓,很多的设备还是比较常见的dpr了,所以我们这里,将之前对设备的判断,转变成对 dpr是否是整数的一个判断。其他地方不变,可以解决对安卓dpr的部分匹配。基本这个解决方案能解决90%的移动端布局和字体问题。缺点是需要动态计算。
PX解决方案
记得应该是weui的设计方案里提到过,建议移动端字体建议以PX来写,缺点也很明显CSS代码会成倍的增长,因为要写各种各样的@media查询。类似
html { font-size : 20px; } @media only screen and (min-width: 401px){ html { font-size: 25px !important; } } @media only screen and (min-width: 428px){ html { font-size: 26.75px !important; } } @media only screen and (min-width: 481px){ html { font-size: 30px !important; } } @media only screen and (min-width: 569px){ html { font-size: 35px !important; } } @media only screen and (min-width: 641px){ html { font-size: 40px !important; } }
如果你不设置html的字体大小,就会使用16px作为基数来。这个比px的好处显而易见,你不需要对每个元素就进行一次@media,只需要对html根元素做不同尺寸的设置就可以了,优点是兼容性很好。但是代码量增加的有点多。
vw实现移动端适配
这个方案是一次阅读网易首页时候看到的,比如我们准备开发一个宽度为640的网页,而基础字体我们设置为10px。那么我们就可以这样计算:10/640=0.015625。因为vw是一个百分比,所以再乘以100,变成1.5625vw。今天看了小米的首页貌似也是使用的vw来设置默认的HTML fontszie。这么设置之后,p的宽度就随着屏幕高度的变化而变化,它的高度就随着屏幕宽度的变化而变化,字体的大小也随着屏幕变化。我这么搞是为了更直观的表示vw这个单位的灵活。再也不用写一堆连七八糟的@media了。怎么个灵活法呢?比如你设置一个p的宽度是屏幕的50%,那么width就是50vw。这时候,你要设置它的高度是它的宽度的50%,如果不用vw咋办?你只能用js去算。但是用了vw就直接设置成25vw就搞定了。但是这个有些兼容性的问题,ios是没有问题的,安卓手机自带浏览器要安卓系统4.4以上才行,别的浏览器都是可以的,只有自带的有问题。 不过现在谁还用安卓自带的浏览器去耍呢,在哪儿都找不到。所以,直接用vw、vh吧。代码参考
/** * 响应式字体设置 */ html { font-size: 13.33333vw } @media screen and (max-width:320px) { html { font-size: 42.667px; font-size: 13.33333vw } } @media screen and (min-width:321px) and (max-width:360px) { html { font-size: 48px; font-size: 13.33333vw } } @media screen and (min-width:361px) and (max-width:375px) { html { font-size: 50px; font-size: 13.33333vw } } @media screen and (min-width:376px) and (max-width:393px) { html { font-size: 52.4px; font-size: 13.33333vw } } @media screen and (min-width:394px) and (max-width:412px) { html { font-size: 54.93px; font-size: 13.33333vw } } @media screen and (min-width:413px) and (max-width:414px) { html { font-size: 55.2px; font-size: 13.33333vw } } @media screen and (min-width:415px) and (max-width:480px) { html { font-size: 64px; font-size: 13.33333vw } } @media screen and (min-width:481px) and (max-width:540px) { html { font-size: 72px; font-size: 13.33333vw } } @media screen and (min-width:541px) and (max-width:640px) { html { font-size: 85.33px; font-size: 13.33333vw } } @media screen and (min-width:641px) and (max-width:720px) { html { font-size: 96px; font-size: 13.33333vw } } @media screen and (min-width:721px) and (max-width:768px) { html { font-size: 102.4px; font-size: 13.33333vw } } @media screen and (min-width:769px) { html { font-size: 102.4px; font-size: 13.33333vw } }
总结
个人建议使用REM的解决方案,大厂背书,使用者多,第二种方式适合JS基础较差的小兄弟们使用。最终都能完美解决问题。