2019年了,实现手机屏幕响应式还不用viewport元数据?

前言

关于手机屏幕响应式编程,从大约从iphone 6时代就开始讨论了,之后的方案是一年一个,如今,都2019年了,也该有个结论了。

以往曾经流行过em方案,后来是rem方案,后来又有vw方案,到最近两年,由于脚手架的逐步进化,加上vue等框架的流行,尺寸现在都流行动态计算,也就是说:

将屏幕宽度假想为750个单位,单位可以叫“rpx”(微信小程序),uni-app里叫“upx”,不过也不要以为uni-app的upx只是给rpx改了改名,毕竟在H5端和APP都是生效的。如果看uni-app生成的H5,会发现,尺寸单位依然是px,显然,所有px值都是由js计算出来的(并不是脚手架生成的静态值)。

这就好玩了,这种方式打脸了一些使用vw、rem的技术方案,因为我就px一万年,依然做得到响应式、自适应,但是它的技术细节就不太容易弄清。

而今天我讲的viewport元数据方案,是最简单,但又没什么明显缺陷的方案。当然,比起uni-app还是差一点,毕竟技术摆在那。

我个人做法是优先用uni-app,简单的H5就用viewport方案,能应付百分之九十九的场景。

viewport元数据方案科普

提起viewport元数据,最典型的元数据规则是:


实际书写的时候应该写成1行,我这里为了方便阅读给做了换行。

这几句是什么意思?可以看我写的《通俗讲解CSS pixels、device pixels、device-width、layout viewport、visual viewport、ideal viewport六个概念》。

好,现在假定你阅读了上文。说白了,device-width就是设备逻辑像素宽度,在最早期就等于320,后面手机越出越多,device-width可能等于360、375、414等等,手机出厂之前就定好了。

viewport元数据方案内容

  1. 以360px逻辑分辨率作为页面宽度标准,以16px作为标准字体尺寸。

  2. 设计师的画布可以为720px,也可以为750px,也可以为1080px,都成,越大则手机显示的画面越细腻。

  3. 除字体之外的尺寸,都根据360px的画布来定px值,比如一个正文页面,正文的留白就可以是12px。完全不用考虑什么rem之类的尺寸单位。

  4. 字体的尺寸,上面说了,标准就是16px,想要小字体就写14px、12px、10px,想要大字体就写18px等等。也完全不用考虑rem之类的尺寸单位。

  5. 加一些代码:
    a. 在最顶部写上一个没有content的元数据:

    
    

    b. 紧贴上文代码,写上:

    
    

viewport元数据方案原理

viewport元数据的牛逼之处就在于缩放。

首先说为什么用360px作为标准,因为360px接近真实的手机宽度,你在电脑上用QQ截图工具量出一个360px长度(别用视网膜屏幕量,这不准),然后你把自己手机贴近电脑屏幕,你会发现360px长度跟手机宽度差不多。

然后,还有一点,就是360px宽度下,用16px作为标准字体,是符合人眼的最舒适感的。如果你要用375px作为标准宽度,那么16px的字就显得比较小,不适合阅读了。当然了,这就纯看你的想法了,因为360px配16px字最佳这句话是我说的,不是公认的,你也可以认为375px配16px字最佳,这就是人眼的感受不同了,就好比有些人喜欢看小字,有些人喜欢看大字,这就不是程序上的“1+1=2”那么死板了。

viewport元数据的作用就是,先把width强行设为360。这时候,很多安卓手机本身就是360逻辑像素,所以还好,但是iPhone最新的手机都是414逻辑像素,这时候,如果不做其他设置,那么iPhone手机上显示的字都是偏小的。然后再给initial-scalemaximum-scaleminimum-scale设一个比例尺,这个比例尺就是动态计算出来的,比如iPhone 6的比例尺就是375 / 360 = 1.04167,这样,浏览器会把整个页面再放大1.04167倍,就实现了各个手机一致的显示效果。

也就是说,屏幕一行永远是显示360 / 16 = 22.5个字,无论你手机多小,还是多大,都是这样的一行22.5个字。而图片呢?比如一张图设了180px宽,那么在小手机是占左半屏那么宽,在大手机上也是占左半屏那么宽。

这样就实现了响应式。

这种方式的实现,源自于浏览器级别的渲染原理,也是最准确的渲染,是最严格意义的放大缩小。

案例

浏览器打开http://common.hebei.sina.com.cn/app/2019/ajsc2019/,然后F12,切换手机模式,先看iPhone 5模式,刷新页面,整个页面是比较小的,元数据是这样:

