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元数据,最典型的元数据规则是:

<meta name="viewport" content="
  width=device-width,
  initial-scale=1.0,
  minimum-scale=1.0,
  maximum-scale=1.0,
  user-scalable=no
">

实际书写的时候应该写成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. 在<head>最顶部写上一个没有content的元数据:

    <meta name="viewport" id="viewport">
    

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

    <script>
    var initialscale = document.documentElement.clientWidth / 360;
    document.getElementById('viewport').content = "width=360, initial-scale=" + initialScale + ", maximum-scale=" + initialScale + ", minimum-scale=" + initialScale + ", user-scalable=no"
    </script>
    

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而已。

<script>
var initialscale = document.documentElement.clientWidth / 750;
document.getElementById('viewport').content = "width=750, initial-scale=" + initialScale + ", maximum-scale=" + initialScale + ", minimum-scale=" + initialScale + ", user-scalable=no"
</script>

那么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打开页面也是浏览器全宽,页面傻大到爆炸。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容