好久没有写博客了,刚好说说最近遇到的移动端布局问题吧。
本来一直是觉得我的页面布局能力还是不错的,当然,是相对于较基础的来说还是不错的。不过,自己写的案例终归是跟实际开发有区别的,自己写案例的是觉得这个样式有时候并没有那个完美就放弃那个效果了。到后来 ,发现这是一个很不好的习惯,一直想着小毛病不去解决,想着以后总归是会的。结果在实际开发的时候,发现这个太影响工作效率了。的确,很多小问题百度都能解决,只是,小毛病一多你就会发现你写一个项目的时候一直都在百度。。。
今天,就来讲讲之前遗留下来的一个问题吧。
其实在很早的时候就已经接触过rem这个单位了,说这个单位在移动端很好,是综合了px跟em的有点什么什么的。然后我去百度大概看来一眼,发现看不懂,好绕。。。然后就留着了,想着先放着再说。直到最近开发公司开发微信端项目的时候,发现整个人都不太好了,就拿其中一个小部分来说吧。页面的需求是要开发一个九宫个样式的页面(大概就是下面这个样式),
乍眼一看,感觉很简单啊,不就几个正方形吗,宽等于高就好了。不过实际需求是要能做到在不同分辨率的手机下都能实现这个效果。移动端要实现自适应,第一反应就是百分比布局,这时候,宽度设置成百分之三十三点三三就好了,不过这个高度就出问题了,宽度可以根据百分比来设置,可是这高度就不行了。于是我找了个投机取巧的办法,给每个div里面再塞了一个正方形的图片,然后让图片不显示。这样,这个效果就实现了
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> * { margin: 0; padding: 0; } ul { list-style: none; } li { float: left; width: 30%; background-color: white; margin-left: 1%; border: 1px solid #000; background-color: #ff3589; margin-bottom: 5px; } img { width: 100%; visibility: hidden; vertical-align: middle; } </style> </head> <body> <ul> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> </ul> </body> </html>
这个方法怎么说呢,勉强算是实现效果了,不过对于实际开发来说,毛病实在太多了,首先,无缘无故就多了九个img标签,对于一个前端工程师来说,这段代码是写的很失败的。用html的标签来写了一个样式,而且,虽然格子的问题是解决了,可是细心的人还发现,这里每个格子之间还有个相等边距,这个就不肯能再靠img来撑起高度了。没办法,我就只能选择用写死高度的办法来解决这个问题了。只是写死高度后,已经不能做到边距都相等了。其实我不是没有想过用js来动态获取高度,只是不知道为什么,我对这种方式并不是很喜欢,首先,前端的结构,样式,行为分离就没有满足,样式的部分写在了js里面,这对于后期维护来说,是很不利的。退而求其次,哪怕我在这里用js动态获取,宽高再来写样式,可是又怎么能保证不会在页面的其他地方又会出现一个类似的样式呢?难道也用js去写吗?所以说,这个就不是个特别好的方法,我就直接放弃了。这时候,rem布局就又他的用武之地了。我上网上查了下资料,看了一些关于rem的知识,只能说对rem大概有了个认识。
首先,看看rem的官方解释吧:这个单位代表相对于根元素的font-size大小(例如 font-size<html>元素)。当用在根元素的font-size上面时 ,它代表了它的初始值(译者注:默认的初始值是html的默认的font-size大小,比如当未在根元素上面设置font-size大小的时候,此时的1rem==1em,当设置font-size=2rem的时候,就使得页面中1rem的大小相当于html的根字体默认大小的2倍,当然此时页面中字体的大小也是html的根字体默认大小的2倍)。
这是我在MDN上找来的关于rem的解释,也就是说,只要给html元素设置一个font-size,之后的子元素都会根据这个font-size来设置就好了就好了,比如根元素设置了font-size为12px,那么整个页面所有用rem的地方都是他的倍数,比如1rem就等于12px,1.2rem就等于18px。看起来好像很简单的样子,的确,这个单位就是这么简单。可是问题来了,简单是简单了,这单位有什么用啊。。。我给html设置死font-size之后用这个根本没有什么自适应啊,说好的这个单位很强大呢???于是我继续查了下资料,发现好多大网站比如淘宝之类的,都采取了rem布局,淘宝的比较特殊,就先不说了,先说一下最简单的是怎么实现的吧。
在工作中,前端在开发的时候会先拿到一张设计稿,这个通常来说,设计稿一般都是640px的或者750px的。而手机的实际尺寸的话可能是320px宽或者375px宽的,关于更多的尺寸的话,我这里就先不考虑到了,就先说一说比较通用的尺寸。而我们在实际开发中的话,是需要用一个设计稿来满足各种尺寸的屏幕的。通常情况下,我们都会使用百分比布局来适应各个屏幕,的确,百分比布局能解决很多问题了,但是总归会有特例,比如前面这种情况,这时候,百分比布局就显得有些无力了。这时候,就可以用到了rem。先直接看代码吧。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"> <title>Title</title> <script> document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px'; </script> <style> * { margin: 0; padding: 0; } img { width: 6.4rem; } </style> </head> <body> <div style='width: 6.4rem;border: 1px solid #ff3589;box-sizing: border-box; height: 5rem'></div> <img src="wxhbbg.png"> </body> </html>
这段代码不多,最主要的功能就是动态获取屏幕的宽度,然后设置到html标签上。也就是说html的font-size是动态获取的。这里面最大的疑问应该就是这个6.4了,其实这个6.4是设计稿的尺寸除以一百后得来的。为什么要用这个值呢,就要一步步来了,首先假设屏幕的宽度为x,然后把这个值除以6.4赋值给html的font-size之后,1rem就等于x/6.4px,而我们的设计稿是640px的。然后其中可能有一个元素是100px,这时候,这个元素就相当于整个设计稿宽度的六点四分之一。这个时候我们就发现了,这个比例跟前面设置的1rem刚好相同,这时候,布局就简单了,这个元素我们只需要设置1rem之后,他的比例就跟设计稿的一样了。到这里,我们就实现用rem布局来实现页面的自适应布局,这时候,再回到最开始的九宫格问题,就相对来说就很简单了,废话不多说,直接上代码吧。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"> <title>Title</title> <script> document.documentElement.style.fontSize = document.documentElement.clientWidth / 6.4 + 'px'; </script> <style> * { margin: 0; padding: 0; } ul { list-style: none; } li { float: left; width: 2rem; background-color: white; margin-left: 0.1rem; border: 1px solid #000; background-color: #ff3589; margin-bottom: 0.1rem; box-sizing: border-box; } img { width: 100%; visibility: hidden; vertical-align: middle; } </style> </head> <body> <ul> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> <li><img src="bb.jpg" alt=""></li> </ul> </body> </html>
这里有一点要解释一下,就是在设置了这个rem布局之后,就已经不怎么适合用rem来设置字体了。对于字体来说,rem其实是不是很适合的。首先,如果单纯的使用rem来设置字体的话,就有可能造成13px,15px这种比较奇葩的字体大小,至于为什么这些字体大小奇葩,只能说自己查阅相关资料了,对于这个东西在网上的观点还是很多的,这里就不多赘述了。其次,就是是否有这个必要让字体实现自适应,有时候,更大的屏幕我们节可以给用户展示更多的信息,这一点,在很多网站上都有体现。这样一来,文字的自适应就没有这么大的需求了。不过,要实现字体自适应也不是不行,这里举一个简单的例子。
@media screen and (min-width: 641px) and (max-width: 960px) { p { font-size:14px } } @media screen and (min-width: 961px) and (max-width: 1200px) { p { font-size:16px } }
这样,我们就能实现文字的自适应布局了。