├── .gitattributes ├── .gitignore ├── src ├── js │ ├── GB-respond.min.js │ └── GB-respond.js ├── css │ ├── GB-respond.css │ ├── GB-respond.scss │ └── normalize.css └── GB-respond.html ├── .editorconfig ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.css linguist-language=JavaScript 2 | *.html linguist-language=JavaScript -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore docs files 2 | _gh_pages 3 | .ruby-version 4 | 5 | 6 | # OS or Editor folders 7 | ._* 8 | .cache 9 | .DS_Store 10 | .idea 11 | .project 12 | .settings 13 | .tmproj 14 | *.esproj 15 | *.sublime-project 16 | *.sublime-workspace 17 | nbproject 18 | Thumbs.db 19 | 20 | # Komodo 21 | .komodotools 22 | *.komodoproject 23 | 24 | # Folders to ignore 25 | bower_components 26 | node_modules 27 | -------------------------------------------------------------------------------- /src/js/GB-respond.min.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(){var e=parseFloat(i.getBoundingClientRect().width||i.clientWidth),t=100/l*(e>u?u:e),n=16!==d?t*(16/d):t;console.log(n),i.style.fontSize=n+"px"}function n(e,t){clearTimeout(e.tId),e.tId=setTimeout(function(){e.call(t)},100)}var o=e.document,i=o.documentElement,d=parseFloat(window.getComputedStyle(i,null).getPropertyValue("font-size")||16),l=375,u=640;e.addEventListener("resize",function(){n(t)},!1),e.addEventListener("pageshow",function(e){e.persisted&&n(t)},!1),t()}(window); -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # For more information about the properties used in 2 | # this file, please see the EditorConfig documentation: 3 | # http://editorconfig.org/ 4 | 5 | root = true 6 | 7 | [*] 8 | charset = utf-8 9 | end_of_line = lf 10 | indent_size = 4 11 | indent_style = space 12 | insert_final_newline = true 13 | trim_trailing_whitespace = true 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | 18 | [{.travis.yml,package.json}] 19 | # The indent size used in the `package.json` file cannot be changed 20 | # https://github.com/npm/npm/pull/3180#issuecomment-16336516 21 | indent_size = 2 22 | indent_style = space 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 givebest 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /src/css/GB-respond.css: -------------------------------------------------------------------------------- 1 | html{font-size:100px}body,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td,hr,button,article,aside,details,figcaption,figure,footer,header,menu,nav,section{margin:0;padding:0}ol,ul{list-style:none}body{font-size:.12rem;background-color:#eee}a{text-decoration:none}.clearfix:before,.clearfix:after{content:" ";display:table}.clearfix:after{clear:both}.text-overflow{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wrapper{margin:0 auto;max-width:640px;min-width:320px;background-color:#fff}.header{position:relative;height:.4rem;line-height:.4rem;color:#fff;background-color:#FE5400}.header--title{position:absolute;left:0;top:0;padding:0 .5rem;margin:0;width:100%;font-size:.16rem;line-height:.4rem;text-align:center;box-sizing:border-box}a.header--icon{display:inline-block;width:.4rem;height:.4rem;text-align:center;font-size:.16rem;color:#fff}.header--icon__left{float:left}.header--icon__right{float:right}.main--banner{text-align:center}.main--banner__img{width:100%;max-width:100%}.main--nav{padding:.1rem 0;overflow:hidden}.main--nav__item{float:left;padding:.04rem 0;width:25%;text-align:center;line-height:2;font-size:.14rem}.main--nav__item a{color:#333}.main--nav__icon{display:block;margin:0 auto;height:.4rem}.main--feature{margin-top:.1rem}.main--feature img{width:100%}.feature--item__left{width:1.47rem;border-top:1px solid #eee}.feature--item__right{border-left:1px solid #eee;width:2.28rem}.main--feature__item,.feature--item__item{float:left;box-sizing:border-box}.feature--item__item{width:50%;border-top:1px solid #eee}.footer{margin-top:.1rem;padding:.1rem;text-align:center;background-color:#FFF} 2 | /*# sourceMappingURL=GB-respond.css.map */ 3 | -------------------------------------------------------------------------------- /src/js/GB-respond.js: -------------------------------------------------------------------------------- 1 | /** 2 | * GB-respond.js 3 | * @see https://github.com/givebest/GB-html5-respond 4 | * @author givenlovs[at]msn.com 5 | * @(c) 2017 6 | **/ 7 | ;(function (win) { 8 | var doc = win.document, 9 | docEl = doc.documentElement, 10 | defaultFontSize = parseFloat(window.getComputedStyle(docEl, null).getPropertyValue('font-size') || 16), 11 | designWidth = 750 / 2, // 设计稿宽度 12 | maxWidth = 1280 / 2; // 最大支持宽度(无限制会导致 Pad 等大屏设备展示内容过少、图像失真等) 13 | 14 | win.addEventListener('resize', function() { 15 | throttle(refreshRem); 16 | }, false); 17 | 18 | // @see https://github.com/amfe/lib-flexible/blob/master/src/flexible.js 19 | win.addEventListener('pageshow', function (e) { 20 | if (e.persisted) { 21 | throttle(refreshRem); 22 | } 23 | }, false); 24 | 25 | // 初始化 26 | refreshRem(); 27 | 28 | /** 29 | * 计算字体大小 30 | * @return {[type]} [description] 31 | */ 32 | function refreshRem () { 33 | var width = parseFloat(docEl.getBoundingClientRect().width || docEl.clientWidth), 34 | fontSize = 100 / designWidth * (width > maxWidth ? maxWidth : width), 35 | // Android webView 会被设备字体大小(默认为16px)影响 @see https://github.com/hbxeagle/rem 36 | finalFontSize = (defaultFontSize !== 16) ? (fontSize * (16 / defaultFontSize)) : fontSize; 37 | console.log(finalFontSize) 38 | docEl.style.fontSize = finalFontSize + 'px'; 39 | } 40 | 41 | /** 42 | * 节流函数 43 | * @param {[type]} method [description] 44 | * @param {[type]} context [description] 45 | * @return {[type]} [description] 46 | */ 47 | function throttle (method, context) { 48 | clearTimeout(method.tId); 49 | method.tId = setTimeout (function () { 50 | method.call(context); 51 | }, 100); 52 | } 53 | })(window); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GB-html5-respond 2 | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fgivebest%2FGB-html5-respond.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fgivebest%2FGB-html5-respond?ref=badge_shield) 3 | 4 | ---- 5 | 6 | ## 简介 7 | 8 | 移动端响应式布局解决方案、用 `JavaScript` 根据屏幕宽度计算 `Root` 字体大小弥补媒体查询断点断层过大问题,元素单位使用 `REM` 即可基于 `Root` 字体大小来改变自身大小。 9 | 10 | 11 | ## 演示 12 | 13 | [http://givebest.github.io/gb-respond.html](http://givebest.github.io/GB-respond.html) 14 | 15 | ## 使用 16 | 17 | ### HTML 18 | 19 | > 在 Head 引入(CSS前面) 20 | 21 | ```html 22 | 23 | 24 | 25 | 26 | 27 | ``` 28 | 29 | ### CSS 30 | 31 | > 以 375 (设计稿 750 * N) 屏幕宽度为基础,推算出元素相对应的 REM 值,如设计稿字体为:40px,那么换算下来为:40 / 2 / 100 = .2rem 32 | 33 | ```css 34 | 35 | html { 36 | font-size: 100px; 37 | } 38 | 39 | body { 40 | font-size: .12rem; /* 在 375 屏幕宽相当于 12px */ 41 | } 42 | 43 | /* 一级容器,包含页面全部元素 */ 44 | .wrapper { 45 | margin: 0 auto; 46 | max-width: 640px; 47 | min-width: 320px; 48 | /* width: 3.75rem; */ 49 | } 50 | ``` 51 | > 750(UI稿宽度) / 100(Html font-size) / 2 = 3.75rem 52 | > ~~加宽度可解决部分 Android 下 webView 中兼容问题(webView 获取设备宽度小于实际宽度),如:HUAWEI MT7~~ 更新解决文案,详见 [JS](#js) 53 | > 灵感来源:https://m.taobao.com/#index 54 | 55 | ### JS 56 | 57 | > Android 设备 WebView 会因设备设置字体(浏览器默认为 `16px`)大小影响,详情: https://github.com/hbxeagle/rem 。 58 | 59 | 解决方法如下: 60 | 61 | ```javascript 62 | var doc = window.document, 63 | docEl = doc.documentElement, 64 | defaultFontSize = parseFloat(window.getComputedStyle(docEl, null).getPropertyValue('font-size') || 16), // 获取 WebView 默认字体大小 65 | width = parseFloat(docEl.getBoundingClientRect().width || docEl.clientWidth), 66 | fontSize = 100 / designWidth * (width > maxWidth ? maxWidth : width), 67 | finalFontSize = (defaultFontSize !== 16) ? (fontSize * (16 / defaultFontSize)) : fontSize; // WebView 默认字体大小不等于 16px 即设备设置改变了默认字体大小,进行换算正确的大小 68 | docEl.style.fontSize = finalFontSize + 'px'; // 为 Html 设置字体大小 69 | ``` 70 | 71 | ## 感谢他们 72 | 73 | 参考: [https://github.com/amfe/lib-flexible](https://github.com/amfe/lib-flexible) 74 | 75 | [https://github.com/hbxeagle/rem](https://github.com/hbxeagle/rem) 76 | 77 | 78 | 79 | ## License 80 | 81 | [MIT](./LICENSE) © 2017 [givebest](https://github.com/givebest) 82 | 83 | 84 | 85 | 86 | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fgivebest%2FGB-html5-respond.svg?type=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fgivebest%2FGB-html5-respond?ref=badge_large) -------------------------------------------------------------------------------- /src/css/GB-respond.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | $fontSize: 100px; 4 | 5 | html { 6 | font-size: $fontSize; 7 | } 8 | 9 | body, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea, p, blockquote, th, td, hr, button, article, aside, details, figcaption, figure, footer, header, menu, nav, section { 10 | margin: 0; 11 | padding: 0; 12 | } 13 | 14 | ol, ul { 15 | list-style: none; 16 | } 17 | 18 | body { 19 | font-size: .12rem; 20 | background-color: #eee; 21 | } 22 | 23 | a { 24 | text-decoration: none; 25 | } 26 | 27 | .clearfix:before, 28 | .clearfix:after { 29 | content: " "; /* 1 */ 30 | display: table; /* 2 */ 31 | } 32 | 33 | .clearfix:after { 34 | clear: both; 35 | } 36 | 37 | .text-overflow { 38 | overflow: hidden; 39 | text-overflow: ellipsis; 40 | white-space: nowrap; 41 | } 42 | 43 | .wrapper { 44 | margin: 0 auto; 45 | max-width: 640px; 46 | min-width: 320px; 47 | // width: 3.75rem; 48 | background-color: #fff; 49 | } 50 | 51 | 52 | .header { 53 | position: relative; 54 | height: .4rem; 55 | line-height: .4rem; 56 | color: #fff; 57 | background-color: #FE5400; 58 | } 59 | 60 | .header--title { 61 | position: absolute; 62 | left: 0; 63 | top: 0; 64 | padding: 0 .5rem; 65 | margin: 0; 66 | width: 100%; 67 | font-size: .16rem; 68 | line-height: .4rem; 69 | text-align: center; 70 | box-sizing: border-box; 71 | } 72 | 73 | a.header--icon { 74 | display: inline-block; 75 | width: .4rem; 76 | height: .4rem; 77 | text-align: center; 78 | font-size: .16rem; 79 | color: #fff; 80 | } 81 | .header--icon__left { 82 | float: left; 83 | } 84 | .header--icon__right { 85 | float: right; 86 | } 87 | 88 | .main--banner { 89 | text-align: center; 90 | } 91 | .main--banner__img { 92 | width: 100%; 93 | max-width: 100%; 94 | } 95 | 96 | .main--nav { 97 | padding: .1rem 0; 98 | overflow: hidden; 99 | } 100 | .main--nav__item { 101 | float: left; 102 | padding: .04rem 0; 103 | width: 25%; 104 | text-align: center; 105 | line-height: 2; 106 | font-size: .14rem; 107 | } 108 | .main--nav__item a { 109 | color: #333; 110 | } 111 | .main--nav__icon { 112 | display: block; 113 | margin: 0 auto; 114 | height: .4rem; 115 | } 116 | 117 | .main--feature { 118 | margin-top: .1rem; 119 | } 120 | .main--feature img { 121 | width: 100%; 122 | } 123 | .feature--item__left { 124 | width: 1.47rem; 125 | border-top: 1px solid #eee; 126 | } 127 | .feature--item__right { 128 | border-left: 1px solid #eee; 129 | width: 2.28rem; 130 | } 131 | .main--feature__item, 132 | .feature--item__item { 133 | float: left; 134 | box-sizing: border-box; 135 | } 136 | .feature--item__item { 137 | width: 50%; 138 | border-top: 1px solid #eee; 139 | } 140 | 141 | .footer { 142 | margin-top: .1rem; 143 | padding: .1rem; 144 | text-align: center; 145 | background-color: #FFF; 146 | } -------------------------------------------------------------------------------- /src/css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | html { 4 | line-height: 1.15; 5 | -ms-text-size-adjust: 100%; 6 | -webkit-text-size-adjust: 100% 7 | } 8 | 9 | body { 10 | margin: 0 11 | } 12 | 13 | article, 14 | aside, 15 | footer, 16 | header, 17 | nav, 18 | section { 19 | display: block 20 | } 21 | 22 | h1 { 23 | font-size: 2em; 24 | margin: 0.67em 0 25 | } 26 | 27 | figcaption, 28 | figure, 29 | main { 30 | display: block 31 | } 32 | 33 | figure { 34 | margin: 1em 40px 35 | } 36 | 37 | hr { 38 | box-sizing: content-box; 39 | height: 0; 40 | overflow: visible 41 | } 42 | 43 | pre { 44 | font-family: monospace, monospace; 45 | font-size: 1em 46 | } 47 | 48 | a { 49 | background-color: transparent; 50 | -webkit-text-decoration-skip: objects 51 | } 52 | 53 | abbr[title] { 54 | border-bottom: none; 55 | text-decoration: underline; 56 | text-decoration: underline dotted 57 | } 58 | 59 | b, 60 | strong { 61 | font-weight: inherit 62 | } 63 | 64 | b, 65 | strong { 66 | font-weight: bolder 67 | } 68 | 69 | code, 70 | kbd, 71 | samp { 72 | font-family: monospace, monospace; 73 | font-size: 1em 74 | } 75 | 76 | dfn { 77 | font-style: italic 78 | } 79 | 80 | mark { 81 | background-color: #ff0; 82 | color: #000 83 | } 84 | 85 | small { 86 | font-size: 80% 87 | } 88 | 89 | sub, 90 | sup { 91 | font-size: 75%; 92 | line-height: 0; 93 | position: relative; 94 | vertical-align: baseline 95 | } 96 | 97 | sub { 98 | bottom: -0.25em 99 | } 100 | 101 | sup { 102 | top: -0.5em 103 | } 104 | 105 | audio, 106 | video { 107 | display: inline-block 108 | } 109 | 110 | audio:not([controls]) { 111 | display: none; 112 | height: 0 113 | } 114 | 115 | img { 116 | border-style: none 117 | } 118 | 119 | svg:not(:root) { 120 | overflow: hidden 121 | } 122 | 123 | button, 124 | input, 125 | optgroup, 126 | select, 127 | textarea { 128 | font-family: sans-serif; 129 | font-size: 100%; 130 | line-height: 1.15; 131 | margin: 0 132 | } 133 | 134 | button, 135 | input { 136 | overflow: visible 137 | } 138 | 139 | button, 140 | select { 141 | text-transform: none 142 | } 143 | 144 | button, 145 | html [type="button"], 146 | [type="reset"], 147 | [type="submit"] { 148 | -webkit-appearance: button 149 | } 150 | 151 | button::-moz-focus-inner, 152 | [type="button"]::-moz-focus-inner, 153 | [type="reset"]::-moz-focus-inner, 154 | [type="submit"]::-moz-focus-inner { 155 | border-style: none; 156 | padding: 0 157 | } 158 | 159 | button:-moz-focusring, 160 | [type="button"]:-moz-focusring, 161 | [type="reset"]:-moz-focusring, 162 | [type="submit"]:-moz-focusring { 163 | outline: 1px dotted ButtonText 164 | } 165 | 166 | fieldset { 167 | padding: 0.35em 0.75em 0.625em 168 | } 169 | 170 | legend { 171 | box-sizing: border-box; 172 | color: inherit; 173 | display: table; 174 | max-width: 100%; 175 | padding: 0; 176 | white-space: normal 177 | } 178 | 179 | progress { 180 | display: inline-block; 181 | vertical-align: baseline 182 | } 183 | 184 | textarea { 185 | overflow: auto 186 | } 187 | 188 | [type="checkbox"], 189 | [type="radio"] { 190 | box-sizing: border-box; 191 | padding: 0 192 | } 193 | 194 | [type="number"]::-webkit-inner-spin-button, 195 | [type="number"]::-webkit-outer-spin-button { 196 | height: auto 197 | } 198 | 199 | [type="search"] { 200 | -webkit-appearance: textfield; 201 | outline-offset: -2px 202 | } 203 | 204 | [type="search"]::-webkit-search-cancel-button, 205 | [type="search"]::-webkit-search-decoration { 206 | -webkit-appearance: none 207 | } 208 | 209 | ::-webkit-file-upload-button { 210 | -webkit-appearance: button; 211 | font: inherit 212 | } 213 | 214 | details, 215 | menu { 216 | display: block 217 | } 218 | 219 | summary { 220 | display: list-item 221 | } 222 | 223 | canvas { 224 | display: inline-block 225 | } 226 | 227 | template { 228 | display: none 229 | } 230 | 231 | [hidden] { 232 | display: none 233 | } 234 | -------------------------------------------------------------------------------- /src/GB-respond.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 移动端响应式布局方案 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |

移动端响应式布局方案移动端响应式布局方案

18 | < 19 | > 20 |
21 | 22 |
23 |
24 | 520 25 |
26 | 27 | 79 | 80 |
81 |
82 | 0 83 |
84 |
85 |
86 | 1 87 |
88 |
89 | 2 90 |
91 |
92 | 3 93 |
94 |
95 | 4 96 |
97 |
98 |
99 | 100 |
101 |
102 | 0 103 |
104 |
105 |
106 | 1 107 |
108 |
109 | 2 110 |
111 |
112 | 3 113 |
114 |
115 | 4 116 |
117 |
118 |
119 |
120 | 121 | 122 | 127 | 128 | 129 | 130 | --------------------------------------------------------------------------------