问题:当前市场上手机屏幕宽度不尽相同,常见有320px(ipone5)、375px(ipone678)等等,而为了在不同宽度的手机屏幕上良好现显示网页,我们需要解决方案。

原理:当前前端解决手机屏幕自适应的手段极多,究其原理,主要分为两大版块:

  一、使用百分比长度单位,当前百分比长度单位一般如下:vw、vh、vm、em、rem、%,优点:一套css代码即可适应所有屏幕宽度不同的手机;

  二、使用固定长度单位px,再使用js根据当前屏幕宽度与固定宽度计算比例,进行网页缩放。优点:网页宽度恒定,便于计算

实现:

  一、使用百分比宽度单位实现移动端屏幕自适应

  我们来聊聊这些百分比长度单位的定义优缺点

  vw:相对于视口的宽度,视口被均分为100单位的vw;即将当前屏幕宽度均分为100份,1vw即为当前屏幕宽度的1%;优点:vw单位长度准确分明,常用此单位,推荐使用此单位

  vh:相对于视口的高度,视口被均分为100单位的vh;即将当前屏幕高度均分为100份,1vh即为当前屏幕高度的1%;基本不用此单位,它的优点vw都有,但是它有一个致命的缺点:手机屏幕高度分成100份后,不是便于计算的数字,譬如iphone5屏幕高568px,此时1vh=5.68px;iphone678屏幕高667px,此时1vh=6.67px;若设计稿一个div宽高皆为100px,你能口算出它的宽高为多少vh吗?我们不可能带着计算器写代码。

  vm:相对于视口的宽度或高度,取决于哪个更小,视口宽度或高度中更小的那个被均分为100单位的vm;即将当前屏幕宽度或高度均分为100份,1vm即为当前屏幕宽度或高度的1%;它的优点vw都有,也曾见有人使用此单位,但我觉得vw比它更好

  em:相对长度单位。相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对于上一个父元素的默认字体尺寸。举例而言,浏览器默认字体大小为16px,在css中设置

html{font-size:15px;}
body{font-size:14px;}

  em将优先使用自身的字体大小,若自身没有设置字体大小,将继承上一个父元素的字体大小,此时没有为当前标签设置字体样式,于是继承body的字体大小,而不是继承html的字体大小,即1em=14px;此单位若要用于屏幕自适应,需与vw配合使用设置父元素的字体大小。于css中进行字体设置譬如:font-size1:4vw;,方可实现屏幕自适应。基本不用此单位,它的优点rem都有,但它是优先使用自身的字体大小,其次继承上一个父元素的字体大小,而我们在使用标签时,经常需要给标签设置字体样式,将导致em的根元素字体尺寸不定,使用起来十分麻烦。

  举例如下所示:

  

  在w3c等教学网站中,他们使用px单位作为em单位的根单位,但是使用px做根单位的em单位是无法实现移动端屏幕自适应的。在移动端中,不推荐将px作为em的根单位

  rem:相对长度单位,相对于根元素(即html元素)内文本的字体尺寸。rem继承且只继承html标签的字体大小。同样的,此单位若要用于屏幕自适应,需与vw配合使用设置根元素的字体大小。必须在css中进行字体设置:

html{font-size:4vw;}

,方可实现屏幕自适应。常用此单位,推荐使用此单位。看到这里,相信很多朋友都会感到疑惑,明明直接使用vw单位即可实现自适应,为何要使用vw单位进行设置后来使用rem单位呢?原因很简单:便于计算。首先,设计师设计的移动端设计稿通常使用750px宽度(契合iphone678的屏幕宽度),前端工程师通常使用375px的网页宽度(在所有手机屏幕宽度中,它是最方便计算的宽度)。此时,1vw=3.75px;而4vw=15px;8vw=30px;那么请问,哪个单位更便于计算?由于30px与375px相除并非整数,我推荐使用15px(即1rem=4vw)。

  当然,这只是我的小技巧,rem单位与vw单位的优先度相差无几,事实上,使用vw单位的人极多,也许比使用rem单位的人更多,全看各人喜好。

  也有人使用px作为rem的根单位,再使用js进行单位缩放,不推荐这样使用,又不是没有rem单位和vw单位用,缩放单位个鸡儿。

  %:基本没人用。原因:单纯使用%无法确定div的高度,若使用%,那么必须搭配px等固定长度单位来确定高度,形如

