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

别再问我手机适配了

时间:2023-03-30 16:15:58 CSS

《别再问我XX的事了》系列:1.别再问我这个方向了。2.跨域移动适配不要问我一般情况下,我们不去深究,因为这种东西配置一次,以后就不用再操心了。收到设计图后,我们照祖传的套路就搞定了。如果你按照步骤去做,你只能成为翻页作家。经过深入研究,您可以成为专业的翻页作家。错综复杂的关系在文章的开头,我们需要弄清楚像素、视口和缩放之间的各种错综复杂的关系,从而破茧成蝶。像素和像素我们写了很多,不就是px吗,为什么要讲呢?因为像素不仅仅是px。DevicePixels设备像素也可以称为物理像素,由设备的屏幕决定。实际上,它们是控制屏幕显示的最小单元。Device-independentpixel设备无关像素是一种可以被程序控制的虚拟像素,对应web开发中的CSS像素。DPR设备像素与设备独立像素的关系是DPR(DevicePixelRatio),DevicePixelRatio=DevicePixels/DeviceIndependentPixels。这个公式的前提是缩放比例为1,原因在下面讲缩放的时候就知道了。根据这个关系,如果设备像素大于设备独立像素(DPR大于1的设备,我们常说的高清屏或者Retina屏),就会出现一个设备独立像素对应多个设备的情况pixels:手机刚出来的时候,很少有网站是专门适配手机端的,但是用户可以通过手机直接访问PC端的网站,那么如何展示一个网站,不管是不是一个网站PC网站还是手机网站,都是亟待解决的问题。于是,移动端的三种viewport布局viewport、visualviewport、idealviewport就横空出世,成为各种移动端适配方案的基础。布局视口布局视口是html元素上面的一个容器,我们的页面就“安装”在了布局视口中。想想我们经常写的宽度:100%。这个100%是根据什么计算出来的?浏览一下信息,你会看到如果给某个属性一个百分比值,它的计算值是从这个元素的包含块中计算出来的。html元素的包含块是什么?没错,就是我们的布局视口,它是所有CSS百分比计算的根。如果CSS是画笔,那么布局视口就是画布。这个画布有一个默认大小(如果没有手动设置metaviewport),一般在768px到1024px之间,可以通过document.documentElement.clientWidth获取。这样一来,网页的布局就不再受设备大小的限制,即使是小屏幕的移动设备也能容纳PC网站。视觉视口视觉视口是指用户透过设备屏幕看到的区域。可视视口的大小可以通过缩放改变,可以通过window.innerWidth获取。这里有必要说一下缩放。缩放会改变CSS像素的大小。放大时,CSS像素增加,一个CSS像素可以跨越更多的设备像素,视觉视口会变小。什么?放大但视觉视口变小?没错,这是因为视觉视口也是用CSS像素来衡量的,放大就是放大CSS像素。假设屏幕原本需要200个CSS像素来填满屏幕,由于放大,现在只需要100个CSS像素来填满屏幕。full,因此视觉视口的宽度变为100px。虽然缩放会改变CSS像素的大小,但在移动端缩放不会改变布局视口,所以缩放不会影响布局,但会影响PC端的布局。最直观的感受就是,当我们平时在移动端用两指缩放网页时,整个网页的布局并没有发生变化。您可以通过拖动来查看不同区域的内容。一些用户放大网页。这时候字符放大了,但是整个页面的布局都会发生变化。那么既然它与布局视口无关,那么它还有谁与它有关呢?答案是下面要讨论的理想视口。它们之间的计算方法是:缩放因子=理想视口宽度/视觉视口宽度理想视口理想视口是指网站在移动设备中的理想尺寸,这个尺寸就是设备的屏幕尺寸。为什么需要理想视口?首先,让我们来看看目前的情况有多不理想。当我们浏览一个没有经过手机适配的网站时,由于布局视口在768px到1024px之间,整个网站就“画”在了这么大的“画布”上,但由于手机屏幕比“canvas”,所以需要缩小以适应手机屏幕。这样一来,我们在浏览网站的时候虽然可以看到全貌,但是里面的东西却变得很小,需要放大才能看清楚,不太理想。如果不用放大也能看得很清楚就很理想了。回想一下上面那个不尽如人意的解决方案,就是把大画布缩小,装进小屏幕。假设现在画布和屏幕一样大,在这个画布上画画不合适吗?所以总结一下,理想视口就是理想的布局视口,由设置。把它们放在一起理解元viewport元素提供关于页面的元信息,不显示在页面上,可以用来告诉浏览器如何解析页面。可以设置的东西很多,这里只说vieport,它是所有移动端适配方案的基础。首先metaviewport的设置格式为,执行console.log(`layoutviewport:${document.documentElement.clientWidth};visualviewport:${window.innerWidth}`)将得到“layoutviewport:400;visualviewport:400”。此时旋转设备,尺寸变为667(w)*375(h),然后执行console.log(`layoutviewport:${document.documentElement.clientWidth};visualviewport:${window.innerWidth}`)将得到“布局视口:667;视觉视口:667”。结论是:width和initial-scale都会初始化layoutviewport,但是浏览器会取其最大值。设置好idealviewport再回头看,显然width=device-width和initial-scale=1是为了初始化布局视口变成理想的布局视口,只写一个就完了。为什么要把两者写在一起?因为有些浏览器只设置了其中一个,不能保证idealviewport的大小能随着屏幕的旋转正确变化,所以把两者写在一起只是为了解决兼容性问题。舒舒服服地还原移动端的设计图上面说了很多理论知识,其实就是有一个方案,舒舒服服地还原移动端的设计图,做一个专门供移动端访问的页面。经典问题图片这里的图片问题是高清/Retina屏下的图片会显示模糊,因为我们平时使用的图片大多是png和jpg格式的图片,我们称之为位图图片(bitmap),由单个像素组成,缩放会失真。上面讲像素的时候,我说如果这个高清/Retina屏的DPR大于1的话,一个像素跨越多个设备像素,一张位图图像需要一个像素对应一个设备像素才能清晰。所以假设一张100x100的图片在普通屏幕上很清晰,但在高清/Retina屏幕上看起来会很模糊。这是因为原始100x100图片在普通屏幕上的图片像素与设备像素相同。一一对应,但是在高清/Retina屏上,一个图片像素对应多个设备像素,所以图片看起来比较模糊。如图所示,如果一个图像像素对应多个设备像素,那么这些设备像素只能以与图像像素相同的颜色显示,从而导致外观模糊。既然知道了问题的原因,那么解决的办法也就很简单了。位图图像需要一个像素对应一个设备像素才能清晰,所以原来的100x100图片在DPR为1的屏幕上可以清晰显示。如果在DPR为2的屏幕上显示模糊,则放一个200x200的图片在DPR为2的屏幕上,这样一一对应。1pxborder"你看设计图,这条线很细,怎么实现这么粗,看起来很劣质。"没道理,设计图是1px,css也是1px,怎么会这么粗糙呢?一般设计师在画图的时候,都会按照一个尺寸作为标准来画。比如他按照iPhone6的尺寸画了一张图,就是宽度为750px的设计图。这个750px其实就是iPhone6的设备像素。在测量设计图的时候,得到的1px其实就是1个设备像素,而当我们设置时,layoutviewport等于到理想viewport等于375px,又因为iPhone6的DPR是2,写css时1px对应2个设备像素,所以看起来更粗。然后只写0.5px对应1个设备像素。是的,确实是这样,但是很多浏览器不支持0.5px的写法,所以显示不出来,不过没关系。网上有很多方法可以解决这个问题。我不会在这里详细介绍。我只是解释清楚,出现1px边框问题的原因。还原设计图因为PC屏幕一般比设计图大,所以只需要在中央固定一个内容区域来显示设计图的内容,其余留空。但是,手机屏幕大小不一,设计图一般都是根据模型绘制的。比如iPhone6的尺寸,如果设计图不加工直接测量,会出现什么问题?(从左到右分别是iPhone4、iPhone6、iPhoneplus)可以看到在基于iPhone6的设计图上测得的350pxx350px的元素写的是width:350px;高度:350px;在iPhone6上刚好是右、左、右各有10px的空隙,但是小屏的iPhone4有水平滚动条,加号的左右空隙明显比10px大很多,这样的效果不同尺寸的屏幕会与设计图纸不同,这不是我们想要的,我们想要的是不同尺寸的屏幕显示效果与设计图的比例一致。既然你要的是不同屏幕尺寸显示的比例和设计图一致,那么显而易见的适配方案就是比例缩放。(以下代码都是为了说明原理,没有过多详细的考虑和测试,不能在生产环境中使用)说到视口方案中的缩放,首先想到的当然是初始——规模。回忆一下initial-scale的作用:设置initial-scale相当于初始化了visualviewport,会将layoutviewport初始化为这个visualviewport的值。那么我们能否根据设计图按比例缩放布局视口来适配呢?这个方法适配了优点就是简单粗暴,缺点是太简单粗暴了,因为viewport的设置影响了整个世界。这样虽然设计图测量出来的尺寸可以直接写到css中,但是如果有一些地方需要,就不需要按比例缩放了,但是需要设置一个固定的尺寸,比如需要在不同大小的屏幕上显示固定大小的文本,或者你引入了一个库,里面有样式,你不知道他们用什么适配方案来适配,那就看你的了。由于globalviewportscalingin项目,本库的显示效果可能会受到影响。rem方案不同于px,它是一个固定大小的单位,rem是一个相对单位,相对于html标签字体大小的单位。比如html标签的font-size是100px,那么1rem就等于100px。借助相对单位rem,我们也可以达到按比例缩放的效果。这个解决方案不需要缩放视口,所以首先,我们按照约定让布局视口等于理想视口:还是以iPhone6设备像素为标准设计图,宽度为750px。假设以设计图为标准的html标签的font-size为100px,则1rem=100px,则设计图总宽度为7.5rem,总宽度为7.5rem如果设计图为标准,不同屏幕尺寸的总宽度也应该是7.5rem。由于上面设置布局视口等于理想视口,以iPhone6为例,iPhone6的布局视口等于理想视口,那么其布局视口为375px(即总宽度为7.5rem)。现在我们只需要解决当layoutviewport为375px时html的font-size需要设置多少就可以了。很简单,htmlfont-size*7.5=375,那么font-size就是50px。扩展到其他屏幕document.documentElement.style.fontSize=`${document.documentElement.clientWidth/7.5}px`现在我们只需要测量设计图,比如设计图中有一个300px的元素,那么我们写成3rem(因为以1rem=100px为基准,所以这里300px/100就够了)。使用这种方案,我们只对需要按比例缩放的元素使用rem,而对固定大小的元素使用px。这样一来,相对于viewport的方案更加灵活,可以按需使用而不是一刀切。不过这个方案在写CSS的时候可能不是那么直观,成本可能会高一点,不过可以借助构建工具或者less/sass来解决。毕竟现在不用这些工具的项目应该很少吧。增强版rem方案这里说的增强版rem方案其实就是手机淘的Flexible方案(类似于手机高清多屏适配方案)。具体增强了什么?即通过设置视口,然后全局解决1px边框问题。既然1px边框问题是要通过设置视口来解决的,那么设置视口的方式肯定有一些东西:if(!dpr&&!scale){varisAndroid=win.navigator.appVersion.match(/android/gi);varisIPhone=win.navigator.appVersion.match(/iphone/gi);vardevicePixelRatio=win.devicePixelRatio;if(isIPhone){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;}得到的scale用来设置viewport的缩放比例document.write(``),这样现在,对于Retina屏幕,将视口缩放到1/dpr的最终效果是1pxcss像素严格等于1px设备像素,从而解决了1px边框问题。那么为什么缩放只适用于iPhone?请看大魔老师的文章,说说Retina下1px的解决方法。其他rem相关的配置与上面的rem方案类似,这里不再赘述。这种增强版的rem方案最大的好处是解决了1px的边框问题,但是也对视口进行了缩放,仍然面临着与上述视口方案相关的一些影响。为此,方案会为html-dprdocument.documentElement.setAttribute('data-dpr',dpr)设置数据,这样在写css的时候,可以为不同的dpr设置固定大小:.test{width:1rem;高度:2rem;字体大小:12px;}[data-dpr="2"].test{font-size:13px;}[data-dpr="3"].test{font-size:14px;}vwschemevw也是一个相对单位,它是相对于布局视口,1vw是布局视口宽度的1%。rem的解决方案其实就是模拟vw,下面看看vw的使用方法。依旧是熟悉的iPhone6标准设计,宽度为750px。那么1vw=1%视口宽度,按照设计图是100vw=750px,那么1vw=7.5px。设计图中的一个元素是100px,css需要写成Xvw*7.5=100,所以X等于13.3vw。至于计算,可以交给构造工具。详见移动端页面适配的rem解决方案。vw也有优点,不会像rem那么绕口,但是兼容性不如rem。从长远来看,vw最终还是会接手rem,成为移动端适配的主力军,因为它天生就是干这个的。终于没有灵丹妙药了。全局视口缩放方案很粗糙?但是对于要求不高,不需要考虑固定大小的页面,上来就可以全局放大,拿起设计稿就可以写代码了。要求高又想变通的你还怕搭建的小麻烦吗?雷姆计划开始了。不需要考虑兼容性,所以vw的方案直接又优雅,你何不试试看呢?没有好坏之分,只有合适与不合适。最后,如果有不对的地方,请大家指正。