内容简介:编者按:本文作者李松峰,资深技术图书译者,翻译出版过40余部技术及交互设计专著,现任360奇舞团高级前端开发工程师,360前端技术委员会委员、W3C AC代表本文是“H5必知必会”系列第二篇。在第一篇“不能不说,这个现象很神奇。也许,在前端行业之外人的眼里,手机屏幕上的网页就应该有一个跟大屏幕上的网页不一样的名字,这样才好区分。事实上,就算是在前端开发行业内,有这么一个词让我们瞬间就可以定位到一种应用形态,至少也是一件非常便利的好事。
编者按:本文作者李松峰,资深技术图书译者,翻译出版过40余部技术及交互设计专著,现任360奇舞团高级前端开发工程师,360前端技术委员会委员、W3C AC代表
本文是“H5必知必会”系列第二篇。在第一篇“ H5必知必会之与App交互 ”中我们提到过,所谓“H5”本来应该是HTML5的简称。但是,在中国,“H5”并不是HTML5的简称那么简单,它更多地被用于指代内嵌在手机App中的网页。无论国外有没有“H5”这个说法(应该没有),反正在国内只要说到App内嵌的网页或网页应用,你完全可以说它是“H5”。一说“H5”,产品经理、设计师、Android/iOS应用开发者、后端工程师全都明白。
不能不说,这个现象很神奇。也许,在前端行业之外人的眼里,手机屏幕上的网页就应该有一个跟大屏幕上的网页不一样的名字,这样才好区分。事实上,就算是在前端开发行业内,有这么一个词让我们瞬间就可以定位到一种应用形态,至少也是一件非常便利的好事。
那么手机上的网页跟大屏幕上的网页有什么不同呢?
首先,手机上的网页运行在手机浏览器或者App内嵌的WebView中,可以使用手机特有的硬件能力,比如GPS、加速计、陀螺仪等传感器;此外,如果加载了宿主App的JSSDK,还可以访问App暴露给网页的各种能力,比如获取登录用户的信息、拍照上传和分享,等等。
其次,手机上的网页布局设计要服从于原生App的界面(UI)设计规范,比如谷歌的扁平化设计Material Design,苹果的人机界面指南(Human Interface Guide)等;总之,手机上的网页看起来必须像原生App的界面,包括使用与原生App一致的布局组件、字体图标、配色方案,乃至交互模式等,比如要支持触摸而非鼠标点击交互。
最后,手机上的网页,特别是运行于App内的网页,构成混合移动应用的一部分,通常都需要与原生App互操作;需要H5与原生应用双方共同商定基础接口,并针对特定的交互场景确定具体的交互模式,包括单向调用还是双向调用,同步还是异步,如何传递数据和凭据,等等。
上述第三点,正是本系列第一篇文章“H5必知必会之一App交互”讨论的内容,感兴趣的同学稍后可以参考。那么今天,本文要讨论的则是上述第二点,即H5在构造页面布局时,如何逼真、像素级还原设计稿。
适配与还原:概念阐述
要说还原,必须先从适配说起。
H5适配手机主要有两个维度:
-
适配不同像素密度
-
适配不同屏幕大小
像素密度,顾名思义就是CSS中的1像素对应多少物理像素。我们以这张iPhone各代屏幕对照图(来源:https://www.paintcodeapp.com/news)为例:
先看iPhone Xs Max和iPone XR。前者屏幕用CSS像素度量是414x896,而用实际渲染的物理像素度量则是1242x2688像素,简单换算可知,1242/414 = 3(或2688/896 = 3)。换句话说,iPhone Xs Max是人们常说的3倍屏(或@3x),即每个CSS像素对应9个物理像素(因为宽高均为3像素)。而iPhone XR呢,则是人们常说的2倍屏(或@2x),每个CSS像素对应4个物理像素。
当然还有1倍屏。上图最后一个iPhone 2G/3G/3GS,就是1倍屏,即每个CSS像素对应1个物理像素。像这种估计市面上已经绝迹的初代iPhone是不用适配的,因为1个CSS像素就对应屏幕上的1个物理像素。(当然,笔记本和电脑外接的大屏幕至今都是1倍屏,所以目前还不需要我们适配像素密度。)
我们常说的适配像素密度,通常指图片如何在3倍屏和2倍屏上显示不失真。当然,适配原则非常简单:1个图片像素对应1个物理像素,图片就不会失真。具体来说,假设原始图片是500x300像素(如image@1x.jpg),那么适配高密度屏的版本则分别是1500x900像素(如image@3x.jpg)和1000x600像素(如image@2x.jpg)。这样才能做到1个物理像素对应到1个图片像素。
当然,也有一个简单粗暴的适配方案,就是针对所有屏幕,都只提供最高清图片。虽然低密度屏幕用不到那么多图片像素,而且会因为下载多余的像素造成带宽浪费和下载延迟,但从结果上说能保证图片在所有屏幕上都不会失真。
适配像素密度的具体技术方案本文就忽略了,因为它不是本文的重点。本文的重点其实是适配不同屏幕大小。适配不同屏幕大小的原则非常简单: 确保页面布局的度量与屏幕大小保持一定比例 。
听起来简单,做起来可不容易。因为这里就涉及还原设计稿的问题了。比如,设计稿宽度通常是750像素:
在这个宽度下,不同页面组件都有各自的度量值,比如,“对音箱说”这个标题的度量为112x28像素:
而标题的上、右、下、左,距离当前组件的边界,分别是38像素、289像素、394像素和289像素:
当然,每个组件与屏幕边界、组件与组件之间,乃至文本大小、间距,在这个设计稿中也都有确定的像素值度量。那么问题来了,面对设计稿中林林总总的像素值,我们如何在H5页面中还原它们?
答案很简单:按比例还原。
仍然以前面的设计图为例,我们知道设计稿假定的屏幕宽度为750像素(实际上多少像素都没问题,因为我们是按比例还原设计稿),而如下面几张图所示,这个圆角矩形组件的宽度是690像素:
它与上方距离为30像素(与左、右边界同样是30像素):
有了这些像素数据,经过简单的数学换算,不难得出:
-
组件宽度占屏幕宽度的百分比为:690/750 = 0.92,即92%;
-
组件上、右、左边距占屏幕宽度的百分比为:30/750 = 0.04,即4%。
好了,现在只要能让浏览器(WebView)按照这个比例去渲染,我们的组件就能做到对设计稿的像素级还原——在750像素宽的屏幕上,组件及其子组件的所有像素度量都能严格与设计稿保持一致!
更重要的是,在屏幕不是750像素的情况下(事实上750像素宽的手机屏幕至今还没出现过,注意我是CSS像素宽度),页面的布局依旧可以按照设计稿的既定比例完美适配,即在大一点的屏幕上,页面的方方面面都会显示得大一些;而在小一点的屏幕上,则整个布局都会按比例缩小一些。
事实上,除了宽度、高度和间距,文本大小(即 font-size )、边框、阴影等度量也可以按这个思路把像素转换为百分比。
好了,以上就是关于适配和还原的概念阐述。接下来,我们从理念到实践,看一看技术上如何实现吧。
一个全局性CSS单位
上一节概念阐述提到按比例适配可以做到像素级还原设计稿。但是,实践中可以直接在CSS里使用百分比单位吗? 很可惜,不能 。
我们知道,根据CSS Values and Units Module Level 4(https://www.w3.org/TR/css-values-4/#percentages)的定义:
百分比值总要相对于另一个量,比如长度。每个允许使用百分比值的属性,同时也要定义百分比值参照的那个量。这个量可以是相同元素的另一个属性的值,也可以是祖先元素的某个属性的值,甚至是格式化上下文的一个度量(比如包含块的宽度)。
那我们也知道:
-
宽度( width )、高度( height )、间距( maring / padding )支持百分比值,但默认的相对参考值是包含块的宽度;
-
边框( border )不支持百分值;
-
边框圆角半径( border-radius )支持百分比值,但水平方向相对参考值是盒子的宽度,垂直方向相对参考值是盒子的高度;
-
文本大小( font-size )支持百分比值,但相对参考值是父元素的 font-size 的值;
-
盒阴影( box-shadow )和文本阴影( text-shadow )不支持百分比值;
-
……
可见,即使支持使用百分比值的属性,其百分比参考值也都不是我们想要的屏幕宽度!换句话说,要实现屏幕级的适配,必须有一个统一的全局性单位供我们参照。我们有吗?有。
首先,有一个 rem 。同样,根据CSS Values and Units Module Level 4(https://www.w3.org/TR/css-values-4/#font-relative-lengths):
(rem)等于根元素(也就是 html 元素) font-size 属性的计算值。
rem 归根结底是一个 font-size ,但却是一个全局性的度量单位,而且其背后还是像素。如果为了适配目的,根据不同屏幕密度动态修改 rem 的值(比如, document.documentElement.style.fontSize = rem + 'px' ),不就可以实现按比例适配了吗?事实上,阿里手机淘宝团队专门为此研发了一个框架:https://github.com/amfe/lib-flexible。从Github仓库来看,这个框架用了大概有两年多时间,2019年年初正式宣布退役。因为又找到了新的更好的全局性参照单位: vw 。
什么是 vw ?同样根据CSS Values and Units Module Level 4:
(vw)等于初始包含块(html元素)宽度的1%。
换句话说,可以认为: 1vw 就等于屏幕宽度的 1% 。哇,这个单位似乎是专门为我们适配量身打造的。首先,它本质上就是一个百分比单位,比如 3vw 就相当“屏幕宽度的3个百分点”;其次,它又是全局性的与屏幕宽度直接相关的单位。那么上一节概念阐述中举的两个百分比的例子,用 vw 单位可以直接写成:
-
组件宽度占屏幕宽度的百分比为:690/750 = 0.92,即 92vw ;
-
组件上、右、左边距占屏幕宽度的百分比为:30/750 = 0.04,即 4vw 。
那么移动浏览器对 vw 的支持度如何呢?根据caniuse.com(https://caniuse.com/#search=vw):
即iOS 8+和Android 4.4+都支持 vw ,而目前的手机应用通常支持iOS 9+和Android 5+。所以,实践中使用 vw 单位完全可行。而这也正是手机淘宝团队今年年初正式转向使用 vw 单位适配的原因。
那么,现在唯一的问题就是人工进行设计稿的 px 到 vw 单位的转换太麻烦。不过,如果你在开发中使用Webpack编译打包,那么已经有人开发了postcss的插件:postcss-px-to-viewport(https://www.npmjs.com/package/postcss-px-to-viewport)。配置好这个插件,你写CSS的时候可以严格按照设计稿上的像素值去写,这个插件负责将你写的 px 转换为 vw 。这样一来,我们所说的“像素级还原设计稿”,就彻底打通了开发和呈现,真的做到了“像素级”!
(假如,我只是说假如你没有或不能使用Webpack打包,那么你可能还需要人工计算。)
使用postcss-px-to-viewport
这一节实际是没有必要的。不过,为了完整起见,我们就简单说一下postcss-px-to-viewport插件的配置。以下内容截取自.postcssrc.js配置文件:
module.exports = {
"plugins" : {
// ...
"postcss-px-to-viewport" : {
viewportWidth : 750 ,
viewportHeight : 1334 ,
unitPrecision : 3 ,
viewportUnit : 'vw' ,
selectorBlackList : [ '.usepixel' ] ,
minPixelValue : 1 ,
mediaQuery : false
} ,
// ...
}
}
其中几个配置项的含义如下:
-
viewportWidth:视口宽度,这里设置为跟设计稿宽度一致;
-
viewportHeight:视口高度,随便设置一个就可以;
-
unitPrecision:转换后值的精度,3表示保留3位小数;
-
viewportUnit:转换成什么视口单位,这里当然是 vw ;
-
selectorBlackList:是一个选择符数组,对应声明中的像素单位不会转换;
-
minPixelValue:最小像素值,大于等于这个值才会转换;
-
mediaQuery:是否转换媒体查询中的像素。
最后,我们以一个实例展示结束本篇文章。仍然是本文开头的设计稿,还是那个圆角矩形组件,在我们这个应用里的类名是 .card 。下面是它的CSS源代码:
section.card {
margin : 0 auto ;
margin-bottom : 20 px ;
background-color : #fff ;
border-radius : 10 px ;
box-shadow : 0 6 px 6 px 0 rgba ( 0 , 0 , 0 , 0.02 ) ;
text-align : center ;
padding : 38 px 70 px 46 px ;
font-weight : 300 ;
}
没错,所有这些 px 值都从设计稿中实测得到的(事实上是标注页面自动给出的)。而经过postcss-px-to-viewport插件转换之后,可以看到这些值都被转换成了相对于视口宽度的 vw 单位:
结束语
作为“H5必知必会”系列的第二篇,本文主要从两个方面讨论了如何高保真还原设计稿,同时适配形态各异的手机屏幕。首先,我们从理论或概念上先搞清楚了适配和还原的内容和目。H5适配主要分适配不同像素密度和适配不同屏幕大小。而适配的目的是为保证用户体验,比如图片不失真;以及在不同大小的屏幕上呈现比例相同的页面布局,这也就是所谓的百分之百还原设计稿,或像素级还原设计稿。
明确了适配和还原的含义及原理,接下来技术实现层面的关键是找到一个全局性的CSS单位。我们先介绍了阿里手机淘宝团队基于 rem 的适配框架(这个框架除了动态修改 rem ,还解决了真1像素边框的问题),然后介绍了基于更普适的 vw 单位实现适配。最后简单介绍了自动实现 px 到 vw 单位转换的插件postcss-px-to-viewport的配置。
看到这里,读者可能会不由自主地猜测这个系列第三篇的主题是什么?是讨论H5如何使用手机或宿主App赋予它的特殊能力吗?我也不知道。因为也有可能会跟大家分享多版本下的H5部署与运维策略。当然,还有可能会写一写基于某个脚手架快速从头搭建一个H5项目以及实现前端工程化。总之,未来有多种可能。其实我也想知道大家都想看哪个主题?如果你有想法,那欢迎留言吧。
关于奇舞周刊
《奇舞周刊》是360公司专业前端团队「 奇舞团 」运营的前端技术社区。关注公众号后,直接发送链接到后台即可给我们投稿。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 掌握web开发基础系列--物理像素、逻辑像素、css像素
- 【译】只用 CSS 就能做到的像素画/像素动画
- 透明度叠加算法:如何计算半透明像素叠加到另一个像素上的实际可见像素值(附 WPF 和 HLSL 的实现)
- 开源人工智能算法一种新颖的超像素采样,网络深层特征估计超像素
- WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码
- canvas像素画板
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
程序员代码面试指南:IT名企算法与数据结构题目最优解(第2版)
左程云 / 电子工业出版社 / 109.00元
《程序员代码面试指南:IT名企算法与数据结构题目最优解(第2版)》是一本程序员代码面试"神书”!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现。针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近300道真实出现过的经典代码面试题,帮助广大程序员的面试准备做到接近万无一失。"刷”完本书后,你就是"题王”!《程序员代码面试指南:IT名企算法与数据结构题目最优解(第2版)》......一起来看看 《程序员代码面试指南:IT名企算法与数据结构题目最优解(第2版)》 这本书的介绍吧!