日期:2014-05-17  浏览次数:20675 次

css之六个为什么---关于性能关于习惯【杂记】

一、css为什么放在在head中而不是body里面或者其他地方?

  都说放body里面是不符合标准,其实最主要的原因不是如此,因为我们在实际情况中会有body中出现css链的存在(虽然这样很二,但是却不得不承认偶尔这样二的事还是会发生),事实也证明在浏览器的宽大下这样的方式也可以正常处理,那么言归正传为什么要尽力把css链放到head头部呢?浏览器页面渲染方式是在所有的stylesheets(也就是前面的css链)加载完成之后,才会开始渲染整个页面,在此之前,浏览器不会渲染页面里的任何内容,页面会一直呈现空白(这也是一些网站前几秒空白的主要原因之一)。这也是为什么要把 stylesheet 放在头部的原因。如果放在 HTML 页面底部,页面渲染就不仅仅是在等待 stylesheet 的加载,还要等待 html 内容加载完成,这样一来,用户看到页面的时间会更晚。顺带说下现在很早不用@import也是因为,它的处理方式是将css <link> 标签放在页面的底部加载。



二、关于图片属性with和height是否多余?
  在我们实际的运用中,相对有经验点的前端在img的外部都会有相对的包裹也就是parent box来限制图片的宽高,避免二B的产品传错图片搞乱整个页面布局,处理这个问题的方法每个前端可能都不同有的是定义父级的宽高然后在进行overflow:hidden;而有的可能是直接继承或者给图片类来设置死图片的高宽,那这个时候问题来了,我们这里已经对图片做了诸多针对二B的保护措施,那图片的这个2个属性是否多余了?NO,在这里我们首先必须肯定前辈们设置的每个属性标签都是有它存在的价值和经过诸多考虑的(当然随着互联网的发展,废去的诸多标签属性,并不是前辈考虑不周而且互联网进步实在太快了),在css 的渲染过程中,它是逐一渲染堆叠的(和叠沙楼一样先渲染完前面的才继续往下渲染),而在这个堆叠渲染的过程中当已渲染元素的宽高等layout改变时会重新回头开始渲染(这也就是所谓的回流),而在页面加载过程中从html的读入到css的渲染,图片加载总是会慢人一步(很多情况下css读写完毕后图片可能还并未加载出来),因此指定的所有图像的宽度和高度可以通过消除不必要的回流与重绘需要更快的渲染,当然对于父级已经固定宽度的行为这里img的属性也就相对没有那么重要了。
  说到图片这里顺带说下,不要对图片进行缩放也就是图片的实际大小大于他的显示必要,比如一个800*600的图片,而我们在页面上只显示的是400*300的大小,那么这便是一种服务器资源的浪费(当然这个其实完全要看后期产品维护了),同时alt这个属性千万别偷懒,或许这个属性在正常情况下基本没用处而且浪费字节,但是对于灰色世界的盲人来说图片他们是看不到的,而alt才能告诉他们这是一张什么样的图。
 


