在接触移动端开发的时候,适配是必须要解决的一个问题。个人在开发过程中,也是边做边学,使用了一些常用的解决方案,这里一一列举出来:
前提:移动端的适配更多关注的是宽度的适配,也就是说元素在不同设备上通过改变自身宽度来实现在页面的比例一样,这样布局就不会乱掉
1.百分比代替px
在最开始做移动端页面时,能想到的只有使用百分比,简单直接
<style>
body{
margin: 0;
padding: 0;
}
.box{
width: 80%;
background-color: #b0b0b0;
}
.child{
width: 20%;
height: 50px;
background-color: yellow;
}
</style>
</head>
<body>
<div class="box">
<div class="child"></div>
</div>
</body>
我们在iphone5和iphone6plus设备上测试,box父元素的宽度是设备宽度的80%,child子元素宽度是box的20%
测量后发现iphone5上box元素宽度是256px,子元素宽度51.19px,iphone6plus上box元素宽度331.19px,子元素宽度66.23px,
元素实现了根据宽度的自动调节来保持布局一致(元素的像素精度略有偏差)
优点:简单、方便
缺点:不适用根据设计稿来开发,并且由于子元素继承了父元素,如果改变了父元素的百分比,子元素的宽度改变也不好控制。另外高度无法适配,局限性较大
2.使用媒体查询
在接触bootstrap的时候,在使用里面提供的组件时,了解到css的媒体查询来实现适配
<style>
body{
margin: 0;
padding: 0;
}
.box{
background-color: #b0b0b0;
}
.child{
background-color: yellow;
height: 50px;
}
@media screen and (max-width: 414px){
.box{
width: 331.2px;
}
.child{
width: 66.24px;
}
}
@media screen and (max-width: 320px){
.box{
width: 256px;
}
.child{
width: 52px;
}
}
</style>
</head>
<body>
<div class="box">
<div class="child"></div>
</div>
</body>
我们使用媒体查询,根据设备宽度分别设置了iphone6plus和iphone5下box和child元素的宽度,从而保证了父元素和子元素的比例一致
优点:可以实现各个移动端适配,并且可以设置高度和其他各种样式,在制作响应式布局时具有强大的功能
缺点:只是为了适配来使用媒体查询,比较麻烦,需要写很多的判断,杀鸡用牛刀的感觉....
3.使用rem
在学习vue项目开发时,大佬们提出了px转rem,来解决适配问题,一个预加载器px2rem-loader
我们可以自己动手写一个这样的功能,来实现px自动转rem。核心是要用到scss的function功能,以及给document元素的DOMContentLoaded事件添加一个事件处理程序,动态计算根节点font-size
用rem和vw方法时,我们需要一个参考标准,也就是设计稿要先按照iphone5、iphone6、iphone6plus等等中的一个做为标准。
比如我们以iphone6为标准 375*667
我们创建一个.scss样式文件
@function px2rem($px){
$rem: 37.5px;
@return ($px/$rem) + rem;
}
.box{
width: px2rem(375px);
height: px2rem(100px);
background: #b0b0b0;
border-bottom: 1px solid red;
}
声明了一个px2rem的函数,$rem变量叫做rem基准值,也是根元素的font-size。这里是根据375/10计算来的,除以10是方便计算。设计稿一般会放大2倍(这个根据设备的dpr),所以我们在样式里的宽度要除2,比如设计稿中的box元素是全屏宽750px,那么样式中box的宽度就要设置为375px。
我们接着再创建一个Adjust.js的文件
var dpr = window.devicePixelRatio;
document.addEventListener('DOMContentLoaded', () => {
document.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';
})
这里是动态设置html元素的font-size,注意这里除10,是和之前$rem那里关联的。如果那里设置3.75,那么这里就要除以100
我们引入Adjust.js和.scss样式文件,在不同设备下查看
可以看到box元素的宽度适配了iphone6和iphone5。
设备的dpr不一样,比如iphone6是2,iphone6plus和iphoneX是3,那么如果美术每次给了dpr不一样的设计稿,我们还要计算后才能在样式中写入,岂不是很麻烦?(其实一般都是iphone6,放大2倍,这里只是引入一个技巧...)
我们是否可以根据设计稿大小直接写,不用计算?
记得写H5页面的head中都会有这么一句:
<meta name="viewport" content="width=device-width, initial-scale=1.0">initial-scale=1.0的意思是缩放为1。我们通过js改变这个缩放不就可以了?比如iphone6下,我们把initial-scale设置成1/2,这样当我们把box的宽度写成750,那么实际显示就是375。
通过window.devicePixelRatio可以获取到设备的dpr
Adjust.js文件修改一下:
/* 动态设置fontSize */
var dpr = window.devicePixelRatio;
document.addEventListener('DOMContentLoaded', () => {
document.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';
})
document.getElementsByTagName('meta')['viewport'].setAttribute('content', 'initial-scale=' + 1/dpr + ', maximum-scale=' + 1/dpr + ', minimum-scale=' + 1/dpr + ', user-scalable=no,width = device-width');
.scss文件也做下对应修改:
@function px2rem($px){
$rem: 75px;
@return ($px/$rem) + rem;
}
.box{
width: px2rem(750px);
height: px2rem(100px);
background: #b0b0b0;
border-bottom: 1px solid red;
}
我们直接写设计稿上box的宽度,基准值那里改成75,大功告成~
4.使用vw
这里贴上大漠老师在vue项目中使用vw实现移动端适配的讲解https://www.w3cplus.com/mobile/vw-layout-in-vue.html
差不多目前学到的适配方法这么多,这里只是记录下,积累知识。