无线web开发经验(3)—— CSS

CSS3有很多类型,大致可以分为以下类型,布局类型、渲染类型、选择器类型、动画类型。

CSS reset

在讲以上布局之前,需要说一下关于CSS的reset的问题。关于这个问题,需要追溯到HTML4的时代,在那个时候,由于PC有各种游览器、各种标准、造成对于HTML的各个标签所带的默认样式的不同,结果造成要在各个平台统一一个样式会非常难。因此出现了reset,所谓reset的意思是把所有HTML的标签的默认样式进行重置,这样方便在所有平台进行页面制作开发。跨入无线Web的时代之后,reset是否还要存在,业界有着非常多的讨论。主要分为两派:reset派和normalize派。reset派认为就算是到了移动时代,还是有各种碎片化的问题,需要reset,而normalize的一派认为,到了无线Web,很多规范已经收到了很多厂商的支持,最出名的要属Google和苹果,因此不需要进行reset,只需要将那些标签进行统一化,即可。

因此,在市面上做移动开发,有两种CSS模式,reset模式和normalize的模式。两者没有绝对的好与坏。主要看这个项目的特性。

  • reset模式 适用于严格要求所有的平台必须完全按照统一的一个形态的进行开发的项目,一般而言,对于webapp的类型的项目,可能使用reset更加适合。reset模式也适合UI控件的编写,因为UI控件有着严格的标准,使用reset,可以更加好的进行精确控制。
  • normalize模式 此模式适用于Web特性的网站,所谓Web特性的网站,是指那种适合各种平台,并且在不同的平台需要体验各平台自己特性的网站,不需要强制要求所有平台进行统一。

不过就大多数项目而言,一般产品经理和交互都会要求在各个平台需要有个统一的产品表现,因此在实际项目里,reset可能用的会更多一点。

布局类型

布局类型的CSS,是指这些属性影响着HTML的布局方式。HTML4最经典要属position、float等这些使用频率极高的属性,进入移动时代,可以使用flex布局。
flex
对于flex的布局, 可以参考我之前总结的另一篇文章 深入解析CSSFlexbox

  • flex的属性使用,在手机端使用flex的时候,尽可能使用比较少的属性,因为不是所有手机都实现了flex的所有属性,因此在使用的时候,建议仅使用flex这个属性,此属性基本满足了绝大多数的场景需求,对于其他的各种属性,如果一定要使用,建议在stackoverflow和google搜索一把,或者参考 http://caniuse.com/。 确定它没有兼容性问题。

fixed
固定布局fixed可以说在PC上使用的非常多的一个属性,在手机上使用fixed属性,需要非常的谨慎小心。以下专门分两个平台详叙述:

  • ios系统 fixed在ios5之后,才正式开始支持fixed的布局,在ios5之前,苹果处于性能上的考虑,并没有实现,因此在使用fixed的时候,需要注意你所做的项目对ios的版本最低支持的版本,不过即使ios5之后,开始支持fixed属性,在实际使用中,还是有很多小坑在,国外专门有个网页再说ios的fixed的问题。提供以下地址,可供参考:http://remysharp.com/2012/05/24/issues-with-position-fixed-scrolling-on-ios/ 。比较安全的做法是,在固定的布局里面,尽可能保持里面的结构简单,不要出现过于复杂的布局,一般app的头部和尾部可以使用fixed属性。
  • android系统 android系统在2.1之后,就已经开始支持fixed,不过由于各个厂商对于fixed的实现不同,2.1和2.2对于fixed的支持不是很好,在滚动的时候会出现闪动,消失、位移等各种渲染问题。2.3之后的版本,fixed的问题相对少一些,不过在个别厂商的手机上也会出现各种渲染问题。从4.x开始,fixed的表现比较好。因此如果在android上需要fixed的效果,需要综合评判其效果。

