一、页面在Native端滚动时模拟原生的弹性滚动

-webkit-overflow-scrolling : touch;

二、点5像素

伪元素 + css3的缩放巧妙地实现;
.fn-border-cells,.fn-border-all,.fn-border-top,.fn-border-bottom{
    position:relative;
}
.fn-border-cells:before,.fn-border-cells:after,.fn-border-all:before,.fn-border-top:before,.fn-border-bottom:after{
  content: " ";
  position: absolute;
  height: 1px;
  -webkit-transform-origin: 0 0;
  -moz-transform-origin: 0 0;
  -o-transform-origin: 0 0;
  -ms-transform-origin: 0 0;
          transform-origin: 0 0;
  -webkit-transform: scaleY(0.5);
  -moz-transform: scaleY(0.5);
  -o-transform: scaleY(0.5);
  -ms-transform: scaleY(0.5);
          transform: scaleY(0.5);
}
.fn-border-cells:before,.fn-border-top:before{
    top: 0;
    left:0;
    right:0;
    border-top: 1px solid #d9d9d9;
}
.fn-border-cells:after,.fn-border-bottom:after{
    bottom:0;
    left:0;
    right:0;
    border-bottom: 1px solid #d9d9d9;
}
.fn-border-all:before{
    width: 200%;
    height: 200%;
    border:1px solid #d9d9d9;
    transform: scale(0.5, 0.5);
    -ms-transform: scale(0.5, 0.5);
    -moz-transform: scale(0.5, 0.5);
    -webkit-transform: scale(0.5, 0.5);
    -o-transform: scale(0.5, 0.5);
}

三、rem解决方案

  1. 当我们在根节点<html>上设置了font-size基准值以后,在文档中有使用rem单位的属性值都是相对于根节点font-size的一个相对值。比如说一些元素的属性如width heightmargin等。也正是这个原因,现在很多网站的移动端网站都在使用rem单位作为适配工具。
  2. 将计算根元素的font-size值的js放在head标签中
  3. 使用JavaScript根据当前屏幕的宽度动态计算font-size值
使用的时候,请将下面的代码放到页面的顶部(head标签内);
/**
 * [以iPhone6的设计稿为例js动态设置文档 rem 值]
 * @param  {[type]} currClientWidth [当前客户端的宽度]
 * @param  {[type]} fontValue [计算后的 fontvalue值]
 * @return {[type]}     [description]
var currClientWidth, fontValue,originWidth; //originWidth用来设置设计稿原型的屏幕宽度(这里是以 Iphone 6为原型的设计稿)
originWidth=375; __resize(); //注册 resize事件
 window.addEventListener('resize', __resize, false);
function __resize() { currClientWidth = document.documentElement.clientWidth; //这里是设置屏幕的最大和最小值时候给一个默认值
if (currClientWidth > 640) currClientWidth = 640;
if (currClientWidth < 320) currClientWidth = 320; // fontValue = ((62.5 * currClientWidth) /originWidth).toFixed(2); document.documentElement.style.fontSize = fontValue + '%'; }

四、移动端开发视窗口的添加
h5端开发下面这段话是必须配置的

<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">

其它相关配置内容如下:

  • width viewport 宽度(数值/device-width)
  • height viewport 高度(数值/device-height)
  • initial-scale 初始缩放比例
  • maximum-scale 最大缩放比例
  • minimum-scale 最小缩放比例
  • user-scalable 是否允许用户缩放(yes/no)
  • minimal-ui iOS 7.1 beta 2 中新增属性(注意:iOS8 中已经删除),可以在页面加载时最小化上下状态栏。

五、媒体查询的改进
之前在做移动端开发的时候,为了适配多屏幕。使用的是rem 单位。这个时候就需要根据屏幕的尺寸来来动态的设置根节点html 的font-size 值。这样可以解决多屏幕适配的问题。
比如下面的 媒体查询代码

html { //iphone5 font-size: 62.5%; } @media (max-width: 414px) { html { //iphone6+ font-size: 80.85%; } } @media (max-width: 375px) { html { //iphone6 font-size: 73.24%; } } 

这样做的结果,有两个很明显的缺点

  • 适配屏幕的尺寸不是连续的。
  • 在自己的 css 文件中添加大段的这样查询代码。增加了 css 文件的体积。

后来参考淘宝移动端页面适配规则,使用 js 获取客户端的宽度,根据设计稿的原型动态的计算font-size 的值。
详细的内容请看这里 根据iPhone6设计稿动态计算rem值

六、标签内容语义化

多数时候我们都会给一片区域加上点击跳转的功能。如下图:

很可能我们商品区域都是使用的div 标签。很容易我们会给最外层加上一个 a 标签。因为a 是行内元素,是没有宽和高的。不能够把容器撑开。
一种解决办法就是给a 标签设置block 属性。如下:

<style>
    a{display:block;}
</style>
<a>
    <div></div>
</a>

功能上已经没有问题。但是在语义化的层面上,上面的代码是不标准的。
最好的做法就是做如下的修改,这样不会使自己的 html 代码显的太突兀:

<style>
 a{display:block;}
 span{dispaly:block;}
</style>
<a>
    <span></span>
    <span></span>
    <span></span>
</a>
七、为自己的页面设置最大宽度和最小宽度 

果我们使用的是rem 单位,使用 js 动态计算font-size 值的话,我们可以无限适配最大和最小的终端屏幕。但是当用户的屏幕超过一定的尺寸以后还继续显示h5页面的话对用户会很不友好。
我们参看下京东和淘宝的h5 页面

我们看到了都是定义了页面的最大和最小宽度。这样在屏幕超过一定的尺寸以后可以更友好的展示(当然这不是必须的)。
我给自己的产品页面定义的最大的宽度和最小宽度分别是:

{
    max-width:640px;
    min-width:320px;
}

八、去掉 a,input 在移动端浏览器中的默认样式

**1.**禁止 a 标签背景

在移动端使用 a标签做按钮的时候,点按会出现一个“暗色”的背景,去掉该背景的方法如下

a,button,input,optgroup,select,textarea {
    -webkit-tap-highlight-color:rgba(0,0,0,0); /*去掉a、input和button点击时的蓝色外边框和灰色半透明背景*/
}

