今天抽空再写一篇~之前已经做了两个Demo,主要是运用CSS+Html完成的,今天还是来完成一个Demo,搭建一个关于宠物的网站。在开始之前我们先介绍一个知识点,关于适配的。
其实对于学习前端来说,H5手机适配也是一个老生常谈的问题了,当然网上也有大牛给了解决方案,这里我就结合自己的实际情况分析一下这个适配问题。
1.viewport
这是加在之间的,用来缩放屏幕内容的。
控制initial-scale这个参数就可以控制缩放比例,同时注意数值必须在maximum-scale和minimum-scale之间;user-scalable是用来禁止用户放大缩小屏幕的。
2.dpr(设备像素比)
dpr=物理像素/设备独立像素;在页面上可以通过window.devicePixelRatio得到。
设备独立像素就是屏幕的宽度,比如iphone6为365px,iphone为320px.
物理像素就是屏幕上的像素点数。
上图是dpr=2的样子,例如就是一个手机屏幕宽度是360px,但是水平方向上的像素个数达到了720个,像素是显示颜色的最小单位,也就是一个1px里面水平方向塞了两个像素。
3.rem
rem是css的一个单位,html的style中font-size的值为1rem,我们一般把屏幕宽度的1/10作为1rem, 例如屏幕宽度为375px,那么1rem=37.5px;
现在我们就来试一试,根据UI给我们的图,看如何来适配的。
就像画画要先开始描边一样,一拿到设计稿,我们就要先把大概的结构和框架给弄出来,这要用到上面讲到的rem知识点。
上面讲到了1rem=屏幕宽度的1/10,但是这个值是要我们自己去设置的,设置代码如下:
document.addEventListener('DOMContentLoaded', function() {
//设置rem,1rem=屏幕宽度的1/10;
var rem = document.body.clientWidth / 10;
document.querySelector('html').style.fontSize = rem + 'px';
});
我们看设计稿上可以看到图片的大小为176*176,那么我们在页面里面该设置多少呢?
原理是这样的:我们先假设设计稿是一个手机屏幕,屏幕的宽度=750,那么对于设计稿来说,1rem=75px;所以176px=176/75=2.34rem;所以,在页面上,我们需要写的是2.34rem而不是176px;
同理,可以把所有有宽度的标注转换成rem,这样就可以把大概的框架给搭建起来。当然也有一些工具之类的,可以自动转换px成rem,感兴趣的话可以自己去找找。
其实只要会上面基本上就完成一大部分了,那为什么要来一个适配方案呢?
不知道大家有没有发现,上面的例子中viewport我用的是initial-scale=1.0,这样本来是没有什么问题的,但是上面我们还讲到了一点,叫做dpr,主要针对例如iphone的高清retina屏幕,它们的dpr比较高,这样就会有一个显示1px的问题。
上图是在dpr=2(例如iphone6)里面显示1px的情况,因为1px有两个像素点,所以没有充分利用到高dpr的特性,而有些设计师希望的1是一个像素点,而不是1px,就是下图的样子。
所以就会有比较出名的flexible.js,这个是淘宝用到的屏幕适配方案,用到的就是这个。原理也很简单,就是通过window.devicePixelRatio获取dpr,然后将initial-scale设置为1/dpr,就是将屏幕整体缩小dpr倍。
1.想用flexible这套方案注意不能加这句话,因为它的代码里面会检测你是否加了这句话,如果加了,它就不控制了。
2.还要注意的是字体,因为屏幕缩小之后,字体也缩小了,所以要把字体放大,如下:
html[data-dpr='1'] body{
font-size:12px;
}
html[data-dpr='2'] body{
font-size: 24px;
}
html[data-dpr='3'] body{
font-size: 36px;
}
当然这样添加如果比较麻烦的话,我们也可以用sass之类的工具后期批量修改。(这里要注意,字体不能用rem控制,等下会讲到。)
上面的方案很完美啊,很好啊,而且是淘宝用的,那还选择什么呢,用flexible.js方案不就好了。。。
其实我开始也是用flexible.js方案的,但是这个方案是有问题的,问题的关键也是1px问题。
上面左边是flexible.js方案的(字体没做适配,不考虑字体问题),右边是没有用flexible.js的方案。
虽然是满足的设计师的刁钻眼睛,做到了1像素的边框,但是这样的体验真的好吗,用户几乎看不到边框,太细了,看起来很费劲。
所以这个时候,一般的方案反而占了优势。
这个时候有人会说,flexible.js方案采用缩小方式可以提高图片的真实度,不失真。
但实际上不是的这样的,因为我们显示的图片都是用rem或者百分比来表示宽度或者高度的,而决定图片显示真实度的是这一片区域内显示屏的像素的点数,缩放不缩放并不影响这一片区域的像素点,因为区域大小没变。
所以基本上来说,用flexible.js方案的基本上是因为UI设计师对1px问题有强迫症导致的...
但是flexible.js也做了一些其他的事情,比如适配ipad,不能让屏幕的宽度超过540px(因为无限放大会导致比例错乱),如下图。
综上所述,我们不采用flexible.js缩小屏幕的方案,采用1:1屏幕方案,同时采用flexible.js的其他方案。
综合方案相比flexible.js方案添加了,因为flexible.js检测到你用了scale,就用你的scale,而不会根据dpr去缩小屏幕;同时去掉了字体放大的css,实际上变简单了。
其实如果字体用rem适配是可以保证设计稿完美缩放的,但是你想象一下,如果字体用rem之后,在pad上虽然整体不变,但是字就变得巨大无比,看起来是非常吓人的。
(左边是字体rem在pad上效果,右边是字体px在pad上的效果)
那字体又不能用rem,可是我又觉得字体在pad上比较小怎么办?其实一般而言,淘宝,天猫都没有对字体做什么动作,它们的字在大屏手机上是比较小的,但是确实会有一些特殊情况,比如我们就是,我们的用户是年纪偏大的,所以我们的字在大屏手机上是要稍微放大一些的。
这个时候就要用轮到@media登场了。
媒体查询一般是用来做pc和手机端屏幕内容自适应的,这里我们用来做字体缩放。
其实媒体查询的难点就是如何划分屏幕宽度,从300-540,如何划分,如何归类,这个也是要根据具体情况具体分析的。
我这里就简单的按照400,500来划分了,iphone5,iphone6,iphone6s采用<400方案,plus采用400,500之间的方案,ipad采用>500方案
@media (max-width: 400px) {}
@media (min-width: 400px) and (max-width: 500px) {}
@media (min-width: 500px) {}
=> 字体适配
(左边是px正常在pad上的显示,右边是px媒体查询在pad上的显示)。
是不是稍微比正常的大了些?如果你觉得大了或者小了,可以通过调整媒体查询来达到你的效果。
当然,写这个媒体查询其实也是比较麻烦的,这个你可以通过sass或者less去写一些通用模版,这个就等你们自己去摸索了,这里只是给你们提供一个思路。
对于字体的line-height,这个使用rem还是px?其实都可以,看实际情况,比如一个div高度为1rem,你完全可以设置line-height:1rem来达到垂直垂直居中的效果。
这套基础库的移动端适配方案,使用的是手机淘宝团队的flexible.js,具体可以查看大漠老师的文章:使用Flexible实现手淘H5页面的终端适配,在这里我简单的介绍它的工作原理。
首先要了解的是rem,rem指相对于根元素的字体大小的单位。简单的说它就是一个相对单位,当然这可能让你想到em
,但是em
相对于父元素,而rem
是相对于根元素。
举个例子,让我们了解em
与rem
的区别。
/* html元素 */
html {
font-size: 100px;
}
/* html的子元素 */
body {
font-size: 0.8em; // 100px * 0.8 = 80px
font-size: 0.8rem; // 100px * 0.8 = 80px
}
/* body的子元素 */
div {
font-size: 0.8em; // 100px * 0.8 * 0.8 = 64px
font-size: 0.8rem; // 100px * 0.8 = 80px
}
接着让我们看看flexible.js的原理。
flexible.js的原理就是根据屏幕的宽度设置html元素的font-size,具体做法是计算出屏幕的宽度然后除以10,赋给html标签的font-size属性。
举个例子:
如果屏幕的宽度是750px,flexible.js就会设置html的font-size为75px。
然后我们在写所有元素的属性时(margin, padding, width, height等)都以rem为单位,
同样举个例子:
如果屏幕的宽度是750px,flexible.js设置html的font-size为75px,一个按钮在750px的设计稿下width为150px,我们就会把这个按钮的样式写成:
.btn {
width: 2rem; // 150px / 75px = 2rem;
}
假设现在屏幕宽度切换到了640px, flexible.js设置html的font-size为64px,这个按钮的width在640px下的大小其实相当于 2rem * 64px = 128px
让我们来看一下:
150px / 750px = 128px / 640px = 1 / 5
我们会发现在不同的屏幕大小下,这个按钮的宽度相对于屏幕的比例是不变的,这样就可以实现UI元素跟随屏幕大小而变化,从而实现适配。
最后要说明一下,以上只是举例,实际情况稍有不同:
以上这种算法只在屏幕宽度小于540px的情况下发生,这是为了避免在宽屏时,UI元素过大的情况,在大于540px的时候,html的font-size一直保持54px不变。
先说到这吧,下一篇会做个Demo来实际使用下。