一、页面在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解决方案
- 当我们在根节点
<html>
上设置了font-size
基准值以后,在文档中有使用rem
单位的属性值都是相对于根节点font-size
的一个相对值。比如说一些元素的属性如width
height
margin
等。也正是这个原因,现在很多网站的移动端网站都在使用rem
单位作为适配工具。 - 将计算根元素的font-size值的js放在head标签中
- 使用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; }