.a{
  width: 20%;
  height: 20px;    
}

  这样的方式,很容易导致图片等变形。

  二、使用固定长度单位px,再使用js根据当前屏幕宽度与固定宽度计算比例,进行网页缩放,来实现移动端屏幕自适应

   这个方法主要需要用到css3的两个属性:transform、 transform-origin。通过transform属性的值scale可以进行网页缩放,这是根本。另外必须允许网页缩放,否则transform属性会不起作用。

  这个手段简单来说,需要先定一个网页宽度(譬如750px),再通过js获取屏幕宽度,屏幕宽度/网页宽度=缩放比例,然后通过js执行缩放(为标签添加transformtransform-origin属性)。话不多说,直接上代码。

<html>
<head>
    <meta content="width=device-width,height=device-height,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
    <style>
    *{margin: 0;padding: 0;}
    #div1{width: 750px;height: 600px;background-color: red;}
    #div2{width: 375px;height: 300px;background-color: green;}
    </style>
</head>
<body id="body">
    <div id="div1">
        <div id="div2"></div>
    </div>
</body>
<script type="text/javascript">
//id    需要进行缩放的标签id
function suofang(id) {
    var num = 750;//css中固定的网页宽度
    var oWidth = window.screen.width;//获取当前手机屏幕宽度
    var objId = document.getElementById(id);//获取传入的id标签对象
    rate = oWidth / num;//缩放比例 = 当前手机屏幕宽度/css中固定的网页宽度
    if (oWidth < 1920) {
        objId.style.transformOrigin = "left top 0px";
        objId.style.transform = "scale(" + rate + ")";
        /* IE 9 */
        objId.style.msTransformOrigin = "left top 0px";
        objId.style.msTransform = "scale(" + rate + ")";
        /* Safari and Chrome */
        objId.style.webkitTransformOrigin = "left top 0px";
        objId.style.webkitTransform = "scale(" + rate + ")";
        /* Firefox */
        objId.style.mozTransformOrigin = "left top 0px";
        objId.style.mozTransform = "scale(" + rate + ")";
        /* Opera */
        objId.style.oTransformOrigin = "left top 0px";
        objId.style.oTransform = "scale(" + rate + ")";
    }
};
suofang("body");//执行缩放
</script>
</html>

   话不再说,直接上效果:

  事实上,有更简便的方法来缩放网页,即通过js操纵meta标签中的initial-scale(即网页初始缩放比例)属性即可。话不多说,直接上代码。

<html>
<head>
    <meta content="width=device-width,height=device-height,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
    <style>
        *{margin: 0;padding: 0;}
        #div1{width: 750px;height: 600px;background-color: red;}
        #div2{width: 375px;height: 300px;background-color: green;}
    </style>
</head>
<body id="body">
    <div id="div1">
        <div id="div2"></div>
    </div>
</body>
<script type="text/javascript">
//网页缩放函数
function suofang() {
    var num = 750;//css中固定的网页宽度
    var oWidth = window.screen.width;//获取当前手机屏幕宽度
    rate = oWidth / num;//缩放比例 = 当前手机屏幕宽度/css中固定的网页宽度
    if (oWidth < 1920) {
        document.getElementsByTagName('meta')[name="viewport"].content="width=device-width,height=device-height,initial-scale=1.0,maximum-scale=1.0,user-scalable=no,width=device-width,height=device-height,initial-scale="+
        rate+",maximum-scale=2.0,user-scalable=no";//修改meta的属性
    }
};
suofang();
</script>
</html>

   话不再说,直接上效果:

   

  ps:此外,还可以使用媒体适配查询的方法来进行自适应,不过媒体适配查询这个方法一般用于pc端与移动端适应。我想应该没人会这么蠢,单纯为了解决移动端自适应而使用它,毕竟为不同宽度手机屏幕的同一个页面的写很多套css实在太蠢了。举例如下:

@media screen and (min-width:1281px) and (max-width:1920px) and (orientation:portrait) {
    html { font-size: 15px; }
}
@media screen and (min-width:320px) and (max-width:1280px) and (orientation:portrait) {
    html { font-size: 73.24%; }
}