**2.**禁止长按 a,img 标签长按出现菜单栏

使用 a标签的时候,移动端长按会出现一个 菜单栏,这个时候禁止呼出菜单栏的方法如下:

a, img {
    -webkit-touch-callout: none; /*禁止长按链接与图片弹出菜单*/
}

**3.**流畅滚动

body{
    -webkit-overflow-scrolling:touch;
}

九、截断字符串
单行截断字符串,这里必须指定字符串的宽度

{
    /*指定字符串的宽度*/
    width:300px;
    overflow: hidden;
    /* 当字符串超过规定长度,显示省略符*/
    text-overflow:ellipsis;
    white-space: nowrap;
}

十、calc 相关问题
之前在做布局的时候使用calc 出现了很严重的线上 BUG。后来就深究了下这个属性的使用。
calc好用的地方就是,可以在任何单位之间进行换算。但是浏览器支持的不是很好。看一下 can i use 截图:
而且在使用的时候要加上厂商前缀,达到兼容性。不过现在不推荐使用,毕竟,浏览器支持有限。
示例代码:

#formbox {
  width:  130px;
  /*加厂商前缀,操作符(+,-,*,/)两边要有空格)*/
  width:  -moz-calc(100% / 6);
  width:  -webkit-calc(100% / 6);
  width:  calc(100% / 6);
  border: 1px solid black;
  padding: 4px;
}

研究过淘宝,天猫,京东的 h5端页面看到这个单位用的不多,主要还是兼容性的问题吧。
十一、box-sizing 的使用
解决盒模型在不同浏览器中表现不一致的问题。但是仍然会有兼容性问题。看最下面的浏览器支持列表。

box-sizing 属性用来改变默认的 CSS 盒模型 对元素高宽的计算方式。这个属性用于模拟那些非正确支持标准盒模型的浏览器的表现。

它有三个属性值分别是:

content-box 默认值,标准盒模型。 width 与 height 只包括内容的宽和高, 不包括边框,内边距,外边距。注意: 内边距, 边框 & 外边距 都在这个盒子的外部。 比如. 如果 .box {width: 350px}; 而且 {border: 10px solid black;} 那么在浏览器中的渲染的实际宽度将是370px;
padding-box width 与 height 包括内边距,不包括边框与外边距。
border-box width 与 height 包括内边距与边框,不包括外边距。这是IE 怪异模式(Quirks mode)使用的 盒模型 。注意:这个时候外边距和边框将会包括在盒子中。比如 .box {width: 350px; border: 10px solid black;} 浏览器渲染出的宽度将是350px.

