当前位置: 首页 > 科技观察

移动端方法:自适应解决方案和高清解决方案

时间:2023-03-20 10:32:34 科技观察

作者毕业后一直在做前端工作,现在90%的项目都是和移动端打交道的,所以当“移动H5”这两个字的时候写在简历上,肯定会要求自适应方案和高清方案。“自适应”是指一套UI(比如750*1334),在多终端下显示出几乎相同的效果;而“HD”是指由于DPR增强而产生的各种精度适配。这篇文章说说笔者理解的自适应方案和高清方案。先说结论吧。自适应方案rem适配思路选择一个尺寸作为设计开发基准定义一套适配规则,自动适配剩余尺寸特殊适配效果赋予设计效果是历史产物,CSS窗口单元还没有被主流看到浏览器支持原理根据窗口宽度动态调整根元素html的font-size值,设置总宽度为100份,每一份称为一个单元。x,并设置1rem单位为10x缺点需要加载JS脚本,根据设备窗口宽度计算,影响性能影响:自2015年诞生以来,在H5适配领域占有一定比重.相关技术库:flexible、px2rem。vw适配的原理(如上)利用了CSS窗口的特性,总宽度为100vw,每部分为1vw为单位,1rem为单位设置为10vw。缺点是根据view的宽度来计算,所以不适用于平板和pc。影响:2018年发布的方案,目前H5适配主流相关技术库:postcss-px-to-viewport。px+calc+clamp适配的思路是基于CSS的新特性:css变量、calc()函数、clamp()、@container函数实现特性解决rem和vw布局的致命缺陷:丢失像素完善,一旦屏幕低于或高于某个阈值,通常会出现布局移动或文本内容溢出。Damo在2021年提出,最先进,但还没有被各大厂商使用(浏览器对钳位功能的支持率暂时不高)。高清方案像素问题的解决方案。不同DPR下图片的高清解决方案。综上所述,自适应方案是解决各个终端的适配问题,高清方案是解决Retina屏的细节问题。写在前面在讲移动端适配方案之前,先了解一些技术概念。DeviceIndependentPixelsDeviceIndependentPixels(DIP)===CSSPixels===LogicalPixels,在Chrome中直接可见为375*667。在chrome中查看css像素当你看到设备无关像素时,不要惊慌,这就是CSS像素,它的长宽在Chrome中都有。可以这样记,“deviceindependentpixels”,字数比较长,文字是CSS像素,理论上也是人为给定的指标,也叫逻辑像素。物理像素物理像素可以理解为手机厂商在销售手机时标榜的分辨率,即物理像素=分辨率,代表的是垂直和水平方向的像素个数。也就是说,设备屏幕水平方向有1920个像素点,垂直方向有1080个像素点(假设屏幕分辨率为1920*1080),即屏幕分辨率代表物理像素点,设置为出厂,单位为pt,1pt=0.376mm。手机分辨率物理像素,又称设备像素,表示设备像素===物理像素。可以这样记忆,设备在物理世界中可以测量的长度。DPR(DevicePixelRatio)什么是设备像素比(DPR)?DPR=devicepixel/deviceindependentpixel,通常与视网膜屏幕(Retinascreen)有关。以iPhone7为例,iPhone7的DPR=iPhone7物理像素/iPhone7设备独立像素=2.Width1334/667=2Height750/375=2iPhone7的DPR为2,也就是我们常说的视网膜屏,这是一个营销术语。正是因为技术的进步,一个CSS像素被打包成更多的物理像素。还有哪些营销名词:农夫山泉的天然搬运工,元气森林的“氪”。作者是这样记忆的:CSS像素(deviceindependentpixels)就像一个容器。以前是一对一插入的,所以DPR就是1。后来随着技术的发展,一个容器可以插入更多的真实像素(物理像素)。像素)。DPR=设备像素/设备独立像素。DPR=物理像素(真实)/CSS像素(虚拟)。在retina屏幕中,以DPR=2为例,4(2x2)个物理像素作为一个CSS像素,让屏幕看起来更清晰(精致),但是元素(CSS像素)本身的尺寸不会改变.DPR对比随着硬件的发展,iPhone13Pro等手机的DPR已经是3,未来突破4不是问题。说到这里,DPR2或3有什么问题?我们以CSS为最小单位编写代码,并以CSS为最小单位显示在屏幕上。也就是说,当DPR为2时,我们想要模拟1个单位的物理像素是不可能的(如果浏览器支持0.5px的CSS,可以模拟,但是DPR3呢,用0.333px?);又因为手机的设备独立像素(CSSpixel)是固定的,使用传统的静态布局(fixedpx)时,会出现样式错位的情况。iPhone5/SE:320*568DPR:2iPhone6/7/8:375*667DPR:2iPhone6/7/8Plus:414*736DPR:3iPhoneX:375*812DPR:3所以我们需要适配每一个终端的CSSpixel和1-pixel问题以及图片在不同DPR下的高清问题。随着技术的发展,前端摆脱了对IE的兼容,同时陷入了各大手机品牌的兼容沼泽。自适应方案rem布局-天下第二介绍:rem是相对于根元素html的font-size计算的。与rem相关联的是em:当em作为font-size单位时,表示父元素的字体大小,当em作为其他属性的单位时,表示自身的字体大小。rem作用于非根元素时,是相对于根元素的字体大小的。rem作用于根元素的字体时,是相对于其初始字体大小的。本质:按比例缩放是通过JavaScript模拟vw的特性。假设将屏幕宽度平均分为100份,每份的宽度用x表示,x=屏幕宽度/100。如果以x为单位,则x前面的数值代表该部分的百分比屏幕宽度。p{width:50x}/*屏幕宽度的50%*/如果我们想让页面元素随屏幕宽度按比例变化,就需要上面的x,这个x是vw,但是vw只有在浏览器支持后才会变大itScaleuse,在此之前,js+rem可以模拟这个效果。前面说过,rem作用于非根元素时,是相对于根元素的字体大小的,所以我们设置了根元素单位后,非根元素以rem为相对单位。html{font-size:16px}p{width:2rem}/*32px*/html{font-size:32px}p{width:2rem}/*64px*/问题来了,我们需要获取动态根元素字体大小,并相应地更改每个元素的大小。有意思的是,我们两个项目目前的做法是通过媒体查询来设置根元素,分为四级,默认为16px。作者表示不理解这种做法。原开发者说我们的系统已经跑了6年了,UI适配也没人说。这里有一个问题。是不是真的像他说的那样很好适配UI,“媒体查询根元素+rem”也能适配吗?完美吗?笔者稍后会在demo中展示这种做法。但是根元素的字体大小是如何变化的呢?它不能总是16px。中大屏还好,小屏字体太大,也需要动态获取。如何让它动态化,上面说了,让根元素的font-size等于屏幕宽度的1/100。html{字体大小:宽度/100};如何设置html的字体大小等于屏幕宽度的1%?可以通过js设置,一般需要在pagedomready、resize和screenrotation中设置。document.documentElement.style.fontSize=document.documentElement.clientWidth/100+'px';灵活源码的写法同上。我们设置了1%的宽度后,在写css的时候,需要使用css处理器如scss/less来编译处理css。假设给定的设计图是750*1334,一个元素的宽度是200px。根据公式:width:200/750*100=26.67rem在sass中需要设置设计图的宽度进行转换:@use'sass:math';$宽度:750px;@functionpx2rem($px){@return#{math.div($px,$width)*100}rem;}以上编译完成后。div{width:26.667rem}在不同的尺寸下有不同的宽度。型号尺寸widthiPhone5/SE320*568170*170iPhone6/7/8375*667200*200iPhone6/7/8Plus414*736220.797*220.797iPhoneX375*812200*200。效果是如下(特别说明:图中的演示是介绍灵活库,其根元素的font-size为屏幕的1/10)。remlayoutremlayout(flexible)demo优点:rem的兼容性低至ios4.1,android2.1。缺点:成比例放大(可以说优点也可以理解为缺点,用在不同的场景)用户选择大屏有几个出发点,有人想要更大的字体,更大的图片,有人想要更多内容,并且不想要更大的图标。字号不能用rem(一般用mediaquery来控制font-size)。PC端浏览碎图一般都会设置一个最大宽度。varclientWidth=document.documentElement.clientWidth;clientWidth=clientWidth<780?clientWidth:780;document.documentElement.style.fontSize=clientWidth/100+'px';body{margin:auto;width:100rem;}如果用户禁止js怎么办?添加noscribe标记以提示用户将默认字体大小添加到HTML。相关技术方案:flexible(amfe-flexible或lib-flexible)+postcss-pxtorem。Viewport布局--VW非我所生,适应永夜vw是基于Viewport窗口的长度单位,其中视口(Viewport)指的是浏览器的可视化区域,这个可视化区域就是window.innerWidth/window.innerHeight的大小是根据CSSValuesandUnitsModuleLevel4:vw等于初始包含块(html元素)宽度的1%,即:1vw等于value的1%window.innerWidth。1vh等于window.innerHeight值的1%。看图就明白了:在rem布局讲屏幕宽高的时候,曾经举过x的例子,x就是vw。/*remscheme*/html{font-size:width/100}div{width:26.67rem}/*vwscheme*/div{width:26.67vw}vw也可以结合remscheme,所以html的计算字体大小很简单,不再需要js。html{font-size:1vw}div{width:26.67rem}效果如下:vw适配vw适配是CSS原生支持,目前大部分手机都支持兼容,不需要加载js,也不会是因为js导致性能问题。vw看起来不错,但也有一些问题。也未能解决高清屏显示1px边框的问题,需要自己处理。由于vw方案是完全按比例缩放,所以在PC端会失真(和rem一样)。相关技术方案:postcss-px-to-viewport。大众布局演??示。px适配——onepowerdropten不需要rem/vw,传统的响应式布局也可以用在移动端布局上,需要设计规范。使用css变量适配(篇幅原因就不详细介绍了,可以直接看代码)。使用场景:新闻类和内容类网站不适合rem,因为大屏用户希望看到更多的内容,比如网易新闻、知乎、taptapPX+CSS变量demo。.媒体询问——我可以坐下吗?上面说了我们公司原来的H5端是用mediaquery适配的。这件事,可是精力还是绰绰有余的。使用rem、vw、px等方法可以实现非标准尺寸(375*667设计稿)下表头高度为165.59px,由于媒体大屏,所以设置了rootfont-size为17px,header的高度变为159.38px(17*9.375rem)。如下图GIF所示:媒体查询布局与其他布局对比,仅使用媒体查询并不令人满意。媒体查询布局演示。各种适配对比vw和rem适配的本质是按比例缩放,px直接写,哪个更好就看自己了。REMlayoutVWlayoutPX+cssvariablelayout容器最小宽度支持不支持支持支持容器最大宽度支持不支持支持HDdevice1pxborder支持支持支持容器固定宽高比支持支持支持优点1.老式方案。2.当支持高清设备1px边框时,可以直接按常规方式书写。1.无需引入js。2.自然支持,标准文体同VW缺点1.需要引入js设置html的font-size。2.字体大小不能用rem。3.PC端浏览会碎图,一般需要设置最大宽度1.PC端会碎图2.老手机不支持。除了VW,还有一种方案是配合vw和rem来设置根元素的大小随之改变vw的单位随着窗口的变化而变化,动态改变每个元素的大小来限制最大值以及根元素的最小字体大小,结合body加上最大宽度和最小宽度//rem单位转换:75px只是为了方便,750px-75px,640-64px,1080px-108px等等$vm_fontsize:75;//iPhone6size根元素大小基准值@functionrem($px){@return($px/$vm_fontsize)*1rem;}//根元素大小使用vw单位$vm_design:750;html{font-大小:($vm_fontsize/($vm_design/2))*100vw;//同时通过MediaQueries限制根元素的最大值和最小值@mediascreenand(max-width:320px){font-size:64px;}@mediascreenand(min-width:540px){font-size:108px;}}//body也增加最大和最小宽度限制,避免默认100%宽度的块元素跟随body过大或过小。正文{最大宽度:540px;min-width:320px;}高清方案像素问题像素是指在Retina屏幕上显示1个单位的物理像素,这个很容易理解。CSS像素(deviceindependentpixel)是我们人为规定的,当DPR为1时,1个像素(指我们写的CSS像素)等于1个物理像素;但是当DPR为3时,1个像素就是3个物理像素。DPR=1,此时1个物理像素等于1个CSS像素。DPR=2,此时1个物理像素等于0.5个CSS像素border-width:1px,其中1px其实就是1个CSS像素宽度,等于2个物理像素,设计师其实想要的是border-width:0.5像素。DPR=3,此时1个物理像素等于0.33个CSS像素。设计师要的是border-width:0.33px。像素解题思路使用0.5px。有限制,iOS8及以上,苹果系统支持,但iOS8及Android以下(部分低端设备),0.5px会显示为0px。由于1个CSS像素代表2(DPR为2)、3(DPR为3)个物理像素,而设备不理解0.5px的写法,那就画1px,然后想办法把宽度减半。schemegradient实现了background-image:linear-gradient(totop,,,,)。实现缩放变换:scaleY(0.333)。使用图像实现base64。使用SVG实现以嵌入背景url。border-image在低端设备中没有得到很好的支持。以上都是通过CSS媒体查询实现的。@mediaonlyscreenand(-webkit-min-device-pixel-ratio:2),onlyscreenand(min-device-pixel-ratio:2){}@mediaonlyscreenand(-webkit-min-device-pixel-ratio:3),onlyscreenand(min-device-pixel-ratio:3){}图像适配和优化图像通常占据网页下载资源的绝大部分,优化图像通常可以最小化网站下载字节和提高网站性能。通常是的,有一些常见的优化方法:为不同的DPR屏幕提供最合适的图像尺寸。看过很多大厂适配分析的文章,比如:各大厂商如何适配移动端。各大厂商采用rem适配,vm适配,vm+rem组合,纯px方案。新闻、社区等可读性更强的场景:px+flex+percentage比如携程、知乎、TapTap。对于可视化组件类型多、依赖性强的移动端页面:vw+rem比如电商、论坛。总结rem方案,介绍amfe-flexible库。设计:设计图为750*1334,设计图裁好后上传到蓝湖,根据尺寸写px。.开发:使用rem方案,引入amfe-flexible库,安装px2rem等px转rem工具。在项目中配置px2rem写入px,输出为rem,适用于任何场景。使用vw方案安装pxtovw工具,如px2vw。配置px2vw在项目中写入px。输出的时候,vw适用于任何场景。使用px方案随便写,但是因为设计方案,按钮的大小是固定的,Icon大小是标准的和TabBar。高度也是硬编码的。什么都有了标准,写页面就方便了。比如左侧固定为100*50,右侧flex布局左侧固定为100*50,右侧为calc(100%-100px)(使用CSS3中的calc计算)。其他caniuse站点测试CSS属性以解决与浏览器的兼容性问题。问题Q:为什么大部分H5手机端UI库单元使用px?不会有适配问题吗?其实我们写px之后,如果项目使用rem写业务,我们可以引入px2rem(已经六年没有维护了)转换。在有赞vant库中,它对浏览器适配的介绍是:ViewportlayoutVant默认使用px作为样式单位。如果需要使用视口单位(vw、vh、vmin、vmax),推荐使用.postcss-px-to-viewport进行转换。postcss-px-to-viewport是一个PostCSS插件,用于将px单位转换为vw/vh单位。如果Rem布局需要使用rem单位进行适配,推荐使用以下两个工具:postcss-pxtorem是一个将px单位转换为rem单位的PostCSS插件。lib-flexible用于设置rem基值。演示合集:在线演示。参考资料前端基础知识概览——移动开发的屏幕、图片、字体和布局的兼容性与适配Rem布局原理分析说说Retina下1px的解决方案说说移动端页面的适配如何在vueprojectsvw实现移动适配