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

移动端适配方案

时间:2023-03-30 22:44:08 CSS

在讨论适配方案之前,先了解几个移动端的概念。基本概念设备像素(devicepixels):又称物理像素,是显示器的最小物理单位。在操作系统的调度下,每个设备像素都有自己的颜色值和亮度值。Deviceindependentpixels(设备独立像素):基于计算机控制的坐标系和抽象像素(虚拟像素),由底层系统的程序使用并转换为物理像素。比如在meta中设置width=device-width,这个device-width就是设备的独立像素。在chrome中看到的375x667320x480都是设备无关像素,在数值上等于CSS像素数组。Devicepixelratio:简称dpr,定义了devicepixels和deviceindependentpixels的对应关系。它的值可以根据公式得到:设备像素比=设备像素/设备独立像素。配置:固定高度,使用rem布局自适应宽度,视口缩放vw自适应固定高度,垂直方向固定值自适应宽度,水平方向百分比,固定值或flex。这样设置之后,不管手机屏幕大小都可以开发。这种方法使用了完美视口:但是这种方法有一个缺点,因为高度是固定的,会导致页面横向拉伸的视觉效果。remlayout,viewportscaling这个也是淘宝用的方案。根据屏幕宽度设置rem值。需要适配的元素以rem为单位,不需要适配的元素仍然以px为单位。字体也需要通过CSShacks以px为单位,因为rem可能会导致字体变形或者模糊。以下是淘宝源码分析:;(function(win,lib){vardoc=win.document;vardocEl=doc.documentElement;varmetaEl=doc.querySelector('meta[name="viewport"]');varflexibleEl=doc.querySelector('meta[name="flexible"]');vardpr=0;varscale=0;vartid;varflexible=lib.flexible||(lib.flexible={});//视口的meta标签是否设置过,如果设置过,则根据设置的initial-scale设置scale和dpr;是否手动设置过dpr,如果设置过,则设置scale和dpr根据设置的initial-dpr或maximum-dprdprif(metaEl){console.warn('Thescalingwillbesetaccordingtotheexistingmetatags');varmatch=metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);if(match){scale=parseFloat(match[1]);dpr=parseInt(1/scale);}}elseif(flexibleEl){varcontent=flexibleEl.getAttribute('content');if(content){varinitialDpr=content.match(/initial\-dpr=([\d\.]+)/);varmaximumDpr=content.match(/最大\-dpr=([\d\.]+)/);如果(initialDpr){dpr=parseFloat(initialDpr[1]);scale=parseFloat((1/dpr).toFixed(2));}if(maximumDpr){dpr=parseFloat(maximumDpr[1]);scale=parseFloat((1/dpr).toFixed(2));}}}//如果没有手动设置scale或dpr,则设置android的dpr为1,ios设置设备的devicePixelRatio如果(!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;}规模=1/dpr;}//data-dpr自定义属性在html上设置docEl.setAttribute('data-dpr',dpr);//设置视口if(!metaEl){metaEl=doc.createElement('meta');metaEl.setAttribute('名称','视口');metaEl.setAttribute('content','initial-scale='+scale+',maximum-scale='+scalee+',minimum-scale='+scale+',user-scalable=no');如果(docEl.firstElementChild){docEl.firstElementChild.appendChild(metaEl);}else{varwrap=doc.createElement('div');wrap.appendChild(metaEl);doc.write(wrap.innerHTML);}}//获取设备的宽度,根据宽度计算rem,rem代表html函数refreshRem()的fontSize{varwidth=docEl.getBoundingClientRect().width;如果(宽度/dpr>540){宽度=540*dpr;}varrem=宽度/10;docEl.style.fontSize=rem+'px';flexible.rem=win.rem=rem;}//监听窗口的resize和pageshow事件,实现css风格的重绘win.addEventListener('resize',function(){clearTimeout(tid);tid=setTimeout(refreshRem,300);},false);win.addEventListener('pageshow',function(e){if(e.persisted){clearTimeout(tid);tid=setTimeout(refreshRem,300);}},错误的);//判断document对象是否处于complete状态,如果是complete状态,我们给body一个font-size=12*dpr值,否则判断dom加载方式实现body中的font-size设置这个设置是针对页面中字体的大小,html中的font-size是用来设置页面的高宽等属性的。style.fontSize=12*dpr+'px';}else{doc.addEventListener('DOMContentLoaded',function(e){doc.body.style.fontSize=12*dpr+'px';},false);}refreshRem();灵活的。dpr=win.dpr=dpr;flexible.refreshRem=refreshRem;flexible.rem2px=function(d){varval=parseFloat(d)*this.rem;if(typeofd==='string'&&d.match(/rem$/)){val+='px';}返回值;}flexible.px2rem=function(d){varval=parseFloat(d)/this.rem;if(typeofd==='string'&&d.match(/px$/)){val+='rem';}返回值;}})(窗口,窗口['lib']||(窗口['lib']={}));总结一下,淘宝使用的解决方案其实做了三件事:动态生成视口屏幕宽度和设置rem大小,即根据设备像素比例为设置font-size和为设置data-dpr(window.devicePixelRatio)(对于csshack)设置rem。比如设计图给我们的一个容器的尺寸是7501000,设计图的宽度是150px225px,所以我们在css中的宽度是:150px/750px/10=150px/75px=2rem;高度为:225px/75px=3rem;综上所述,布局时,每个元素的css大小=设计稿尺寸/设计稿水平分辨率/10。settingviewport和data-dpr这两个设置是适合高清屏手机的px单位。缩放是动态的,px在不同设备下显示的长度是一样的。例如设备像素比为2,缩放比例为0.5,data-dpr为2;设备像素比为3,缩放比例为0.3333,data-dpr为3。data-dpr的用法如下图所示,字体大小最好按以下方式设置。[data-dpr="2"]{font-size:26px;}[data-dpr="3"]{font-size:39px;}vw适配现在vw已经被很多浏览器支持了,所以我们可以直接考虑将vw单元应用到我们的适配布局中。vw基于Viewport窗口的长度单位(window.innerWidth/window.innerHeight)。viewport的概念可以参考文章https://www.w3cplus.com/css/v...vw,vh与窗口宽高的关系如下:1vw等于1%window.innerWidth1vh??等于1%window.innerHeight因此,假设以750px的设计稿为例,100vw=750px,即1vw=7.5px。那么我们就可以直接将设计图上的px值转换成对应的vw值。我们可以使用PostCSS插件postcss-px-to-viewport,这样我们就可以直接在代码中写px了。以下情况我们可以使用vw容器适配,我们可以使用vw文本适配,我们可以使用vw边框大于1px,圆角,阴影可以使用vw内外距离,我们可以使用vw