十二、水平垂直居中的问题
可以看之前写定位的一篇文章,末尾有讲到各种定位:【从0到1学Web前端】CSS定位问题三(相对定位,绝对定位)
这里实现一个相对定位和绝对定位配合实现水平垂直居中的样式。看效果:
这里写图片描述
html 代码如下:

    <div class="parent-div">
        <div class="child-div"></div>
    </div>

css代码如下:

.parent-div{
            width: 100px;
            height: 100px;
            background-color:red;
            position:relative;
        }
        .child-div{
            width:50px;
            height:50px;
            background-color:#000;
            position: absolute;
            margin:auto;
            top:0;
            left:0;
            right:0;
            bottom:0;
        }

绝对定位在布局中可以很方边的解决很多问题,但是大多数时候都不去使用绝对定位,而是使用浮动等方法。而当需要 DOM 元素脱离当前文档流的时候才使用绝对定位。如: 弹层,悬浮层等。
十三、css 中 line-height 的问题
line-height 一个很重要的用途就是让我们的文本可以在父级元素中垂直居中,但是在使用它的过程中也会遇到一些问题。
先来看一个实例,如下图:
这里写图片描述
代码也很简单,就是当我们在div 中定义的字体很大的情况下,我们看到字体和父级元素之间有一些空隙。那么这是为什么?
我们查一下 line-height 的定义,如下:

normal 默认。设置合理的行间距。
number 设置数字,此数字会与当前的字体尺寸相乘来设置行间距。
length 设置固定的行间距。
% 基于当前字体尺寸的百分比行间距。
inherit 规定应该从父元素继承 line-height 属性的值。

所以在以上的情况我们要想使,我们的字体能够撑满我们的容器,就需要给父级容器添加 line-height属性且值为 100%
代码和效果如下:
这里写图片描述
那么为什么会出现上面的问题呢?

line-height 与 font-size 的计算值之差(行距)分为两半,分别加到一个文本行内容的顶部和底部。

所以,可以得出下面的一个公式:

空白间距 = line-height – font-size

所以,当设置为line-height 的值为100%的时候,line-height的值就等于 font-size的尺寸,此时的空白间距为0
十四、使用 vertical-align 调整图标垂直居中
很多时候我们要把图标和文字配合使用,而且需要图标和文字都能够垂直居中。如下图所示:
这里写图片描述
如果要实现文字的垂直居中很容易,只需要使用line-height=父容器高度 。但是要想使图标能够垂直居中就比较麻烦。
正常情况下我们的文字或者说相邻的容器,都应该和文字保持在相同的底线上,如下图:
这里写图片描述
明显的可以看到我们的返回图标不是垂直居中的。那么应该怎么样使图标垂直居中呢?
首先,我们先来搞清楚几个线的关系(图片来源于网络,侵权请告知):
这里写图片描述
这样我们就要用到 vertical-align 这个属性,最重要的一点是:
指定了行内(inline)元素或表格单元格(table-cell)元素的垂直对齐方式

baseline:将支持valign特性的对象的内容与父级元素基线对齐
sub:元素基线与父元素的下标基线对齐。
super:元素基线与父元素的上标基线对齐。
top: 元素及其后代的顶端与整行的顶端对齐。
text-top:元素顶端与父元素字体的顶端对齐。
middle:元素中线与父元素的基线对齐。
bottom:元素及其后代的底端与整行的底端对齐。
text-bottom:元素底端与父元素字体的底端对齐。
percentage:用百分比指定由基线算起的偏移量。可以为负值。基线对于百分数来说就是0%。
length:用长度值指定由基线算起的偏移量。可以为负值。基线对于数值来说为0。(CSS2)

看下边的一段 html :

    <div class="title-div">
        <img src="1_icon.png" alt="返回图标">
        <!-- <span >图标位置</span> -->
        <span>我就是标题</span>
    </div>

最初的结果是这样子的
这里写图片描述
十四、页面优化技巧工具
1.SPARK动画平台,这是我们组做的一个动画效果平台,里面集合了所有的牛逼动画,可以让你灵感猛增!(目前已开放外网使用);
2.OneDiv,这是个神奇的网站,里面的所有细节都是用一个div元素通过复杂的Css3实现的,有空可以去开开脑洞噢;
3.贝塞尔曲线生成器,动画速率太平怎么办?果断使用贝塞尔曲线来调节动画,这个网站可以帮你生成可视化的曲线。
 
十五、动画雪碧图
如果页面图片实在太多,可以分雪碧图,例如分成1-3张,因为三张图片是可以同时加载的,这里牺牲多2个请求换来图片同时加载比一张图片慢慢加载要好。