image.png

然后切换到iPhone 6,刷新页面,页面整体变大,元数据是这样:

image.png

那么,是不是尺寸值都是用的px呢?select一个首页的图片看看:

image.png

可以看到,就是px值,而且是基于360px画布写出来的px值。

发丝线

这个方案不可解决发丝线宽度的问题,想解决发丝线宽度,还是要用发丝线本身的解决方案。

方案缺陷

  1. 不支持viewport的手机浏览器,就不能采用这种方案了,比如安卓古老版本的自带浏览器。但是,2019年了,还有这种手机么?这种手机的使用者又能给你带来多少价值呢?

  2. 设计稿中的px值都要经过换算才能用。怎么办?有2种办法:

    1. 设计规范里面的固定尺寸,和常用尺寸,就直接脑子记住,比如留白,设计稿里是20px,那么我们css里就写10px就可以了,尽管严格说应该写20 * 360 / 750 = 9.6px,但是也没必要那么精确了,10px并不是不可以,只要你坚持用10px就行。

    2. 不在设计规范里的尺寸,要么就简单的口算除以2,想要精确值就可以使用sass计算,我们先定义一个mixin和一个function,mixin用于多个值,fuction用于单个值,各有各的场合:

    @mixin scaler($property, $values...) {
      $resultValues: '';
      @each $value in $values {
        $resultValues: #{$resultValues + $value * 36 / 75 + "px "};
      }
      #{$property}: $resultValues; 
    }
    
    @function scaler($value) {
      @return #{$value  * 36 / 75 + 'px'};
    }
    

    其中36和75根据你的实际情况改。

    使用:

    body {
      @include scaler(margin, 2, 4, 6, 8);
      padding: scaler(5) scaler(10);
    }
    

    结果:

    image.png

    其他css预处理器也同样道理。

    从这个角度说,拿375px作为标准宽度似乎更便于开发,所以尺寸都除以2就好了。总而言之,随你定。

最后一个问题,为什么标准宽度不直接用750px?

标准宽度用750px也是可以的,这样的话,尺寸就可以完全照抄设计稿(如果设计稿是750px的话)。这时候就是字体尺寸怎么写的问题了。

假设我真让标准宽度使用750px,那么字体的标准尺寸就应该是16 * 750 / 360 = 33.33px,约等于34px,作为标准字体尺寸,记下这个尺寸。或者你就用32px作为标准尺寸也是可以的,还是那句话,你们开发者和你们收到的反馈说多少px看着舒服,就用多少px。

比34px字体小一点的字体就可以是32px、30px,依然2个2个的递减。

这时候还有一个问题就是兼容PC端的问题。

上面的例子有一个 http://common.hebei.sina.com.cn/app/2019/ajsc2019/,它是兼容PC端的,在PC端上viewport失效,像素都是PC真实像素,这时候,如果标准宽度是360px,那么它在PC端依然显示360px,跟真实手机的大小是接近的,只要经过简单样式兼容,就可以兼容PC端。而如果是以750px为标准,那么就会在PC端显示一个750px宽度的网页,显然,这是一种傻大傻大的网页,体验会非常差。

所以结论是,如果你打算兼容PC端,那么标准宽度设为360还是375都可以,但不能是750px,如果从来不需要兼容PC端,那么标准宽度设750px完全可以,毕竟跟设计稿尺寸完全一致,不需要换算,是一个优势。

假设你决定了用750px作为标准宽度,那么,下面这段代码依旧必须写,只不过360要改成750而已。


那么uni-app做的H5兼容PC端么?

默认不兼容,需手动改造可以实现兼容。

如果所有的组件都是以upx为单位开发,那么只需要限定body宽度为375px,同时为了把fixed元素约束在375px内,需要给body加上transform: translateZ(0)(原理见如何让position: fixed不再基于浏览器窗口定位?)。

如果有些尺寸使用了upx之外的单位,那就麻烦大了,兼容性比较难调,有一个办法是做一个居中的、375px宽、浏览器那么高的iframe,嵌套你的H5,也可以实现PC端兼容。

vw、rem方案兼容PC端么?

至少市面上的方案默认不去考虑PC端,也就是说PC打开页面也是浏览器全宽,页面傻大到爆炸。

所以如果要兼容也需要另外考虑,就不多说了。

你可能感兴趣的:(2019年了,实现手机屏幕响应式还不用viewport元数据?)