before,after
before,after 可以说用的最多的可能是这两个CSS属性。其具体的含义,可以参考各种文档,这里就不详细述说。这里说的是它的一般使用场景。before和after原先在w3c的定义中,主要在节点的前面和后面插入一段内容,因此在before和after中必须要有content的属性以及数值。不过在在实际项目中,通过它自动在节点前和后面插入一个节点,通常不会插入一个文字,而是一个绝对定位的图标之类的元素。虽然这个实现在html中加个结构可以实现,不过通过before和after来插入的节点,有个好处,就是能是html的结构显得更加精简和语义化更加强。不过带来的不便之处,就是进行问题的排查,因此无法直接通过查看html结构查看before和after的元素类型。不过现代游览器自带的debugger工具,都能够进行查看,问题不是很大。因此对于这两个伪类,推荐大家使用。

渲染类型

渲染类型是指该类型的主要的功能是在渲染html结构上,说的通俗一点,就是在结构上加上各种颜色,尺寸。可以说CSS的一大部分做的都是这些事情,渲染类型按照不同的角度,可以分为很多种类型,不过以下从维度的区分,2D和3D。

2D渲染

绝大多数的CSS的属性都属于2D的渲染。由于在CSS3中加入大量的有用的2D渲染的属性,以前需要使用图片才能实现的效果,现在通过CSS的设置也可以实现,以下主要说明比较常用的属性,以及使用注意点。

  • border-radius 圆角类型 这是个非常常用的CSS的类型,几乎在所有的项目多多少少都会用到,以前在html4的时代,实现圆角是一件很费劲的事情,css3带来的属性可以很好地解决圆角问题。不过在实际使用圆角的时候,需要注意,在ios上面,实现的比较完美。在Android上,需要注意,很多机型,对于圆角的渲染处理并没有达到一个理想的状态,特别是处理圆角和直线的连接,在圆角的半径设置比较小(1-3像素)的时候,不是很明显。不过当超过4像素的时候,在部分机型上,会出现明显的圆角的边缘和直接差半个像素的问题。如果半径超大(>10px)的时候,圆角会有非常明显的锯齿。因此对于大半径的圆角,不推荐使用border-radius,建议使用border-image来实现
  • box-shadow 盒模型阴影,此属性使用一般不会太大的问题,至今还没有发现非常大的问题,可以比较放心的使用。不过有些Android低端低版本机不支持box-shadow,这个需要注意一下,不过问题不大,因为大部分对于盒阴影不会特别明显,用户一般不会特别注意。
  • text-shadow 文字阴影 文字阴影在手机web上基本都支持,可以使用,不过有一点需要注意,在android 2.3以及之前的版本,在blur radious为0的时候,文字阴影会失效,需要注意。
  • linear-gradient 线性渐变其本身不是CSS的属性,而是属性下面的数值,一般用在background的属性里比较多,使用线性渐变需要注意,有很多种线性渐变的表达方式,对于不同的手机、版本也会有所不同。在手机web上面,使用这种格式比较安全,-webkit-gradient(linear, left top, left bottom, from(), to())
  • border-image 在日常的使用中,border-image是一个相当使用的属性,其主要的用途,是进行图片的拉伸,具体的使用方法,可以在网上自行搜索一下,估计里面会有这样一个问题,就是如果一个图片被拉伸到一定宽度之后,四个角的图片那里会有变形,这个在部分android机上发现的,不过此类机型不是很多,不过还是需要注意。
3D渲染

3D渲染是个非常cool的属性,它能将页面上的元素进行3D化的渲染,实现各种非常炫酷的效果。不过由于其非常的先进性,所以能支持3D的属性的机型、版本、厂商也会有很多的不同。因此这里说3D,并不是要使用3D里面的属性,而是使用其特性。

从实践的角度来看,3D的最大的好处,它使用了硬件加速功能,虽然可能直接使用它的各种属性有困难,但是它却给我们一个很多的硬件加速特性支持。因此在做页面动画的时候,即使不是做3D的变化,却可以通过3D的设置开启硬件加速功能。使用 translateZ(0);可以是当前的节点开启硬件加速功能,又不会带来任何的渲染变化。这里很多人会认为使用2D的动画会开启硬件加速,其实不是,必须使用3D,才会开启,这个需要注意

选择器类型

CSS3提供了大量新的选择器,使得选择一个节点变得非常简单,CSS3的选择器很多,大多数在手机里都支持,不过对于日常项目的开发,以下的几种类型会非常常用的,大家可以做参考,对于其他的选择器,可以参考网上。