//style.css
@import url("reset.import.css");
@import url("loading.import.css");
@import url("m-animate-1.import.css");
@import url("m-animate-2.import.css");
@import url("m-animate-3.import.css");

十六、 图片压缩
图片压缩是老生常谈,但是仍然有不少人忘记压缩,那可是活生生的带宽和流量浪费啊…
压缩图片需要有好工具,这里推荐我们做的一个工具智图,相关介绍请看ISUX官博文章
但是仍然有以下方式优化图片:
1.尽量避免用PNG24。如果图片色彩要求不高,请使用PNG8;
2.使用新格式,WEBP和BPG等新格式的到来,在不用考虑兼容的情况下请大胆尝试;
3.用SVG和ICONFONT代替简单的图标;
4.用糖饼和FUFU的字蛛来代替艺术字体切图。
十七、多终端兼容
1.CSS3 Media Query,按范围兼容机型。
 
 

/*iphone6*/
@media only screen
    and (min-device-width : 375px)
    and (max-device-width : 667px)
    and (orientation : portrait)
    and (-webkit-min-device-pixel-ratio : 2)
{
    .page6 .ele-building{top: 69px;}
    .page6 .ele-runner{top: 100px;}
    .page6 .ele-pophome{top: 16px;}
}

 
2.类覆盖,这种方式适合直接为小屏或大屏做整体兼容。
首先,为小屏(大屏)加一个识别类,这里小于420表示为小屏幕(IPHONE4有上下导航栏):
 
 

var bh = $(window).height();
// 480 - 64 = 416 iphone4
if(bh<420){
    $('body').addClass('low-screen');
}

 
然后,对应识别类加上要变动的元素,例如:
 
 

.page6 .ele-bg{top: 10px;}
.low-screen .page6 .ele-bg{top: 0px;}

 

 

!function(){function e(){var e=document.documentElement.clientWidth,t=1;t=e>768?2:320>=e?.853:e/375;var n=Math.floor(16*t)+"px",o=document.getElementsByTagName("html")[0];o.style["font-size"]=n}e(),window.onresize=e}();;

 
十八、 交互提示
前面说了,加了音效就要加上音乐切换开关的按钮,不然用户会骂死。还有其他,例如如果你的页面不能兼容横屏,请监听横屏状态,然后加上适当的横屏提示。
例如:
 
 

// 横屏监听
var updateOrientation = function(){
    if(window.orientation=='-90' || window.orientation=='90'){
        $('.landscape-wrap').removeClass('hide');
        console.log('为了更好的体验,请将手机/平板竖过来!');
    }else{
        $('.landscape-wrap').addClass('hide');
        console.log('竖屏状态');
    }
};
window.onorientationchange = updateOrientation;

 
提示越多,界面越友好,有时候设计师会漏掉一些可能出现的页面情况。作为有态度的前端,请好好把关,让用户有好的体验。
十九、分享接口
H5做好了,要传播分享才能展示你的牛逼轰轰呀。然而分享一切是个坑,分享到微信、手Q、空间、微博等都有各种问题,为此我还写过一篇文章《HTML5页面分享功能》,里面有各种方法。
然而最近微信开放了微信API,分享功能越来越牛逼了,相信日后分享的坑会越来越少。
二十、SEO和无障碍
SEO(搜索引擎优化)是个长谈啊,但基本的做法是写好meta标签,写好页面结构(H1-H6的层级树),用好语义化标签等等。
其实分享接口,SEO,还有无障碍都基于良好的HTML结构,这是玩转页面的基础。
二十一、重力陀螺仪
想让页面更有层次感,不妨让设计提供一些碎片元素,例如彩花,星星之类,然后把它们单独切出来放画面前景,使用陀螺仪伴随着手机运动碎片也跟着运动,多么好玩!
这里提供一个工具可以轻松实现陀螺仪重力效果的:parallax.js
用法简单,定义一个parallax-obj的父类,把需要动的元素加上layer的类,然后设置动的范围data-depth:
 
 

<div>
    <div data-depth="1.00"></div>
    <div data-depth="0.80"></div>
    <div data-depth="0.30"></div>
    <div data-depth="0.30"></div>
    <div data-depth="1.10"></div>
