{"action":"created","issue":{"url":"https://api.github.com/repos/riskers/blog/issues/18","repository_url":"https://api.github.com/repos/riskers/blog","labels_url":"https://api.github.com/repos/riskers/blog/issues/18/labels{/name}","comments_url":"https://api.github.com/repos/riskers/blog/issues/18/comments","events_url":"https://api.github.com/repos/riskers/blog/issues/18/events","html_url":"https://github.com/riskers/blog/issues/18","id":128394366,"number":18,"title":"移动端适配方案(下)","user":{"login":"riskers","id":5653652,"avatar_url":"https://avatars.githubusercontent.com/u/5653652?v=3","gravatar_id":"","url":"https://api.github.com/users/riskers","html_url":"https://github.com/riskers","followers_url":"https://api.github.com/users/riskers/followers","following_url":"https://api.github.com/users/riskers/following{/other_user}","gists_url":"https://api.github.com/users/riskers/gists{/gist_id}","starred_url":"https://api.github.com/users/riskers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/riskers/subscriptions","organizations_url":"https://api.github.com/users/riskers/orgs","repos_url":"https://api.github.com/users/riskers/repos","events_url":"https://api.github.com/users/riskers/events{/privacy}","received_events_url":"https://api.github.com/users/riskers/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/riskers/blog/labels/mobile","name":"mobile","color":"5319e7"},{"url":"https://api.github.com/repos/riskers/blog/labels/%E9%80%82%E9%85%8D%E6%96%B9%E6%A1%88","name":"适配方案","color":"207de5"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":15,"created_at":"2016-01-24T12:48:01Z","updated_at":"2016-02-18T11:44:56Z","closed_at":null,"body":"[上一篇](https://github.com/riskers/blog/issues/17)介绍了像素和视口这些基本概念，现在接着移动端的适配方案。\r\n\r\n>推荐一篇文章：[MobileWeb适配总结](http://html-js.com/article/MobileWeb)，里面说到的三种布局方法已经说的很详细，还分别做了demo，我就不做了，这里说说三种方案的原理以及我使用中的感受，希望各为互补，大家理解是最重要的。\r\n\r\n之前做过PC页面的人聊的最多的就是『兼容』，这是因为浏览器之间的差异引起的，不再多说。而移动端是基本没有『兼容』的问题的，全是CSS3，简直不要太开心。可是『适配』问题随之而来。\r\n\r\n什么是『适配』？做PC页面的时候，我们按照设计图的尺寸来就好，这个侧边栏200px，那个按钮50px的。可是，当我们开始做移动端页面的时候，设计师给了一份宽度为640px的设计图。那么，我们把这份设计图实现在各个手机上的过程就是『适配』。\r\n\r\n那么，我们怎么开始呢？目前有三种方法：\r\n\r\n* 固定高度，宽度自适应\r\n* 固定宽度，viewport缩放\r\n* rem做宽度，viewport缩放\r\n\r\n这三种方法的核心都是**视口的确定**，现在以实现这个设计图为例说明。\r\n\r\n![app-demo](http://7xlc2a.com1.z0.glb.clouddn.com/FlIqUibwhVcB4dvR-8RPOTkog3kP)\r\n\r\n## 固定高度，宽度自适应\r\n\r\n[demo](http://www.meow.re/demo/screen-adaptation-in-mobileweb/app-fixed-height.html)\r\n\r\n这也是目前使用最多的方法，垂直方向用定值，水平方向用百分比、定值、flex都行。[腾讯](http://xw.qq.com/index.htm)、[京东](http://m.jd.com/)、[百度](https://www.baidu.com/)、[天猫](https://www.tmall.com/)、[亚马逊](http://www.amazon.cn/)的首页都是使用的这种方法。\r\n\r\n随着屏幕宽度变化，页面也会跟着变化，效果就和PC页面的流体布局差不多，在哪个宽度需要调整的时候使用*响应式布局*调调就行（比如[网易新闻](http://news.163.com/mobile/)），这样就实现了『适配』。\r\n\r\n===\r\n\r\n**原理**\r\n\r\n这种方法使用了完美视口：\r\n\r\n```\r\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\r\n```\r\n\r\n这样设置之后，我们就可以不用管手机屏幕的尺寸进行开发了。\r\n\r\n## 固定宽度，viewport缩放\r\n\r\n[demo](http://www.meow.re/demo/screen-adaptation-in-mobileweb/app-fixed-width.html)\r\n\r\n设计图、页面宽度、viewport width使用一个宽度，浏览器帮我们完成缩放。单位使用px即可。\r\n\r\n目前已知[荔枝FM](http://m.lizhi.fm/)、[网易新闻](http://c.3g.163.com/CreditMarket/default.html)在使用这种方法。有兴趣的同学可以看看是怎么做的。\r\n\r\n===\r\n\r\n**原理**\r\n\r\n这种方法需要根据屏幕宽度来动态生成`viewport`，生成的 viewport 基本是这样：\r\n\r\n```\r\n<meta name=\"viewport\" content=\"width=640,initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable=no\">\r\n```\r\n\r\n640 是我们根据设计图定下的，0.5 是根据屏幕宽度动态生成的。\r\n\r\n生成的viewport告诉浏览器网页的布局视口使用 640px，然后把页面缩放成50%，这是绝对的等比例缩放。图片、文字等等所有元素都被缩放在手机屏幕中。\r\n\r\n这个gif图说明了一切：\r\n\r\n![1](http://7xlc2a.com1.z0.glb.clouddn.com/FjDCphxn990kD9GTMJZOYXJ5fVKh)\r\n\r\n## rem做宽度，viewport缩放\r\n\r\n[demo](http://www.meow.re/demo/screen-adaptation-in-mobileweb/app-rem.html)\r\n\r\n这也是[淘宝](https://m.taobao.com)使用的方案，根据屏幕宽度设定 `rem` 值，需要适配的元素都使用 `rem` 为单位，不需要适配的元素还是使用 `px` 为单位。\r\n\r\n具体使用方法见[使用Flexible实现手淘H5页面的终端适配](https://github.com/amfe/article/issues/17)\r\n\r\n使用这个方法的库：\r\n\r\n* [lib-flexible](https://github.com/amfe/lib-flexible)\r\n* [hotcss](https://github.com/imochen/hotcss)\r\n\r\n===\r\n\r\n**原理**\r\n\r\n实际上做了这几件事情：\r\n\r\n1. 动态生成 viewport \r\n2. 屏幕宽度设置 `rem`的大小，即给`<html>`设置`font-size`\r\n3. 根据设备像素比（window.devicePixelRatio）给`<html>`设置`data-dpr`\r\n\r\n![rem](http://7xlc2a.com1.z0.glb.clouddn.com/FiER3qR2qrrXLna3KNuzm-oYf-qG)\r\n\r\n这么设置的好处是可以让不同设备的`rem`或`px`都显示一样的长度。\r\n\r\n### 设置rem\r\n设置rem的意义在于得到一个与屏幕宽度相关的单位，本来`vw`是最合适的，但是因为兼容性的问题，只能使用`rem`来做。这样，让**不同设备的`rem`显示一样的长度**。\r\n\r\n>vw是CSS3引入的单位，1vw = 1%窗口宽度\r\n\r\n![rem](http://7xlc2a.com1.z0.glb.clouddn.com/FoU5vgLoTAPCSxNZP6yl8kgSPh-i)\r\n\r\n上面的布局我们可以这样：\r\n\r\n```css\r\nhtml{\r\n\tfont-size: 屏幕宽度 / 10; \r\n}\r\n.btn{\r\n\twidth:8.75rem;\r\n\theight:1.25rem;\r\n}\r\n```\r\n\r\n这样，无论屏幕宽度是多少，`.btn`都是相对于屏幕的这么宽，做到了适配。\r\n\r\n### 设置 viewport 缩放 和 data-dpr\r\n\r\n这两个设置其实是干的一件事，就是适配高密度屏幕手机的`px`单位。\r\n\r\n```css\r\n.a{\r\n  font-size:12px;\r\n}\r\n[data-dpr=\"2\"] .a{\r\n  font-size: 24px;\r\n}\r\n[data-dpr=\"3\"] .a{\r\n  font-size: 36px;\r\n}\r\n```\r\n\r\n而缩放是动态的，这样，**不同设备下的`px`显示一样的长度**。\r\n\r\n之前说过CSS像素和物理像素与缩放、dpr都有关系，这里说明：\r\n\r\n>在普通手机上，`.a`字体设置为12px；\r\n>\r\n>在dpr是2的手机上，`[data-dpr=\"2\"] .a`字体为24px，又因为页面缩放50%，字体为还是12px\r\n\r\n\r\n## 总结\r\n坦白说，我不觉得第一种方案能就做『适配』方案，因为太笨了，只能做一些列表等简单排列的样式。\r\n\r\n![demo](http://7xlc2a.com1.z0.glb.clouddn.com/FtuW6bLLa0jVmND_X0t2ll-df1gX)\r\n\r\n但是一些复杂的活动页的布局，用它可能就力不从心了：\r\n\r\n![PK活动](http://7xlc2a.com1.z0.glb.clouddn.com/FuLz-9m9uuVD1ktTKf1hcByT28BU)\r\n\r\n这是我曾经做过的一个页面，『PK』要和左右两张图平行，而且下面的『不怒自威』、『义薄云天』和下面的战斗力位置都要固定，不能有差。如果用第一种方案，可能各个元素就要绝对定位，然后各种百分比来定位了。且不说计算麻烦，而且辛苦一番最后的结果尺寸是和设计图有出入的。\r\n\r\n但是，第二种和第三种方案就绝对不会有这种情况，不会和设计图有差。再说第二种和第三种方案的区别，目前我唯一知道的区别就是第三种方案更加灵活，有两种单位可以使用，想让元素适配的时候就用`rem`，想让文字不缩放的时候就用`px`。\r\n\r\n如果你没有明白我以上讲的，可能是我太啰嗦了，这是我在团队内分享时做的[PPT](http://ybshare.coding.io/share/flexible.htm)，应该没那么啰嗦了。当然你也可以看看下面的那些文章，不过最好的理解方式就是用这些方案做几个页面，到时候就明白了。\r\n\r\n\r\n**其他文章**\r\n\r\n* [移动端高清、多屏适配方案](http://div.io/topic/1092)\r\n* [从网易与淘宝的font-size思考前端设计稿与工作流](http://www.cnblogs.com/lyzg/p/4877277.html)\r\n* [百度方案](http://js8.in/2015/12/12/%E6%89%8B%E6%9C%BA%E7%99%BE%E5%BA%A6%E7%A7%BB%E5%8A%A8%E9%80%82%E9%85%8D%E5%88%87%E5%9B%BE%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88%E4%BB%8B%E7%BB%8D/)\r\n* [移动端自适应方案](http://f2e.souche.com/blog/yi-dong-duan-zi-gua-ying-fang-an/) 介绍了 flex 布局和rem方案\r\n\r\n\r\n这两篇文章看着简单，尤其是上一篇讲视口，花费了将近一周的时间去翻阅资料。本来以为很简单的东西，才发现有那么多名堂。\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/riskers/blog/issues/comments/185679038","html_url":"https://github.com/riskers/blog/issues/18#issuecomment-185679038","issue_url":"https://api.github.com/repos/riskers/blog/issues/18","id":185679038,"user":{"login":"MaskWu","id":10556006,"avatar_url":"https://avatars.githubusercontent.com/u/10556006?v=3","gravatar_id":"","url":"https://api.github.com/users/MaskWu","html_url":"https://github.com/MaskWu","followers_url":"https://api.github.com/users/MaskWu/followers","following_url":"https://api.github.com/users/MaskWu/following{/other_user}","gists_url":"https://api.github.com/users/MaskWu/gists{/gist_id}","starred_url":"https://api.github.com/users/MaskWu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MaskWu/subscriptions","organizations_url":"https://api.github.com/users/MaskWu/orgs","repos_url":"https://api.github.com/users/MaskWu/repos","events_url":"https://api.github.com/users/MaskWu/events{/privacy}","received_events_url":"https://api.github.com/users/MaskWu/received_events","type":"User","site_admin":false},"created_at":"2016-02-18T11:44:56Z","updated_at":"2016-02-18T11:44:56Z","body":"关于对 设置 viewport 缩放 和 data-dpr的解释中，以下部分不是十分的理解，看了几遍，都没有明白\r\n\r\n> 在普通手机上，.a字体设置为12px；\r\n> \r\n> 在dpr是2的手机上，[data-dpr=\"2\"] .a字体为24px，又因为页面缩放50%，字体为还是12px\r\n\r\n\r\n既然最后字体还是12px为什么要进行先将字体设置为24px再然后进行缩放的操作呢，还望博主解答"}}