让移动端布局开发更加容易
介绍
-
hotcss
不是一个库,也不是一个框架。它是一个移动端布局开发解决方案。使用hotcss
可以让移动端布局开发更容易。 -
使用动态的HTML根字体大小和动态的
viewport scale
。 -
遵循视觉一致性原则。在不同大小的屏幕和不同的设备像素密度下,让你的页面看起来是一样的。
-
不仅便捷了你的布局,同时它使用起来异常简单。可能你会说
talk is cheap,show me the code
,那我现在列下hotcss整个项目的目录结构。
├── example //所有的示例都在这个目录下
│ ├── duang
│ ├── normal
│ └── wolf
│
└── src //主要文件在这里
├── hotcss.js
├── px2rem.less
├── px2rem.scss
└── px2rem.styl
示例名称 | 演示地址 | 贡献者 |
---|---|---|
普通的演示 | http://imochen.github.io/hotcss/example/normal/ | 墨尘 |
duang游戏 | http://imochen.github.io/hotcss/example/duang/ | 阳阳 |
灰太狼 | http://imochen.github.io/hotcss/example/wolf/ | 阳阳 |
谁在用hotcss
优势
- 保证不同设备下的统一视觉体验。
- 不需要你再手动设置
viewport
,根据当前环境计算出最适合的viewport
。 - 支持任意尺寸的设计图,不局限于特定尺寸的设计图。
- 支持单一项目,多种设计图尺寸,专为解决大型,长周期项目。
- 提供
px2rem
转换方法,CSS布局,零成本转换,原始值不丢失。 - 有效解决移动端真实1像素问题。
用法
引入hotcss.js
<script src="/path/to/hotcss.js"></script>
根据页面渲染机制,hotcss.js
必须在其他JS
加载前加载,万不可异步加载。
如果可以,你应将hotcss.js
的内容以内嵌的方式写到<head>
标签里面进行加载,并且保证在其他js文件之前。
为了避免不必要的bug
,请将CSS放到该JS之前加载。
css
要怎么写
你可能已经注意到在src/
目录下有px2rem.scss/px2rem.less/px2rem.styl
三个文件。没错,这就是hotcss
提供的将px
转为rem
的方法,可根据您的需要选择使用。
推荐使用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编译会出错。
注意:如果使用less
,则需要引入less-plugin-functions
,普通的less
编译工具无法正常编译。
想用px
怎么办?
直接写px
肯定是不能适配的,那hotcss.js
会在html
上注册data-dpr
属性,这个属性用来标识当前环境dpr
值。那么要使用px
可以这么写。
//scss写法
#container{
font-size: 12px ;
[data-dpr="2"] &{
font-size: 24px;
}
[data-dpr="3"] &{
font-size: 36px;
}
}
接口说明
initial-dpr
可以通过强制设置dpr
。来关闭响应的viewport scale
。使得viewport scale
始终为固定值。
<meta name="hotcss" content="initial-dpr=1">
<script src="/path/to/hotcss.js"></script>
<!--
如iphone微信强设dpr=1,则可以长按识别二维码。
注意,强制设置dpr=1后,css中的1px在2x,3x屏上则不再是真实的1px。
-->
max-width
通过设置该值来优化平板/PC访问体验,注意该值默认值为540
。设置为0
则该功能关闭。
为了配合使用该设置,请给body
增加样式width:16rem;margin:0 auto;
。
<meta name="hotcss" content="max-width=640">
<script src="/path/to/hotcss.js"></script>
<!--
默认为540,可根据具体需求自己定义
-->
<style>
body{
width: 16rem;
margin: 0 auto;
}
</style>
design-width
通过对design-width
的设置可以在本页运行的JS中直接使用hotcss.px2rem/hotcss.rem2px
方法,无需再传递第二个值。
<meta name="hotcss" content="design-width=750">
<script src="/path/to/hotcss.js"></script>
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
去设置。
/**
* [px2rem px值转换为rem值]
* @param {[number]} px [需要转换的值]
* @param {[number]} designWidth [设计图的宽度尺寸]
* @return {[number]} [返回转换后的结果]
*/
hotcss.px2rem( px , designWidth );
/**
* 同上。
* 注意:因为rem可能为小数,转换后的px值有可能不是整数,需要自己手动处理。
*/
hotcss.rem2px( rem , designWidth );
//你可以在meta中定义design-width,此后使用px2rem/rem2px,就不需要传递designWidth值了。同时也支持旧的设置方式,直接在JS中设置hotcss.designWidth
hotcss.px2rem(200);
hotcss.rem2px(350);
hotcss.js
源码
(function( window , document ){
'use strict';
//给hotcss开辟个命名空间,别问我为什么,我要给你准备你会用到的方法,免得用到的时候还要自己写。
var hotcss = {};
(function() {
//根据devicePixelRatio自定计算scale
//可以有效解决移动端1px这个世纪难题。
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 );
//允许通过自定义name为hotcss的meta头,通过initial-dpr来强制定义页面缩放
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(/design\-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; // 保证px2rem 和 rem2px 不传第二个参数时, 获取hotcss.designWidth是undefined导致的NaN
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 ){
//预判你将会在JS中用到尺寸,特提供一个方法助你在JS中将px转为rem。就是这么贴心。
if( !designWidth ){
//如果你在JS中大量用到此方法,建议直接定义 hotcss.designWidth 来定义设计图尺寸;
//否则可以在第二个参数告诉我你的设计图是多大。
designWidth = parseInt(hotcss.designWidth , 10);
}
return parseInt(px,10)*320/designWidth/20;
}
hotcss.rem2px = function( rem , designWidth ){
//新增一个rem2px的方法。用法和px2rem一致。
if( !designWidth ){
designWidth = parseInt(hotcss.designWidth , 10);
}
//rem可能为小数,这里不再做处理了
return rem*20*designWidth/320;
}
hotcss.mresize = function(){
//对,这个就是核心方法了,给HTML设置font-size。
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 );
//绑定resize的时候调用
window.addEventListener( 'load' , hotcss.mresize , false );
//防止不明原因的bug。load之后再调用一次。
setTimeout(function(){
hotcss.mresize();
//防止某些机型怪异现象,异步再调用一次
},333)
window.hotcss = hotcss;
//命名空间暴露给你,控制权交给你,想怎么调怎么调。
})( window , document );