</div>

 
最后只需要调用:$(‘.parallax-obj’).parallax();就一切OK了。
二十二、背景音乐&音效
H5页面要炫酷,画面生动还是不够的,一定要配合生动的音乐。因此可以主动跟设计或产品沟通,让他们可以提供音乐资源,分分钟导致UV猛涨有木有!
当然,有了音乐,前端也不是直接引用的,还是有点要求:
1.音乐不宜过长,30s为佳,而且音乐要加上渐现渐隐效果,方便循环播放;
2.音乐体积要小,音质和流量,在手机上还是优先考虑流量吧。
一般背景音乐体积可以接受的范围是200K以下,若太大,可以使用格式工厂等软件,降低它的比特率和声道来改变体积。
接着,只需要简单引用:
 
 

<audio id="audio" src="音乐地址" loop preload="auto" autoplay="true"></audio>

 
这里有个问题,IOS是不能自动播放音乐的,一定要触发一个用户交互事件,例如点击,但是有一种自创的hack方法可以规避:
通过new一张图片,监听一张图片的onload事件,结束后回调执行音频播放audio.play()即可,原理估计是动了dom结构,相当于执行了一次交互。
最后,记得暴露一个音乐关闭/打开的按钮,不然肯定被用户骂死(°ロ°٥)。
二十三、有趣的loading
Loading页还是要有的,万一用户网速慢呢?
以上做了那么多事,如果没有资源加载都是玩不来的,因此还需要一个loading的支持。
然而loading还是可以做得很有趣的,一般的做法是:
1.引入品牌,例如APP宣传页;
2.引入有趣动画,放一个贱贱的人物跳舞给你看;
3.一切从简,用CSS3简单动画。
=======
休息区
说了那么多,来个例子吧(电脑上用Chrome模拟手机打开):
查看DEMO
这是空间5.0预约页第二版,使用了以上的若干方法论,例如loading动画,CSS3动画,SVG星空连线,首屏星球重力感应,音乐(这里使用开启按钮后播放)等等。
二十四、高清屏和普通屏幕及其适配方案

1.Media Queries的解决方案

根据屏幕的设备像素比来加载不同图片可以使用css 的media queries来解决,当然使用css来解决也是兼容性最好的解决方案(其实意味这我们要切两套图片1倍图和2倍图)。
示例的demo如下:

.css{/* 普通显示屏(设备像素比例小于等于1.3)使用1倍的图 */
    background-image: url(img_1x.png);
}
@media only screen and (-webkit-min-device-pixel-ratio:1.5){
.css{/* 高清显示屏(设备像素比例大于等于1.5)使用2倍图  */
    background-image: url(img_2x.png);
  }
}

CSS Media Queries的优点

  • 只有对应的目标元素才会下载图片资源
  • 跨浏览器兼容
  • 像素可以精确控制

    CSS Media Queries的缺点

  • 单调无味的实现过程,特别是大型项目中
  • 只能通过HTML元素的背景图片来实现,无任何语义化可言

2.JavaScript的解决方案

使用js对“window.devicePixelRatio”进行判断,然后根据对应的值给Retina屏幕选择图像。

$(document).ready(function(){
  if (window.devicePixelRatio > 1) {
    var lowresImages = $('img');
    images.each(function(i) {
      var lowres = $(this).attr('src');
      var highres = lowres.replace(".", "@2x.");
      $(this).attr('src', highres);
    });
  }
});

Javascript查询的优点

  • 易于实施
  • 非Retina屏幕不用下载过大的资源
  • 像素精确控制

    Javascript查询的缺点

  • Retina屏幕下必须下载标准备和高精密度的两个资源
  • Retina屏幕下图像交互可见
  • 浏览器兼容性不强

3.使用SVG矢量图像

SVG矢量图的优点

  • 一个资源适合所有设备
  • 易于维护
  • 面向未来的:可伸缩向量图形

    SVG矢量图的缺点

  • 没有像素那样有精度
  • 由于文件大小,不适合复杂的图形
  • 不支持IE7-8和早期的安卓版本

二十五、动画卡顿的解决方案
2.1 改变元素位置使用 css3 新属性,触发 GPU (硬件加速)辅助渲染动画 扩展阅读点这里
2.2 使用 chrome 开发者工具,查看动画元素是否造成周围大量 DOM 节点的重排(reflow),如果是则对动画元素使用 absolute 定位,脱离所在文档流,减少对周围元素的影响。
2.3 对要做动画的元素使用backface-visibility,opacity,perspective
这里属性主要是设置动画元素只渲染面向用户的一面。减少动画渲染对系统性能的消耗。

{
-webkit-backface-visibility:hidden;
        backface-visibility:hidden;
        -webkit-perspective: 1000;
                perspective: 1000;
}