前端的一大工作内容就是去兼容页面在不同内核的浏览器,不同的设备,不同的分辨率下的行为,使页面的能正常工作在各种各样的宿主环境当中。
而本文的主题--移动端开发的兼容适配与性能优化,就是希望能从一些常见的移动端开发问题出发,厘清Web移动端开发的前前后后,一些技术的发展过程,一些问题的优化手段以及给出一些常见的兼容性问题的解决方案。
首先先聊聊响应式设计,这个与移动端开发有着密切的联系。
响应式设计即是RWD,ResponsiveWebDesign。
这里百度或者谷歌一下会有各种各样的答案。这里一段摘自知乎上我觉得很棒的一个答案:什么是响应式布局设计?[1]
根据维基百科及其参考文献,理论上,响应式界面能够适应不同的设备。描述响应式界面最著名的一句话就是“Contentislikewater”,翻译成中文便是“如果将屏幕看作容器,那么内容就像水一样”。
为什么要费神地尝试统一所有设备呢?
上面一段我觉得已经涵盖了响应式设计的绝大部分,简单总结起来,可以概括为:
响应式设计是ResponsiveWebDesign(RWD),自适应设计是AdaptiveWebDesign(AWD)。经常有人会将两者混为一谈,或者其实根本也区分不了所谓的响应式与自适应。
RWD和AWD两者都是为了适配各种不同的移动设备,致力于提升用户体验所产生的的技术。核心思想是用技术来使网页适应从小到大(现在到超大)的不同分辨率的屏幕。通常认为,RWD是AWD的子集。
AWD:AdaptiveDesign是AaronGustafson的书的标题。他认为AWD在包括RWD的CSS媒体查询技术以外,也要用Javascript来操作HTML来更适应移动设备的能力。AWD有可能会针对移动端用户减去内容,减去功能。AWD可以在服务器端就进行优化,把优化过的内容送到终端上。
一图胜千言。
从定义上而言,RWD是一套代码,适用于所有屏幕。而AWD则是多端多套代码。本文不会过多去纠结响应式与自适应区别,我觉得这两者的本质都是致力于适配不同设备,更好地提升用户体验。
Quora-ResponsiveDesignvs.AdaptiveDesign[2]zhihu--Responsivedesign和Adaptivedesign的区别[3]
区别:优雅降级是从复杂的现状开始,并试图减少用户体验的供给,而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要。降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带。
渐进增强/优雅降级通常是AWD会牵扯到的另一个技术术语。本质上而言即是随着屏幕的大小的改变,功能会一点一点增强。
也通常会用在一些高级CSS3属性上,我们对一些CSS属性进行特性检测,甚至不进行特性检测直接使用。后果是在支持它的网页上该属性正常展示,而不支持它的网页该属性不生效,但也不影响用户的基本使用。
典型的例子是CSS3逐渐被大众认可并被使用,PC端页面开始由IE678向兼容性更好的IE9+,chrome,firefox浏览器转变的时期。我们可以对页面元素直接使用阴影,圆角等属性。对于不支持它的低版本IE而言,没有什么损失,而对于支持它的高级浏览器而言,带给了用户更好的交互视觉体验,这就是渐进增强。
下面会针对一些具体的案例,展开讲讲。第一个是高保真还原设计稿,也就是如何适配移动端繁杂的屏幕大小。
通常而言,设计师只会给出单一分辨率下的设计稿,而我们要做的,就是以这个设计稿为基准,去适配所有不同大小的移动端设备。
在此之前,有一些基础概念需要理解。
一些概念性的东西,大部分人很难一次性记住,或者记了又忘,我觉得记忆这个东西比较看技巧,比如关联法,想象法,把这些生硬的概念与一些符合我们常识的知识关联在一起记忆,往往能够事半功倍。
以iPhone6/7/8为例,这里我们打开Chrome开发者工具:
这里的375*667表示的是什么呢,表示的是设备独立像素(DIP),也可以理解为CSS像素,也称为逻辑像素:
设备独立像素=CSS像素=逻辑像素
如何记忆呢?这里使用CSS像素来记忆,也就是说。我们设定一个宽度为375px的div,刚好可以充满这个设备的一行,配合高度667px,则div的大小刚好可以充满整个屏幕。
OK,那么,什么又是物理像素呢。我们到电商网站购买手机,都会看一看手机的参数,以JD上的iPhone7为例:
可以看到,iPhone7的分辨率是1334x750,这里描述的就是屏幕实际的物理像素。
物理像素,又称为设备像素。显示屏是由一个个物理像素点组成的,1334x750表示手机分别在垂直和水平上所具有的像素点数。通过控制每个像素点的颜色,就可以使屏幕显示出不同的图像,屏幕从工厂出来那天起,它上面的物理像素点就固定不变了,单位为pt。
设备像素=物理像素
OK,有了上面两个概念,就可以顺理成章引出下一个概念。DPR(DevicePixelRatio)设备像素比,这个与我们通常说的视网膜屏(多倍屏,Retina屏)有关。
设备像素比描述的是未缩放状态下,物理像素和设备独立像素的初始比例关系。
简单的计算公式:
DPR=物理像素/设备独立像素
我们套用一下上面iPhone7的数据(取设备的物理像素宽度与设备独立像素宽度进行计算):
iPhone7’sDPR=iPhone7’s物理像素宽度/iPhone7's设备独立像素宽度=2
750/375=2或者是1334/667=2
可以得到iPhone7的dpr为2。也就是我们常说的视网膜屏幕。
视网膜(Retina)屏幕是苹果公司"发明"的一个营销术语。苹果公司将dpr>1的屏幕称为视网膜屏幕。
在视网膜屏幕中,以dpr=2为例,把4(2x2)个像素当1个像素使用,这样让屏幕看起来更精致,但是元素的大小本身却不会改变:
OK,我们再来看看iPhoneXSMax:
上面三个概念(CSS像素、设备独立像素、DPR)是我觉得比较重要的,还有一些其他比较重要的概念PPI、DPI不影响后续的内容,可以自行去加深理解。
OK,到这里我们就完成了一个小的里程碑。我们通常说的H5手机适配也就是指的这两个维度:
适配不同屏幕大小,也就是适配不同屏幕下的CSS像素。最早移动端屏幕CSS像素适配方案是CSS媒体查询。但是无法做到高保真接近100%的还原。
适配不同屏幕大小其实只需要遵循一条原则,确保页面元素大小的与屏幕大小保持一定比例。也就是:按比例还原设计稿
这样,无论屏幕的CSS像素宽度是320px还是375px还是414px,按照等量百分比还原出来的界面总是正确的。
然而,理想很丰满,现实很骨感。实现上述百分比方案的核心需要一个全局通用的基准单位,让所有百分比展示以它为基准,但是在CSS中,根据CSSValuesandUnitsModuleLevel4[4]的定义:
百分比值总要相对于另一个量,比如长度。每个允许使用百分比值的属性,同时也要定义百分比值参照的那个量。这个量可以是相同元素的另一个属性的值,也可以是祖先元素的某个属性的值,甚至是格式化上下文的一个度量(比如包含块的宽度)。
具体来说:
首先,支持百分比单位的度量属性有其各自的参照基准,其次并非所有度量属性都支持百分比单位。所以我们需要另辟蹊径。
在vw方案出来之前,最被大众接受的就是使用rem进行适配的方案,因为rem满足上面说的,可以是一个全局性的基准单位。
rem(fontsizeoftherootelement),在CSSValuesandUnitsModuleLevel3[5]中的定义就是,根据网页的根元素来设置字体大小,和em(fontsizeoftheelement)的区别是,em是根据其父元素的字体大小来设置,而rem是根据网页的跟元素(html)来设置字体大小。
基于此,淘宝早年推行的一套以rem为基准的适配方案:lib-flexible[6]。其核心做法在于:
关于头两点,其实现在的lib-flexible库已经不这样做了,不再去缩放Viewport,字体大小的设定也直接使用了rem
hotcss[7]不是一个库,也不是一个框架。它是一个移动端布局开发解决方案。使用hotcss可以让移动端布局开发更容易。本质的思想与flexible完全一致。
使用flexible/hotcss作为屏幕宽度适配解决方案,是存在一些问题的:
到今天,其实存在很多在flexible基础上演化而来的各种rem解决方案,有的不会对Viewport进行缩放处理,自行处理1px边框问题。
严格来说,使用rem进行页面适配其实是一种hack手段,rem单位的初衷本身并不是用来进行移动端页面宽度适配的。
到了今天,有了一种更好的替代方案,使用vw进行适配。
百分比适配方案的核心需要一个全局通用的基准单位,rem是不错,但是需要借助Javascript进行动态修改根元素的font-size,而vw/vh(vmax/vmin)的出现则很好弥补rem需要JS辅助的缺点。
根据CSSValuesandUnitsModuleLevel4:vw等于初始包含块(html元素)宽度的1%,也就是
简单的一个页面,看看效果,完全是等比例缩放的效果:
vwCodePenDemo(移动端打开):使用vw进行页面适配[8]
当我们使用rem作为长度单位的时,通常会有借助Sass/Less实现一个转换函数,像是这样:
//假设设计稿的宽度是375px,假设取设计稿宽度下1rem=100px$baseFontSize:100;@functionpx2rem($px){@return$px/$baseFontSize*1rem;}同理,在vw方案下,我们只需要去改写这个方法:
//假设设计稿的宽度是375px@functionpx2vw($px){@return$px/375*100vw;}当然,我们还可以借助一些插件包去实现这个自动转换,提高效率,譬如postcss-px-to-viewport[9]
vw现在毕竟还是存在兼容问题的,看看兼容性:
其实已经覆盖了绝大部分设备,那么如果业务使用了且又真的出现了兼容问题,应该怎么处理呢?有两种方式可以进行降级处理:
vw确实看上去很不错,但是也是存在它的一些问题:
当然,两个方案现阶段其实都可以使用甚至一起搭配使用,更多详情可以读读:
上面说到使用vw适配屏幕大小方案,其中有一个缺点就是在Retina屏下,无法很好的展示真正的1px物理像素线条。
设计师想要的retina下border:1px,其实是1物理像素宽度,而不是1CSS像素宽度,对于CSS而言:
然而,并不是所有手机浏览器都能识别border-width:0.5px,在iOS7以下,Android等其他系统里,小于1px的单位会被当成为0px处理,那么如何实现这0.5px、0.33px呢?
这里介绍几种方法:
Retina屏幕下1px线的实现[13]
图像通常占据了网页上下载资源的绝大部分。优化图像通常可以最大限度地减少从网站下载的字节数以及提高网站性能。
通常可以,有一些通用的优化手段:
首先就是上述的第二点,尽可能利用CSS3\SVG矢量图像替代某些光栅图像。某些简单的几何图标,可以用CSS3快速实现的图形,都应该尽量避免使用光栅图像。这样能够保证它们在任何尺寸下都不会失真。
其次,实在到了必须使用光栅图像的地步,也是有许多方式能保证图像在各种场景下都不失真。
在移动端假设我们需要一张CSS像素为300x200的图像,考虑到现在已经有了dpr=3的设备,那么要保证图片在dpr=3的设备下也正常高清展示,我们最大可能需要一张900x600的原图。
这样,不管设备的dpr是否为3,我们统一都使用3倍图。这样即使在dpr=1,dpr=2的设备上,也能非常好的展示图片。
当然这样并不可取,会造成大量带宽的浪费。现代浏览器,提供了更好的方式,让我们能够根据设备dpr的不同,提供不同尺寸的图片。
简单来说,srcset可以根据不同的dpr拉取对应尺寸的图片:
上面1x,2x的写法比较容易接受易于理解。
除此之外,srcset属性还有一个w宽度描述符,配合sizes属性一起使用,可以覆盖更多的面。
以下面这段代码为例子:
sizes=“(min-width:600px)600px,300px"的意思是,如果屏幕当前的CSS像素宽度大于或者等于600px,则图片的CSS宽度为600px,反之,则图片的CSS宽度为300px。
srcset=“photo@1x.png300w,photo@2x.png600w,photo@3x.png1200w里面的300w,600w,900w叫宽度描述符。怎么确定当前场景会选取哪张图片呢?
当前屏幕CSS宽度为375px,则图片CSS宽度为300px。分别用上述3个宽度描述符的数值除以300。
上面计算得到的1、2、4即是算出的有效的像素密度,换算成和x描述符等价的值。这里600w算出的2即满足dpr=2的情况,选择此张图。
当前屏幕CSS宽度为414px,则图片CSS宽度仍为300px。再计算一次:
因为dpr=3,2已经不满足了,则此时会选择1200w这张图。
当前屏幕CSS宽度为1920px,则图片CSS宽度变为了600px。再计算一次:
因为dpr=1,所以此时会选择600w对应的图片。
具体的可以试下这个Demo:CodePenDemo--srcset属性配合w宽度描述符配合sizes属性[14]
此方案的意义在于考虑到了响应性布局的复杂性与屏幕的多样性,利用上述规则,可以一次适配PC端大屏幕和移动端高清屏,一箭多雕。
CSS有个类似的属性,image-set(),搭配使用,效果更佳。
了解更多细节,推荐看看:
字体是很多前端开发同学容易忽略的一个点,但是其中也是有很多小知识点。
首先要知道,浏览器有最小字体限制:
如果小于最小字体,那么字体默认就是最小字体。
在字体适配上面,我们需要从性能和展示效果两个维度去考虑。
而从展示效果层面来说,使用系统字体能更好的与当前操作系统使用的相匹配,得到最佳的展示效果。所以我们在字体使用方面,有一个应该尽量去遵循的原则,也是现在大部分网站在字体适配上使用的策略:
使用各个支持平台上的默认系统字体。
下面就以CSS-Trick[17]网站最新的font-family为例,看看他们是如何在字体选择上做到适配各个操作系统的
{font-family:system-ui,-apple-system,BlinkMacSystemFont,segoeui,Roboto,Helvetica,Arial,sans-serif,applecoloremoji,segoeuiemoji,segoeuisymbol;}font-family关键字对于CSS中的font-family而言,它有两类取值。
其中,sans-serif表无衬线字体族,例如,"OpenSans","Arial""微软雅黑"等等。
关于通用字体族名,在CSSFontsModuleLevel3--BasicFontProperties[18]中,定义了5个,也就是我们熟知的几个通用字体族名:
而在CSSFontsModuleLevel4--Genericfontfamilies[19]中,新增了几个关键字:
我们看看用的最多的system-ui。
简单而言,font-family:system-ui的目的就是在不同的操作系统的Web页面下,自动选择本操作系统下的默认系统字体。
默认使用特定操作系统的系统字体可以提高性能,因为浏览器或者webview不必去下载任何字体文件,而是使用已有的字体文件。font-family:system-ui字体设置的优势之处在于它与当前操作系统使用的字体相匹配,对于文本内容而言,它可以得到最恰当的展示。
OK,简单了解了system-ui字体族。但是像-apple-system、BlinkMacSystemFont没有在最新的标准里出现。它们又代表什么意思呢?
在此之前,先了解下SanFranciscoFonts。
SanFranciscoFonts又叫旧金山字体,是一款西文字体。随着iOS9更新面世,在WatchOS中随AppleWatch一起悄然发售,并且还将在AppleTV上的新tvOS中使用。
SanFranciscoFonts在iOS系统上用于替代升级另外一款西文字体HelveticaNeue。Apple做了一些重要的改变,使其成为平台上更好的,甚至是完美的西文字体。
话说回来。正如每个前端开发人员都知道的那样,将一个功能纳入规范是一回事,将其纳入浏览器又是另一回事。
幸运的是,system-ui的普及很快。Chrome和Safari都可以在各种平台上完全支持它。只有Mozilla和Windows相对落后。
看看system-ui的兼容性,CaniUse--system-ui[20](图片截取日2019-08-13):
仔细看上图的最后两行:
考虑到不同平台及向后兼容,在macOS和iOS上,我们需要使用-apple-system及BlinkMacSystemFont来兼容适配system-ui标准。
SegoeUI是Windows从Vista开始的默认西文字体族,只有西文,不支持汉字,属于无衬线体。
它也表示一个系列而不是某一款单一字体。使用font-family:SegoeUI可以在Windows平台及WindowsPhone上选取最佳的西文字体展示。
Roboto是为Android操作系统设计的一个无衬线字体家族。Google描述该字体为“现代的、但平易近人”和“有感情”的。
这个字体家族包含Thin、Light、Regular、Medium、Bold、Black六种粗细及相配的斜体。
到此,我们可以总结一下了。以CSS-Tricks[21]网站的font-family定义为例子:
{font-family:system-ui,-apple-system,BlinkMacSystemFont,segoeui,Roboto,Helvetica,Arial,sans-serif,applecoloremoji,segoeuiemoji,segoeuisymbol;}上述5个字体族定义,优先级由高到底,可以看到,它们5个都并非某个特定字体,基本的核心思想都是选择对应平台上的默认系统字体。
涵盖了iOS、MACOSX、Android、Windows、WindowsPhone基本所有用户经常使用的主流操作系统。
并且系统字体的优点在于它与当前操作系统使用的相匹配,因此它的文本展示必然也是一个让人舒适展示效果。
当然,上述font-family的定义不一定是最佳的。譬如天猫移动端在font-family最前面添加了"PingFangSC",miui,..必定也有他们的业务上的考虑。但是一些fallback方案向后兼容的思想都是一致的,值得参考学习。
前端工程师的一大工作内容就是页面布局。无论在PC端还是移动端,页面布局的兼容适配都是重中之重。在整个前端发展的历程中,布局的方法也在不断的推陈出新。
简单来说,前端的布局发展历程经历了下面几个过程:
表格布局-->定位布局-->浮动布局-->flexbox布局-->gridbox布局
每一种布局在特定时期都发挥了重要的作用,而每一种新的布局方式的出现,往往都是因为现有的布局方式已经在该时期已经无法很好的满足开发者的需求,无法满足越来越潮流的页面布局的方式。
以Flexbox的出现为例子,在Flexbox被大家广为接受使用之前。我们一直在使用定位+浮动的布局方式。像下面这个布局:
然而,使用flexbox布局的话,只需要:
.container{display:flex;justify-content:space-between;align-items:center;}flexbox的出现,一次性解决了流动布局,弹性布局,排列方式等多个问题。并且它是简洁的,可控的。
再来看一个例子,水平垂直居中一个元素。使用flexbox也许是最便捷的:
.container{display:flex;}.item{margin:auto;}最便捷的垂直居中方式[27]
OK,flexbox已经足够优秀了,为什么gird网格布局的出现又是为什么?它解决了什么flex布局无法很好解决的问题?
看看下面这张图:
一图以蔽之,flexbox:
在现阶段,移动端布局应当更多使用flexbox去完成(相对那些还在使用float布局的),而考虑到未来页面布局的推陈出新。对于Grid布局我们应当像前几年对待flexbox一样,重视起来,随着兼容性的普及,Grid布局也会慢慢成为主流。
好了,本文到此结束,希望对你有帮助:)
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
今年早些时候,抖音悄然上线了一款名为“青桃”的App,Slogan为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素C和E等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为ProjectKuiper卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“AppsbyApple”的网站,展示了苹果为旗下产品(如iPhone、iPad、AppleWatch、Mac和AppleTV)开发的各种应用程序。
特斯拉本周在美国大幅下调ModelS和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(FutureFund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商Globalstar近期向马斯克旗下的SpaceX支付6400万美元(约4.65亿元人民币)。用于在2023-2025年期间,发射卫星,进一步扩展苹果iPhone系列的SOS卫星服务。
据报道,马斯克旗下社交平台(推特)日前调整了隐私政策,允许使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于9月29日生效。新政策规定,可能会使用所收集到的平台信息和公开可用的信息,来帮助训练的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的iPhone新品,具体内容为:“以我对我‘子公司’的了解,我认为iPhone15跟iPhone14不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。