first-child、last-child
这个也是非常常用的伪类,特别是用在布局中,有一个非常的经典的场景,就是一个列表,要求一个列表项的上边和组后一个列表项的下边是圆角。之前如果需要实现的话,需要额外增加class来实现的。如果使用这些伪类的话,就非常的简单。

属性选择器
在诸多的CSS选择器中,属性选择器是个非常好用的一个类型,比较常用的一种场景是input的样式修改,因此input的属性比较丰富,针对具体某一类的input类型的样式修改,如果通过以前的方式,只能通过增加class的名字。现在使用属性选择器后,代码量和复杂度会大幅度降低。

动画类型

动画类型是CSS3中一个比较有用的一种类型,它可以实现节点的动画效果,配合js,可以让其动画变得非常的丰富。不过对于如果正确使用动画上,也需要处处小心,最关键的是性能问题。

很多在PC上没有的性能问题,一旦到手机上就会变得非常的明显。其中动画就是。由于网页的DOM的特性,动画是非常消耗性能的,再加上网页是单进程单线程的,因此所有的程序运行都会在一根ui线程里运行。手机上的性能还没有达到PC上的性能,因此动画的性能问题在手机上显得异常突出。

不过不用过于悲观,也不是不能使用,但是在使用上,需要小心谨慎,可以准从以下标准(没有绝对也没有一定,看实际效果)

  • 动画触发的reflow要尽可能小
  • 动画尽可能使用absolute的方式
  • 动画的区域尽可能小,并且里面的结构要简单
    +文字的动画性能消耗较小,图片次之,复杂结构最耗性能(比如说html嵌套n层结构,里面包含float,flex等复杂布局)
  • 不推荐使用3D动画,各种厂商的实现差异很大
  • 不推荐整个页面的动画,比如说模拟native的整页切换效果
  • 动画的话尽可能使用CSS而不是JS,如果使用JS的话,推荐使用webkitRequestAnimationFrame的方式(如果支持的话),具体如何使用,请大家自己google
  • 对于动画的节点,开启硬件加速 translateZ(0)
  • 动画的时间不宜过长,经验来看500ms-1s,就差不多了,时间越长,其性能问题越明显

以上是使用前的注意点,如果已经确定都没有问题的话,开始进入正题。一般使用2D动画,主要会使用以下两个属性,transition和animation。

  • transition 这个属性在手机web的各个平台上支持的比较好,不过需要加上webkit的前缀,已保证在老机型上没有兼容性问题。transition可以进行动画变化的CSS的属性比较多,width,height,color,background等都可以支持。如果不是很确认的话,可以设置成all。

不过在使用的时候,需要注意以下几点:width和height,如果设置成auto的话,动画变化会比较诡异,建议动画起始都是具体的像素或者百分比。background如果变化的是图片的话,图片切换的效果并不是非常理想,避免对不同的图片进行变化,不过可以考虑使用background position,进行位置的变化。

  • animation 这个属性的手机浏览器基本都兼容,不过在低版本需要加上-webkit的前缀,animation适合用在需要重复触发的动画上面。