三、css选择符越详细越好吗?为什么?  
  其实这个问题,我想很多前端都不会犯,但是对于新人或者涉足不深的人来说偶尔不经意间还是会写出来,在说这个前,首先我们应该知道css的查找方式和js的不同,总所周知js查找元素是从上向下的查找,也就是先查找到父级,接着在是子级,而css则相反,它的属性选者符是从后向前查找的,比如.class .a则是先会遍历整个dom树查到类名为a的元素接着在继续向上查在这个元素的父级上有没有一个类名为class的元素,没有的话这继续查找直到查找完所有的元素为止(http://www.zhihu.com/question/20185756/answer/14263713),因此对于属性选择符则是越简略越好(当然基于模块化却不能完全执行这个准则),因为这样会加快查找速度(无需根据上级类去一一匹配),同时也会方便你的维护和修改,除了性能还能方便维护和修改,因为对于选择符优先级,越详细则写的越深(即层次越多)那当下个元素需重用覆盖的时候必须要写比前者更高的优先级层次,那么这样的模块越多你的代码也就叠加的越高,而且对于以后的模块迁移调整起来更加是场灾难;例如要定义div .a 下的 ul 中的所以li的字符大小 .a ul li{font-size:12px;}这样中的ul是远远多余的因为li本身就是不可能单独存活的,当然如果你a中有ol的话那我更加建议给ol和ul分布加上类去单独定义;
 


四、expression为什么不建议用?以及*通配符为什么也不建议用?   
   对于万恶的ie6中最小宽高不得不说是比较让人郁闷的东西之一,而那个时候expression闪闪发光的跳了出来,后来渐渐隐没当然还是有那么一小撮怀旧的偶尔会用用,很多人只知道用它性能不好也就不用了,但是却不知道为什么性能不好,其实相对的来说在css中能直接运用expression这样的js表达式来处理一些简单的事情还是比较前卫和值得开心的(当然这样和分离有点背道而驰了),但是不幸的是这个属性仅仅是ie特有的,而且它运用起来性能存在严重的问题,它的问题就在于它的计算频率要比我们想象的多,不仅仅是在页面显示和缩放时,就是在页面滚动、乃至移动鼠标时都会要重新计算一次,大家可以做个测试在这个表达式中增加一个计数器来跟踪表达式的计算频率,最后在页面中随便移动鼠标,可以看到它轻松达到10000次以上的计算量,想想这鬼东西背着我们在后面吃了我们多少内存。所以真爱用户远离expression,其实针对ie6对于宽高的处理特性来说换个方向,它是远远都足够表现最小宽高的(ie6对于宽高处理方式是元素大于父级时会撑大容器而不是溢出),当然最大宽高的解决方案相信亲都不用我说了这里也就节约下力气。    
   然后我们说说通配符,我记得在08年那段时间通配符真是个神器,为我们可是省了不少力气,大家那个时候都爱用它,甚至很多书本也会专门的划出一部分来讲它,但如今相信很多人都不用说已经开始摈弃它了,大家都有了一套自己的reset小库或者小段落,但是为什么这么省事的东西现在大家却想法不用呢?因为对于*它会遍历所有的dom去一一的执行我们定义的样式,那这可真不是个小工程,就像大家以前最常用的*{margin:0;padding:0}这个会设置所有的元素内边矩和外边距,但是在实际情况中并不是所有的元素都需要这样做,那它带来的就是负担了,同时也尽量要避免类名下直接定义通配符,这样做浏览器会匹配文档中所有的元素后分别向上逐级匹配这个类的元素,直到文档的根节点,其匹配开销非常大,通常比开销最小的ID选择器高出1~3个数量级,所以也要避免使用关键选择器是通配选择器的规则。(关于css选择符及性能更详细可以看看https://developers.google.com/speed/docs/best-practices/rendering?hl=zh-TW)

   
五、css合并图片是越多越好吗?    
  现在对于超链过多请求影响网页加载是大家总所周知的一件事,大家都会习惯图片合并成一张,来获取更好的性能,在这样做的同时也付出了一定的代价,图片的体积更大了,更有甚者一张图高达200多K,这样图片带来的效果是否会真的更加好?我们都知道这样合并之所以好,是因为它减少了从服务器多余的请求所消耗的等待时间,比如10张4k的图片那就要请求10次,最后的总大小也就是40k,但是图片合并到一张后只需请求一次,而且合并后的图片可能并不会大于这40k(合并的图片要比分离的图片的总和要小,因为它降低了图片自身的开销如颜色表、格式信息等),这其余的九次请求也就是节约来的性能,但是事情也是相对的,请求次数是少了,但是服务器承载的负担却会比开始大大增加同时以太网最大传输单元MTU为1500字节而当我面合并的图片过大时会最大限度地加大动态和静态资源的有效载荷大小增加网络延迟。对于一个大型的门户网站来说一张200K的图片每天几十万几百万的请求对服务器的承载负担是相当重的,在css和页面渲染完毕后背景图片会姗姗来迟所带来的交互也是很不好的,同时对于后期的按钮等修改带来的维护成本也很高,所以这里建议合理运用。(更详细的可以可以看看https://developers.google.com/speed/docs/best-practices/payload?hl=zh-TW)
 
 
六、table真的那么可恶不要运用吗?还有html怎么去优雅合理运用?
  现在很多面试都会问是div+css吗?不用表格的吧?(当然前几年比较多,现在都改为会css3和html5,我擦)其实这样问的多数都是你未来的lead,对于表格其实我想说它真的很冤枉,