号称移动端布局终极解决方案。其实现非常简洁,但功能却不是盖的。在最近准备做的一个项目中会用到该解决方案,知根知底最好的办法便是学习官方文档和敲源码了。嗯,感觉这法还好,于是废话不多说,开始正文吧
官方文档
hotcss 官网称这是一个移动端布局开发的解决方案,使用动态HTML根字体大小和动态viewport scale。之前有一篇很火的讲述移动端布局的,介绍了淘宝、网易几家大厂的实现方式,这里的不同也就是在这个动态viewport scale上了吧。
其优势在于:
- 保证不同设备下的统一视觉体验。
- 不需要你再手动设置viewport,根据当前环境计算出最适合的viewport。
- 支持任意尺寸的设计图,不局限于特定尺寸的设计图。
- 支持单一项目,多种设计图尺寸,专为解决大型,长周期项目。
- 提供px2rem转换方法,CSS布局,零成本转换,原始值不丢失。
- 有效解决移动端真实1像素问题。
用法
直接引入
<script src="/path/to/hotcss.js"></script>
css写法
推荐使用scss来编写css,在scss文件的头部使用import将px2rem导入
@import '/path/to/px2rem.scss';
如果项目是单一尺寸设计图,那么你需要去px2rem.scss中定义全局的designWidth。
@function px2rem( $px ){
@return $px*320/$designWidth/20 + rem;
}
$designWidth : 750; //如设计图是750
如果你的项目是多尺寸设计图,那么就不能定义全局的designWidth了。需要在你的业务scss中单独定义。如以下是style.scss
@import '/path/to/px2rem.scss';
$designWidth : 750; //如设计图是750
$designWidth必须要在使用px2rem前定义。否则scss编译会出错。
hotcss 源码学习
上面的是用来初(凑)步(字)认(数)识的,果断还是要从源码着手,才能拨云见雾。
项目目录
1 2 3 4 5 6 7 8 9 10
| ├── example │ ├── duang │ ├── normal │ └── wolf │ └── src ├── hotcss.js ├── px2rem.less ├── px2rem.scss └── px2rem.styl
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| ;(function(widnow, document) { 'use strict'; var hotcss = {} ;(function() { var viewportEl = document.querySelector('meta[name="viewport"]'), hotcssEl = document.querySelector('meta[name="hotcss"]'), dpr = window.devicePixelRatio || 1, maxWidth = 540, designWidth = 0 dpr = dpr >= 3 ? 3 : (dpr >= 2 ? 2 : 1) if (hotcssEl) { var hotcssCon = hotcssEl.getAttribute('content') if (hotcssCon) { var initialDprMatch = hotcssCon.match(/initial\-dpr=([\d\.]+)/) if (initialDprMatch) { dpr = parseFloat(initialDprMatch[1]) } var maxWidthMatch = hotcssCon.match(/max\-width=(\d\.)+/) if (maxWidthMatch) { maxWidth = parseFloat(maxWidthMatch[1]) } var designWidthMatch = hotcssCon.match(/degisn\-width=([\d\.]+)/) if (designWidthMatch) { designWidth = parseFloat(designWidthMatch[1]) } } } document.documentElement.setAttribute('data-dpr', dpr) hotcss.dpr = dpr document.documentElement.setAttribute('max-width', maxWidth) hotcss.maxWidth = maxWidth if (designWidth) { document.documentElement.setAttribute('design-width', designWidth) } hotcss.designWidth = designWidth var scale = 1 / dpr, content = `width=device-width, initial-scale=${scale}, minimum-scale=${scale}, maximum-scale=${scale}, user-scalable=no` if (viewportEl) { viewportEl.setAttribute('content', content) } else { viewportEl = document.createElement('meta') viewportEl.setAttribute('name', 'viewport') viewportEl.setAttribute('content', 'content') document.head.appendChild(viewportEl) } })() hotcss.px2rem = function(px, designWidth) { if (!designWidth) { designWidth = parseInt(hotcss.designWidth, 10) } return parseInt(px, 10) * 320 / designWidth / 20 } hotcss.rem2px = function(rem, designWidth) { if (!designWidth) { designWidth = parseInt(hotcss.designWidth, 10) } return rem * 20 * designWidth / 320 } hotcss.mresize = function() { var innerWidth = document.documentElement.getBoundingClientRect().width || window.innerWidth; if (hotcss.maxWidth && (innerWidth / hotcss.dpr > hotcss.maxWidth)) { innerWidth = hotcss.maxWidth * hotcss.dpr }
if (!innerWidth) return false document.documentElement.style.fontSize = (innerWidth * 20 / 320) + 'px' hotcss.callback && hotcss.callback() } hotcss.mresize() window.addEventListener('resize', function() { clearTimeout(hotcss.tid) hotcss.tid = setTimeout(hotcss.mresize, 33) }, false) window.addEventListener('load', hotcss.mresize, false) setTimeout(function() { hotcss.mresize() }, 333) window.hotcss = hotcss })(window, document)
|
还不错,加上注释也没多少行代码,为以后读大段源码打下了基础…… 误。。。 看到这里,其实和之前淘宝 rem 解决方案差不多,这里只是进行整合。
我们可以简单回顾一下,脚本执行后 为window添加全局变量hotcss。在其中可以调用 hotcss.mresize方法,设置几大重要值,随着屏幕尺寸的改变,font-size也会跟着变,从而让我们写在代码中的rem值也随之调整,这样就实现了移动端的适配。
接口说明
initial-dpr
可以通过强制设置dpr。来关闭响应的viewport scale。使得viewport scale始终为固定值。
1 2 3 4 5 6
| <meta name="hotcss" content="initial-dpr=1"> <script src="/path/to/hotcss.js"></script>
|
max-width
通过设置该值来优化平板/PC访问体验,注意该值默认值为540。设置为0则该功能关闭。 为了配合使用该设置,请给body增加样式width:16rem;margin:0 auto;。
1 2 3 4 5 6 7 8 9 10 11
| <meta name="hotcss" content="max-width=640"> <script src="/path/to/hotcss.js"></script>
<style> body{ width: 16rem; margin: 0 auto; } </style>
|
design-width
通过对design-width的设置可以在本页运行的JS中直接使用hotcss.px2rem/hotcss.rem2px方法,无需再传递第二个值。
hotcss.mresize
用于重新计算布局,一般不需要你手动调用。
hotcss.mresize();
hotcss.callback
触发mresize的时候会执行该方法。
hotcss.callback = function(){
//your code here
}
单位转换 hotcss.px2rem
/ hotcss.rem2px
hotcss.px2rem 和 hotcss.rem2px。你可以预先设定hotcss.designWidth可以在meta中设置design-width,则之后使用这两个方法不需要再传递第二个参数。
迭代后仍然支持在js中设置hotcss.designWidth,推荐使用meta去设置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
hotcss.px2rem( px , designWidth );
hotcss.rem2px( rem , designWidth );
hotcss.px2rem(200); hotcss.rem2px(350);
|
参考资料
官方文档 http://imochen.github.io/hotcss/
github https://github.com/imochen/hotcss/blob/master/src/hotcss.js