从实践的角度来看,transition和animation使用的场景不太一样,transition适合用在短而小的动画上面,animation适合用在会不断重复的场景里。在使用动画动画的时候,需要注意几件事情:

  • 动画不一定触发,在css的某些设置的时候,会发现动画无法实现,特别是快速切换的时候,会发现所设置的动画强制跳过

  • 动画出现断帧的现象,即看到的动画卡,发生断帧一般处于以下几种原因

  • 动画期间,发生垃圾收集,这个时候整个页面会强制停顿数百毫秒,对于这种原因,没啥办法,因为页面无法控制垃圾回收机制,因此动画不要太长时间,否则遇到的几率就会变高

  • 多段动画发生,由于单线程的原因,当一段动画在播放时,如果出现另外一段动画,势必就将当前的动画渲染暂停,因此在同一个时间段内,不适合多个地方出现不同的动画

  • 在动画播放期间,发生了js的操作,这种情况一般出现在js之前有通过setTimeout或者setInterval的方式,进行异步的程序,特别是在ajax的场景下,会发生。想象一下,在ajax获取数据的时候,会出现一个loading图标,当remote的数据到来时,js会进行很多操作,数据格式化,组合模板,渲染部分页面,这些都会影响loading的动画,如果loading是用动画实现。

  • 在发生动画的时候,系统发生某种事件,或者手机内其他后台程序突然使用了大量的CPU的时间,也会造成卡顿。不过这种情况,随着手机的性能的改善,发生率会降低。

  • 动画需要准备时间,这个听起来好像不可思议,不过确实需要,在PC上,由于硬件性能非常强劲,准备时间非常少吗,不过在手机上,就是另外一个天地。 举个简单的例子,对某个元素做一个45度的旋转,一般的做法是在这个元素上加上初始化class,比如说角度初始化为0,然后加上结束class,即角度为45度,由于设置了transition,渲染引擎会自动将0度转到45度。不过在某些手机上会发生这个元素,没有动画,突然跳转到45度。其原因在于,当用js设置初始化0度的时候,浏览器引擎需要将这个元素进行初始化的设置,这个时间非常短,不过还是需要时间的,比如说10ms。 如果在js的后面的语句马上加上结束的class,如果这句语句只用了8ms,也就是说游览器还没有为前面一个元素加上动画的时候,后一个class已经到了。这个时候,就会强制将css设置为结束的属性。因此一般在使用动画的时候,会人为将结束的class通过setTimeout晚几十ms加上。具体几十ms看动画的时间而定。

  • 无论是transition还是animation在w3c里的定义里有动画结束时触发的事件,不过有时候,这个事件是不会触发的。根据实践来看,在以下几种情况下可能不会触发:

  • 当前节点的一个动画还没结束吗,另外一个动画马上设置,之前的动画结束事件有时候会消失,其具体原因不明

  • 如果当前节点动画,因为准备时间太长,而结束属性已经设置,则不会触发动画结束事件

  • 如果在动画期间,发生垃圾回收等其他事件所造成的时间超过其动画时间,动画结束事件可能不会发生

综上所述,在手机web上使用动画的时候,需要谨慎。

CSS px,设备独立像素,设备物理像素相关概念及关系总结(From悦悦)

基本概念
CSS px 与 device px的概念
  • css px:浏览器使用的抽象单位,主要用于在网页上绘制内容

  • 设备物理像素(physical pixel):设备能显示的最小的单位,也就是显示器上能看见的一个个点

  • 设备独立像素:(也称密度无关像素),可以认为是计算机坐标系统上的一个点,这个点代表一个可以由程序使用并控制的虚拟像素,然后由相关系统转换为物理像素

screen.width/height:获取屏宽/屏高。无论横屏还是竖屏该比值不会变化

  • 所以不管是移动端还是PC端通过screen.width/height 获取的这个值是设备独立像素(CSS 像素),而不是设备的屏幕分辨率,因为设备的屏幕分辨率对于WEB开发者来说是无法通过代码来获得的,是完全透明的。
设备物理像素和设备独立像素之间的关系

在一定条件下,设备物理像素 = 设备独立像素= css px。比如,在PC端浏览器默认情况下(100%,即页面没被缩放)。

在移动端设备物理像素和设备独立像素之间通常是不相等的,需要通过一定的公式转化。

  • PPI 全称是(pixel per inch)翻译下就是每英寸内有多少个像素点,这个像素点指的是设备像素点(物理像素),说得接地气点PPI就是像素密度(pixel density)。PPI的值越高,画质越好,也就是越细腻,看起来更有逼格。
  • DPR 设备像素比:设备像素比 = 设备像素/设备独立像素

通过PPI可以确定屏幕的的画质是否细腻,但是实际开发过程中,并无需关心它,反而是DPR 才是开发者应该关心的问题,因为DPR反映的正式物理像素和实际CSS px 之间转化的公式。

实际开发过程中你可以通过JavaScript 中的window.devicePixelRatio来获取设备中的像素比值。而在CSS中,可以通过-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和 -webkit-max-device-pixel-ratio进行媒体查询,对不同dpr的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview)然后部署自己的响应式方案。

深入理解参考文章
http://isux.tencent.com/mobile-development-essential-knowledge.html
http://yunkus.com/physical-pixel-device-independent-pixels/

你可能感兴趣的:(无线web开发经验(3)—— CSS)