🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 思考 ### 思路整理图 ![](https://box.kancloud.cn/f4365a6fa969dc50c59473523c8b97e7_4200x3116.jpg) ***** [浅谈响应式Web设计与实现思路](https://www.toutiao.com/a6508149161299280398/?tt_from=weixin&utm_campaign=client_share&timestamp=1515350460&app=news_article&utm_source=weixin&iid=22069500288&utm_medium=toutiao_android&wxshare_count=1) * **响应式(Responsive)** 响应式是什么呢?顾名思义,响应式,肯定会自动响应,响应什么?应用程序是在终端屏幕窗口中展示给用户,被用户访问的,那么就是响应屏幕的变化,不同终端屏幕尺寸大小不一致,需要针对不同尺寸屏幕进行不同的展示响应。 > 响应式(Responsive web design, RWD),是指一套应用程序用户界面(User Interface)能自动响应不同设备窗口或屏幕尺寸(screen size)并且内容,布局渲染表现良好。 * **自适应(Adaptive)** 在响应式设计(RWD)之外,还有一种适配多设备屏幕的方式,自适应设计(Adaptive web design, AWD)。 > 自适应设计(AWD),是指一个应用程序使用多版本用户界面,针对不同设备屏幕,服务器端返回不同版本用户界面,供用户访问。 ***** [css3的字体大小单位\[rem\]底好在哪? - 知乎](https://www.zhihu.com/question/20312140) [前端移动端适配总结](http://mp.weixin.qq.com/s/P37snHNoi7G4SpL3FEhMGg) 传统的px,在不同分辨率的屏幕上,元素大小是可以自动伸缩适应的,也就是说是灵活的,是等比例缩放的,这是极好的。**(一个在电脑上显示好好的普通网页,拿到户外大屏或者投影仪上去看,虽然屏幕物理尺寸大了,但是页面布局基本一致,不需要任何处理,页面都是等比例放大的,因为户外屏幕大,但是由于像素不高,每一个像素颗粒的尺寸大,即屏幕虽然大了,但是所拥有的像素数量还是和PC屏幕的像素数量是差不多的,所以网页在这样的大屏上显示和我们之前电脑上显示基本没有区别,只是一个放大版的而已。)** 但是如果分辨率密度一样,只是屏幕大小不同,那么元素尺寸还是一致的。此时不能实现不同尺寸下还能等比例缩放。**(即同样一块屏幕,iPhone6和iPad Air屏幕分辨率是一样的,屏幕材质是一样的,但是后者的屏幕面积尺寸大,拥有的像素点也就越多。此时需要依靠响应式了,使用css媒体查询实现。如果不做响应式——使同一页面在不同设备上都能够呈现出最好的显示效果,那么同一页面,就不能同时在iPhone6和iPad Air上面呈现最好出的显示效果。)** >[danger] 就像放大缩小一张图片一样,缩放并不会影响图片的本身内容的呈现,也就是说图片会等比缩放。现在我们想要将这种缩放应用到网页上,但是这可不像图片缩放那么简单。 flexible.js要解决的问题应该就是**后者的问题**。 > `css 1px` 在不同像素密度的屏幕上,能自动等的比例缩放(1px的物理尺寸不同),所以没有任何问题,PC端无适配压力就是这个原因,而在移动端,问题就突出了,怎么还原设计稿呢,怎么让设计稿应对不同大小的屏幕而自动等比例缩放适应屏幕呢? `css 1px` 在相同屏幕(像素密度相同),但屏幕大小不同的手机上(px在不同的屏幕尺寸上会展示为定宽),怎么保持元素因屏幕大小不同而自动等比例缩放呢(使其不出现滚动条或者占不满的情况),这就是`flexible.js`要解决的问题了。 ***** ### TODO 这是什么原理? [http://h5.snacks.pindou.com/v/index#/items/97?user=11](http://h5.snacks.pindou.com/v/index#/items/97?user=11) 切换成手机浏览时,有缩放效果。css像素显示一样的,但是明显物理尺寸变大了。(屏蔽js,也不影响效果) ![](http://cdn.aipin100.cn/18-3-21/18696754.jpg) ![](http://cdn.aipin100.cn/18-3-21/53845379.jpg) 不开手机版显示时,调整屏幕大小,没效果。 ![](http://cdn.aipin100.cn/18-3-21/1311519.jpg) ![](http://cdn.aipin100.cn/18-3-21/83178488.jpg) ***** 还有这个,也是这样的,一开手机版就能自动缩放适配啊,看到的大小明明不一样,但是显示的px是一样的,神奇! 这非流式100%布局居然也能上下左右放大缩小啊,神奇! [http://www.hnojm.cn/app/index.php?i=17&c=entry&pid=mm\_113576304\_40690311\_161558621&do=lmsearch&m=tiger\_newhu](http://www.hnojm.cn/app/index.php?i=17&c=entry&pid=mm_113576304_40690311_161558621&do=lmsearch&m=tiger_newhu) 这是什么原理,太神奇了! 找到原因了,我们以前总是加上这一句: ```html <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no"> ``` 其实这个有问题,只需要这样就可以实现这样的效果: ```html <meta name="viewport" content="width=device-width"> ``` 其实这没卵用,当屏幕大到一定程度就不会有缩放效果了,比如上面的640px,所以其实这并不是什么适配方案,只是浏览器的效果而已。 但是: ```html <meta name="viewport" content="width=640"> ``` 又能突破640的魔咒,怎么都能缩放,好奇怪啊,但就是我们想要的适配效果吗,**整个页面随着屏幕尺寸变化自动缩放,而无需关心我们的css大小。这就像魔法一样**,但是这样也有缺点,无法控制我们不想缩放的元素。**所以这应该不算什么适配方案!** 待研究!!! 2018-5-5 14:52:00 其实就是自己设置了设备独立像素了而已,以前还不知道原来设备独立像素是可以被改变的,这样的话,不管屏幕尺寸多大,设备独立像素都是一样的,也就是上面的效果,css像素显示时是一样的,但是元素大小却可以不一样。 [【直播公开课】之"不是干货,劈脸就揍"! - html5效果 - 海棠学院 - WEB前端学习新体验](http://www.apeclass.cn/article/51) (这里移动端适配课程讲的很清楚了) [豇豆恐怖吗的头条主页 - 今日头条(www.toutiao.com)](https://www.toutiao.com/c/user/52889429289/#mid=1553692861394945)(移动端适配课程) ***** [第六届襄阳大学生电影展举行颁奖典礼\_手机网易网](http://3g.163.com/local/article/DLFC2HE204088E1B.html?from=timeline) ```javascript "use strict"; var Dpr = 1 , uAgent = window.navigator.userAgent , isIOS = uAgent.match(/iphone/i) , isYIXIN = uAgent.match(/yixin/i) , is2345 = uAgent.match(/Mb2345/i) , ishaosou = uAgent.match(/mso_app/i) , isSogou = uAgent.match(/sogoumobilebrowser/gi) , isLiebao = uAgent.match(/liebaofast/i) , isGnbr = uAgent.match(/GNBR/i) , $fixed = document.getElementById("fixed"); function resizeRoot() { var e, i = 0 < screen.width && (window.innerWidth >= screen.width || 0 == window.innerWidth) ? screen.width : window.innerWidth, n = 0 < screen.height && (window.innerHeight >= screen.height || 0 == window.innerHeight) ? screen.height : window.innerHeight; window.devicePixelRatio && window.devicePixelRatio, isIOS && (i = screen.width, n = screen.height), n < i && (i = n), 100 < (e = 32 < (e = 1080 < i ? 144 : i / 7.5) ? e : 32) && (e = 100), window.screenWidth_ = i, isYIXIN || is2345 || ishaosou || isSogou || isLiebao || isGnbr ? setTimeout(function() { i = 0 < screen.width && (window.innerWidth >= screen.width || 0 == window.innerWidth) ? screen.width : window.innerWidth, n = 0 < screen.height && (window.innerHeight >= screen.height || 0 == window.innerHeight) ? screen.height : window.innerHeight, e = 32 < (e = 1080 < i ? 144 : i / 7.5) ? e : 32, document.getElementsByTagName("html")[0].style.fontSize = e + "px", $fixed && ($fixed.style.display = "none") }, 500) : (document.getElementsByTagName("html")[0].style.fontSize = e + "px", $fixed && ($fixed.style.display = "none")) } resizeRoot(); var reviseViewPort = function(e, i) { var n = 0 , t = i || 5 , o = setInterval(function() { var e, i = 0 < screen.width && window.innerWidth >= screen.width ? screen.width : window.innerWidth; i < window.screenWidth_ ? (e = 32 < (e = 1080 < (window.screenWidth_ = i) ? 144 : i / 7.5) ? e : 32, document.getElementsByTagName("html")[0].style.fontSize = e + "px", clearInterval(o)) : n++, t <= n && clearInterval(o) }, e || 200) }; reviseViewPort(200); ``` ```javascript window.onresize = function() { "function" == typeof window.resizeRoot && window.resizeRoot() } ``` ***** ### 例子 * [外卖生态圈之前端](http://test.fe.ptdev.cn/elm/#/home) ``` …… 163: function(i, e) { "use strict"; ! function(i, e) { var a = i.documentElement, n = "orientationchange" in window ? "orientationchange" : "resize", t = function() { var i = a.clientWidth; i && (a.style.fontSize = 20 * (i / 320) + "px") }; i.addEventListener && (e.addEventListener(n, t, !1), i.addEventListener("DOMContentLoaded", t, !1)) }(document, window) }, …… ``` * [小米商城-小米官方网站,小米手机、红米手机正品专卖](http://m.mi.com/) ```javascript ! function(n) { var e = n.document, t = e.documentElement, i = 720, d = i / 100, o = "orientationchange" in n ? "orientationchange" : "resize", a = function() { var n = t.clientWidth || 320; n > 720 && (n = 720), t.style.fontSize = n / d + "px" }; e.addEventListener && (n.addEventListener(o, a, !1), e.addEventListener("DOMContentLoaded", a, !1)) }(window); ``` >[danger] 可见它们都通过监听窗口大小改变事件来动态改变html上的font-size的值,以达到在不同屏幕尺寸下rem大小不同。 **设计稿px换算到rem时,直接用设计稿的px值除以html基准值即可。flexible.js将页面分为100份,基准值为7.5这样不好除,所以需要借助cssrem插件帮助换算时自动计算,小米这个为了换算时计算方便,没有将页面分为100份,而是将基准值设为100px,也就是把页面分为7.2份了,这样换算时直接除以100比较好算,不需要借助插件也容易计算。** ***** ```javascript document.addEventListener("DOMContentLoaded", function() { window.onresize = function() { document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + "px" } ; document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + "px" }, false); ``` [http://m.kuwo.cn/?mid=MUSIC\_3365790&from=baidu](http://m.kuwo.cn/?mid=MUSIC_3365790&from=baidu) ***** 饿了么 ```html <script> !function(e, t) { function i() { var t = n.getBoundingClientRect().width / 10; n.style.fontSize = t + "px", p.rem = e.rem = t } var a, r = e.document, n = r.documentElement, o = r.querySelector('meta[name="viewport"]'), l = r.querySelector('meta[name="flexible"]'), m = r.querySelector('meta[name="flexible-in-x5"]'), s = !0, c = 0, d = 0, p = t.flexible || (t.flexible = {}); if (o) { console.warn("将根据已有的meta标签来设置缩放比例"); var u = o.getAttribute("content").match(/initial\-scale=([\d\.]+)/); u && (d = parseFloat(u[1]), c = parseInt(1 / d)) } else if (l) { var f = l.getAttribute("content"); if (f) { var v = f.match(/initial\-dpr=([\d\.]+)/) , h = f.match(/maximum\-dpr=([\d\.]+)/); v && (c = parseFloat(v[1]), d = parseFloat((1 / c).toFixed(2))), h && (c = parseFloat(h[1]), d = parseFloat((1 / c).toFixed(2))) } } if (m && (s = "false" !== m.getAttribute("content")), !c && !d) { var x = (e.navigator.appVersion.match(/android/gi), e.chrome) , g = e.navigator.appVersion.match(/iphone/gi) , b = e.devicePixelRatio , w = /TBS\/\d+/.test(e.navigator.userAgent) , y = !1; try { y = "true" === localStorage.getItem("IN_FLEXIBLE_WHITE_LIST") } catch (e) { y = !1 } d = 1 / (c = g || x || w && s && y ? b >= 3 && (!c || c >= 3) ? 3 : b >= 2 && (!c || c >= 2) ? 2 : 1 : 1) } if (n.setAttribute("data-dpr", c), !o) if ((o = r.createElement("meta")).setAttribute("name", "viewport"), o.setAttribute("content", "initial-scale=" + d + ", maximum-scale=" + d + ", minimum-scale=" + d + ", user-scalable=no, viewport-fit=cover"), n.firstElementChild) n.firstElementChild.appendChild(o); else { var E = r.createElement("div"); E.appendChild(o), r.write(E.innerHTML) } e.addEventListener("resize", function() { clearTimeout(a), a = setTimeout(i, 300) }, !1), e.addEventListener("pageshow", function(e) { e.persisted && (clearTimeout(a), a = setTimeout(i, 300)) }, !1), "complete" === r.readyState ? r.body.style.fontSize = 12 * c + "px" : r.addEventListener("DOMContentLoaded", function(e) { r.body.style.fontSize = 12 * c + "px" }, !1), i(), p.dpr = e.dpr = c, p.refreshRem = i, p.rem2px = function(e) { var t = parseFloat(e) * this.rem; return "string" == typeof e && e.match(/rem$/) && (t += "px"), t } , p.px2rem = function(e) { var t = parseFloat(e) / this.rem; return "string" == typeof e && e.match(/px$/) && (t += "rem"), t } }(window, window.lib || (window.lib = {})) </script> ``` [https://h5.ele.me/](https://h5.ele.me/) ***** #### 容器变焦缩放方案 [https://agent-paycenter-ssl.xunlei.com/](https://agent-paycenter-ssl.xunlei.com/) [css中zoom和transform:scale的区别 - foodoir - 博客园](https://www.cnblogs.com/foodoir/p/5821018.html) 和拼豆那个效果很像,但这个其实是利用css多媒体查询设置了容器的变焦属性: ``` css /* media */ @media only screen and (min-width:820px){ .wrap{zoom:3.2;} } @media only screen and (min-width:481px) and (max-width:768px) { .wrap{zoom:2.4;} } @media only screen and (min-width:436px) and (max-width:480px) { .wrap{zoom:1.5;} } @media only screen and (min-width:415px) and (max-width:435px) { .wrap{zoom:1.3594;} } @media only screen and (min-width:401px) and (max-width:414px) { .wrap{zoom:1.2935;} } @media only screen and (min-width:385px) and (max-width:400px) { .wrap{zoom:1.25;} } @media only screen and (min-width:376px) and (max-width:384px) { .wrap{zoom:1.2;} } @media only screen and (min-width:361px) and (max-width:375px) { .wrap{zoom:1.1718;} } @media only screen and (min-width:321px) and (max-width:360px) { .wrap{zoom:1.125;} } ``` ***** ### 响应式与屏幕适配的思考 ***** 不用响应式媒体查询,也不用百分比适配,只需要以一套代码就能满足所有尺寸的屏幕屏幕,例如 让页面在 iphone6 - iphone8 有相同的展示效果。 ***** 单纯的使用rem与固定单位px没有区别,我们是通过控制了基准值,才使得rem具备动态适配的能力。 没有rem适配时,固定单位px的元素在适配多种手机屏幕时,我们是从最小屏幕开始,只要最小屏幕满足了,那么就认为没有问题,也就是不会出现挤在一起,有内容超出屏幕外的情况了。而有了rem适配后,我们直接还原设计稿无压力,所有屏幕通吃。(以某一款设备为标准来做设计稿,开发时用屏幕适配方案以一套设计稿适配多端) ***** 响应式虽不能像适配一样随着屏幕大小变化而等比缩放页面,但也能随着屏幕大小变化而改变布局,调整元素大小(在断点位置改变样式),也能让页面以合适的方式展现。这么说吧,假如适配是劳斯莱斯,响应式就是宝马,虽算不上奢华,但也不错,够用了。 当然这么将它们拿来比较是不对的,就像让老虎和狮子打架看谁更厉害一样,首先它们关注点不同,适配是以一比一还原设计稿尺寸为目标的,响应式是让同一套页面同时在pc和移动端获得较好的展示效果,它们作用不相同,是不能这样对比的,只有在合适的时候采用合适的技术才是最好的,和取长补短相互结合才能最终提高效率。 ***** 适配是屏幕尺寸不同,以同一套代码,元素大小也都能自动相应缩小和放大,以刚好和设计稿相同。响应式是用媒体查询屏幕尺寸发生变化,元素会变换位置或布局发生变化,以迎合当前设备,显示出出最好的展示效果,满足不同设备的操作习惯,交互效果等。 一般来说,pc端不需要这种适配,我换大屏显示器是为了看到更多的内容,而不是希望你内容也跟着变大了,那样的话,我要大屏显示器还有什么用。 ***** last update:2019-1-23 01:32:47