当前位置: 首页 > Web前端 > HTML

fen的四种写法-移动端适配解决方案的演进

时间:2023-04-02 13:30:24 HTML

据说刚开始工作的时候开始用rem,后来接触了一段时间灵活的,系统化的支持iOS的retina画面很快就征服了我,最近又看到了大漠之神的VW。所以本文想完成一篇一站式的文章,可以系统的了解前端适配的演进。废话不多说,直接开始。1、什么是前端适配从UI呈现的角度:我们期望不同尺寸的设备,页面能够自适应或者按比例缩放,从而在不同尺寸的设备下看起来协调或者相似。从代码实现层面:我们希望前端适配能够用尽可能简洁的代码实现。最好有一套兼容所有设备的代码,而不是为每个或每个设备写一套解决方案,不要每次都选择最无奈的解决方案(Android和iOS是分开写的)。2.关键词如果你了解这些关键词,你可以跳过这一段。如果后面遇到问题,感觉有点迷茫,也可以回过头来参考一下。2.1Viewport/viewport通俗地说,移动设备上的视口就是设备屏幕上可以用来显示我们网页的区域[1],但不一定是我们能看到的区域。具体分为以下三种。2.1.1VisualViewportVisualViewport:可视视口。这是我们在移动设备上可以看到的部分。移动端通过window.innerWidth获取宽度(仅限移动端,即使是PC端的chrome模拟也会有不同的结果)。2.2.2LayoutViewportLayoutViewport:布局视口。如果把PC端的页面放到移动端,以iphone8为例,如果只显示为可视视口的宽度(375px),那么页面会被压缩,显示会乱,所以移动浏览器决定默认将视口设置为更宽的值,比如980px,这样即使是那些专为桌面设计的网站也可以在移动浏览器上正常显示。[1]其实我们一般不会看到如上图这样带有水平滚动条的界面;在手机上访问页面时,往往是下图这样的:这是因为页面body宽度设置为100%,没有指定具体的宽度造成的,从而使页面按比例缩放。由于用户可以缩放,因此效果很好。2.2.3IdealViewportIdealViewport:理想视口实际上就是设备的可见区域,与可见视口一致。设置IdealViewport的好处是,只要按照IdealViewport设计样式稿,用户不需要能够完美地查看网站内容——既不左右滑动,也不放大缩小。设置理想视口:这段代码表示要布局视口的宽度设置为设备宽度,初始缩放因子为1,最大缩放因子为1,用户不能缩放。2.2像素2.2.1物理像素物理像素:物理像素是显示器(手机屏幕)上最小的物理显示单元。在操作系统的调度下,每个设备像素都有自己的颜色值和亮度值。[2]2.2.2Deviceindependentpixel设备独立像素:又称CSS像素,是我们日常代码中使用的像素。浏览器中所有的长度都是以CSS像素为单位的,CSS像素的单位是px。2.2.3DevicePixelRatioDevicePixelRatio(简称dpr)定义了物理像素和设备独立像素之间的对应关系。比如iOS的retina屏,1个设备独立像素对应4个物理像素。这样的设计可以让画面更加清晰锐利,如下图所示:3.业界的方案是可以的。在LongLongAgo这个前缀之后,终于进入正题了。回到我们的初衷:我们只是想通过一组代码实现一个可以在不同页面大小上显示相似页面的页面。在这方面,主要有三种选择。3.1Rem的解决方案当DPR一致时,px在不同的屏幕尺寸上会显示为固定宽度,这可能会导致我们页面出现滚动条或者不满意。通过rem设置div的宽高,可以通过调整html的font-size,保证页面整体放大或缩小,从而达到页面无论屏幕都能完美展示的效果宽度。例如750*1334的设计稿:这样所有设备的宽度都是7.5rem。只需要将设计稿上的px值除以100就可以得到对应的rem值。网易也采用了这种方法。3.2Flexible.jsFlexible是阿里团队开发的前端适配方案,同样使用rem方式。那么第一种方式其实可以解决前端适配问题,为什么阿里还要开发一个Flexible呢?第一种方法,dpr=1时没有问题,但是在dpr=2或更高的手机屏幕上,由于物理像素的增加,显示空间不足1px。如果采用第一种方式,因为它统一设置了scale为1,那么我们要想达到0.5px,就只能使用transform了。如果有多个这样的样式,代码会变得很麻烦。.scale{position:relative;}.scale:after{content:"";位置:绝对;底部:0px;左:0px;右:0px;border-bottom:1pxsolid#ddd;-webkit-transform:scaleY(.5);-webkit-transform-origin:00;}所以阿里灵活的方案充分考虑了这种情况,动态设置fontsize和scale,让css中的1px等于物理像素中的1px。在IOS下获得最清晰的体验。如果(!dpr&&!scale){varisAndroid=win.navigator.appVersion.match(/android/gi);varisIPhone=win.navigator.appVersion.match(/iphone/gi);vardevicePixelRatio=win.devicePixelRatio;if(isIPhone){//iOS下,对于2屏和3屏,使用2倍方案,其余使用1倍方案if(devicePixelRatio>=3&&(!dpr||dpr>=3)){dpr=3;}elseif(devicePixelRatio>=2&&(!dpr||dpr>=2)){dpr=2;}否则{dpr=1;}}else{//对于其他设备,仍然使用1x方案dpr=1;}scale=1/dpr;}最后iphone8下的页面header设置为:具体可以看《使用Flexible实现手淘H5页面的终端适配》还有一点需要指出的是:Flexible将页面分成100个部分,页面宽度为10rem。对于750的设计稿,我们需要用对应的px数除以75得到。手动计算是愚蠢的。不同的编译器可以下载pix2rem插件(可以直接写px然后自动转换成对应的rem值),直接使用sass或者postcss打包实现同样的功能。总结以上两种rem方法,主要思路是:根据dpr的值修改html的font-size,从而利用rem实现比例缩放。根据dpr的值修改视口,实现1px的直线,但是Flexible也有其局限性。具体表现为:不兼容响应式布局,Android没有处理,导致1px和backgroundImage需要额外处理的问题[4]所以我们有了第三种解决方案——vw。3.3vwvw是基于Viewport窗口的长度单位。CSS3中与Viewport相关的单位有四个,分别是vw、vh、vmin和vmax。vw:是Viewport宽度的缩写,1vw等于window.innerWidth的1%vh:类似vw,是Viewport高度的缩写,1vh等于window.innerHeihgt的1%vmin:vmin的值为当前vw和vh中较小的值vmax:vmax的值是当前vw和vh中较大的值。其实vw方案的写法和flexible方案是一样的——因为flexible其实是通过hack的方式模拟vw的实现。具体写法:对于750px的设计稿,将对应的px值除以7.5得到vw的值。因为这个方法不会改变可见视口的宽度,所以可以和媒体查询通用。此外,它还支持Android上高分辨率屏幕的显示。虽然在部分Android机型上还存在兼容性问题,但我们也可以使用ViewportUnitsBuggyfill,见《如何在Vue项目中使用vw实现移动端适配》总结正如大魔所说,灵活模拟vw的时代已经过去,真正的首席vw又回来了。参考文献:《移动前端开发之viewport的深入理解》《移动端高清、多屏适配方案》《再聊移动端页面的适配》《基于淘宝弹性布局方案lib-flexible的问题研究》《如何在Vue项目中使用vw实现移动端适配》