标签">
详解标签
我们拿到一个设计稿,以iPhone7为基准的,
好的,我们按照习惯在html插入标签
但是,当我们在css里面设置
@media screen and (min-width: 300px){
#myDiv{
width:200px;
height:100px;
}
}
}时,发现是下面的效果,这显然和目标的样式不匹配。
或许,有人说,应该把200px除以2,设置成100px,的确,这样可以达到目标要求,但是为什么这样可以呢?
我们先说说上述<meta>标签以及css中的媒体查询
@mediascreenand(min-width:300px),@mediascreenand(min-device-width:300px)
这里的viewport,width=device-width,initial-scale究竟是什么意思,怎么起的作用呢?
css里面的min-width,min-device-width又究竟是何物?
visual viewport:可以在通过window.innerWidth获取,表示浏览器窗口可以显示出多少个CSS像素,所以是以px为单位的。
layout viewport:布局视口,顾名思义,就是html的宽度,移动端有自己的默认布局视口宽度,是980px,之所以这样设计的目的是为了让PC端的网页可以在手机上显示出来而不变形,这个布局视口宽度是可以自己设定的。可以通过document.documentElement.clientWidth来获取。
width=device-width:这里的width是布局视口的宽度,device-width是设备以常规CSS像素为单位时可以显示的宽度,是一个出厂后就固定的值,比如iPhone7就是375px。这句话就是把默认的980px的布局视口变成了和浏览器一样宽,比如375px。
scale:我们知道CSS像素是一个抽象的单位,一个CSS像素等于几个设备像素和设备的DPR有关,当然,CSS像素是可以缩小放大的,scale就是对本页面的CSS像素进行缩放。比如,在iPhone7上,设备像素比是2,那么一个CSS像素就代表着2个设备像素,而添加initial-scale=0.5后,一个CSS像素就等于一个设备像素了,就是说,插入<metaname="viewport"content="width=device-width,initial-scale=.5,maximum-scale=.5,minimum-scale=.5,user-scalable=no">后,布局视口就变成了750px了。
min-wdith:自适应时,常用到@media query,这里的width就是指布局视口layout viewport的宽度,如果插入了<metaname="viewport"content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">的话,此时的布局视口宽度就是设备宽度,那么就可以直接用min-width来区分不同的设备了,比如iPhone7是375px,而iPhone7Plus是414px。
好的,我们来测试一下你是否理解了。
1号代码:
const scale = 1/window.devicePixelRatio;
document.querySelector('meta[name="viewport"]').setAttribute('content','width=device-width,initial-scale=' + scale + ',minimum-scale=' + scale + ',maximum-scale=' + scale + ',user-scalable=no');
上面这段代码,在iPhone7下,会有什么样的作用?这样做的目的是什么?
我们回到上面那个iPhone7的设计稿,我们知道,单单插入<metaname="viewport"content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no"> 这个标签之后,CSS里设置div的宽为200px,出现的效果是下面这样的:
这显然和我们的目标效果是不对的,思考为什么会这样?
>>因为我们设置了布局视口layout viewport的宽度是375px。>>那么我们怎么样能达到目标的比例呢?>>因为iPhone7的设备像素比是2,所以如果我们把布局视口的宽设置为750px,那么此时div的宽再设置为200px,将会和我们目标的比例一致,当然,可以把设计稿的元素宽度除以2来设置,但是碰到111px这种除以2会得到55.5px的宽度时,会出现偏差。所以,可以插入content="width=device-width,initial-scale=.5,maximum-scale=.5,minimum-scale=.5,user-scalable=no">,通过缩小一个CSS像素代表的设备像素来使得layout viewport布局视口变成750px;
这样,可以看到效果是符合我们目标的:
但是,这是在iPhone7设备像素比为2的情况下的,如果像iPhone7plus这种设备像素比为3的情况下呢?我们想要维持和设计稿一样的比例,就要把缩放比例设置为0.33333....。这意味着在不同设备中要设置不同的缩放比例,这很麻烦。回到上面1号代码,显然是可以根据不同的设备像素比来动态设置缩放比例的。
这样做会有什么问题?我们前面说过,@media query中的min-width是layout viewport布局视口的宽度,我们看看采用1号代码后的iPhone7和iPhone7plus的布局视口宽度。
iPhone7:751px;
iPhone7plus:1242px。
理论上,在7和7P上访问的网页应该是一样的手机端版本,但是假如你这时设置区分手机和PCmin-width分别是400px和1200px,显然7P会显示和PC(当然是正常的PC网页)上一样的网页。因此这个时候,想要区别手机端和PC端还是使用min-device-width吧。
当然,一般情况下, 在移动端,我们对除了文字以外的其他元素会设置以rem为单位。对上述1号代码来说,只需要再增加
document.documentElement.style.fontSize = document.documentElement.clientWidth/10 + 'px';
这样一行。还是假设我们拿到的是iPhone7的设计稿,此时,一个rem代表75px(前面已经说了,此时的布局视口宽度是750px),那么200px转换成rem为单位时,只需要200/75即可。不用担心这是在iPhone7下的设计稿到其他手机上会不会比例不对。因为,我们这样做,实际上是把页面规定了为10rem宽,div和页面的比例也是定了的。
这样一想,即使没有1号代码,只要规定了页面的宽是几个rem值,再确认比例不就可以了吗?像这样,采用普通的标签,
<metaname="viewport"content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
再配合
document.documentElement.style.fontSize = document.documentElement.clientWidth/10+'px';
这行代码,然后把div以rem为单位设置,同样可以实现在不同设备上的比例相同的效果。没错,是可以,但是回到在iPhone7上宽200px的那个比例上去,这时应该设置为多少rem呢?这时的fontSize是37.5px,所以需要200/2/37.5,这样就比较不方便了,对吧。采用1号代码以后,计算比例只需要把200/75,计算比较方便。
上面是规定了页面宽为10rem,假如我们规定页面宽为7.5rem,那么在750px里面是200px的div,rem值就应该是2rem,对吧,这样计算起来更加方便。
总结:1.viewport、width等的具体含义就不再多说了。
2.以某一个手机为设计稿、rem为单位设置之后,不必担心换了设备之后比例就不对了。因为动态设置fontSize之后,以rem为单位就固定了比例。
3.采用1号代码的目的就是拿到设计稿可以直接用里面div的像素值,例如200px,直接除以75(iPhone7的设计稿)计算得到比例值。不采用1号代码的情况下,建议规定页面为7.5rem(iPhone7设计稿),这样直接除以100得到div的宽。
表达不清或是有误的地方,欢迎指正讨论,特别是layout viewport宽度这块,有权威的说法烦请指导。