CSS编写时的高性能以及高维护性代码优化建议总结
性能,这个词如今被炒的很热,也是每个开发者,由“知道”、“会做”之后必经的一个“怎样做好”的阶段。性能关乎用户在不同设备和不同网络状态下的体验。也被多方面因素所影响。此文说说css方面怎样做到高性能。
高性能css
Html和css本身的性能问题并不突出,在提高可读性和可维护性的前提下,如果能让代码运行和解析的速度更快,则是锦上添花了。
一、使用高效css选择器
简单来说,能被浏览器快速解析和匹配的css选择器,就是高效的选择器。
首先要知道浏览器如何解析css
举个例子:
- .nav ul.list li div{}
我们常见的思维是,先去找到nav这个类,再找类包含的ul,再找ul中类为list的后代所有li中所有的div,简而言之,就是从左到右。可事实是这样么?么?么?~
事实是相反的!意味着什么呢?就是说它不是从第一个开始去慢慢的缩小范围,而是从div这个“裸奔”的盒子开始,相当于遍历,然后再找到li,以此类推,好吧不用我形容你应该知道这当中的消耗。理解这一原理非常重要,高效的选择器意味着匹配更快,查找次数更少。所以我们定义选择器时,应该让第一次匹配时的数量达到最少,并且让整体的匹配查找次数最少。
以上这些解释恰恰遵循了这样一些原则
(1)避免使用通配符
(2)避免使用标签选择器和单个属性选择器作为关键选择器
(3)不要在id选择器前加标签名
(4)尽量不要在选择符定义过多层级,层级越少,同时也降低了css和dom结构的耦合程度,提高样式的可维护性
(ps:老实说上面的这些“禁忌”你是不是都有犯过?~)
做个小结,以上所说,有两点需要知道,第一点在开头就已经提到,css的性能问题表现的并不突出,特别是在小项目中,所以,可维护性为先;第二点是虽然定义id选择器,有唯一性的优势,但是一个页面只能定义唯一id,定义过多id会使重用性降低,维护更困难,所以不建议多用id。
二、css相关的图片处理
现在的网页当中,图片所占的比重以及它的重要性大家都知道。那么如何处理好图片以及如何为图片设置样式,才能让用户打开网页时体验更好呢?下面给出一些意见:
(1)不给图片设置尺寸
在我个人的从业经历当中,有过这样的情况,我按照设计稿做好了页面,交给后台去测试,他就突然跑过来跟我说:hi,你看,这儿出状况了,我一看,坏菜,图片出格了,我才想起没有给图片定义宽高(直接从设计稿里切的也不需要),然后就犯错了似的在css样式里定义了宽高。以至于后来我把这个作为下次再做页面时候的注意事项。当我看到这一条意见的时候,才更知一二。
来看解释,第一、设计人员为了画面的精美,会制作一些超出需求尺寸的图片;第二、同一张图片可能会在页面不同地方多次使用,比如缩略图、正常图、大图。问题来了,如果图片原始尺寸和实际需求不同,在使用过程中就会存在性能问题,利用样式缩放会带来cpu的额外计算过程,增加了图片在浏览器的渲染时间,网络传输过程也会占更多带宽,增加下载时间。因此,最佳做法是,为需要的部分单独做一套图片,初始页面加载时就能更快展示。
(2)使用css“雪碧图“
是将零散的图片合并成一张大图,在利用css进行背景定位。好处是减少请求数,提高了图片整体的加载速度。
但它也存在一些缺点:
比如,多张图片合并成大图,需要精确计算,仔细的调整位置,单纯手工制作是一件很复杂的事情。(所幸现在有一些工具可以帮我们做)
另外,维护过程复杂,要尽量让已有的图片保持原来的位置不变,如果是背景图的尺寸发生变化导致原有区域无法放置,那就只好放弃,如果非要在原有位置修改,则剩余的图片样式都需要修改,是很繁琐的过程。新加的图片最好放在最后面。
还有就是使用不当会导致性能问题,最大的问题就是内存消耗。如果制作过程不做任何的规划,随意摆放,则可能会使图片变得相当大,从而很占内存。
下面是一些最佳实践:
1、在项目后期应用css sprite技术
因为一般在开发过程中,会比较频繁的修改或者更换图片,如果这个时候使用sprite技术,就会增加很多开发成本。
2、合理组织“雪碧”图
如果要把所有的图片放在一张图上面,也会有不妥,维护方面也不会很方便。组织背景图主要按照模块和背景图的风格来划分。比如,作为展示的缩略图放在一起,评论、点赞、上下箭头等图标放在一起等。
3、控制“雪碧”图的尺寸和大小
因为大尺寸的图片会占用大量的内存,所以要控制在合理尺寸,推荐长宽相乘不超过2500,大小在200kb内
4、合理控制背景图单元间的距离及背景图位置
这个原则是为了防止在背景图比元素大小更小的时候,区域出现别的无关背景图
5、借助相关工具处理sprite
三、减少css的代码量
提高网站整体加载速度的一个重要手段,就是提高代码文件的网络传输速度。除了代码压缩,精简代码也是一种手段。
(1)定义简洁的css规则
合并相关规则,定义简洁的属性值
合并规则是指比如font-family、font-size、font-weight等等,可以合并为font。 简洁属性值,比如颜色值:color,#33AAFF可以简化为#3AF等。
(2)合并相同定义
网页中总会有一些模块有较高相似度,则可把同样的部分共用一次定义,不同的部分再单独定义。而且在css中,很多属性是可以继承的,则只需要在合适的地方定义一次即可。
(3)删除无效的定义
无效的定义,并不会影响页面功能显示,但会影响页面展示的性能,增加代码量的同时,也增加了浏览器解析代码的时间。无效的定义包括无效的规则及无效的样式属性,一般是开发过程中引入的,而从直观上无法判断,这情况,可以用工具,chrome自带的工具就可以查找css中的无效样式。。
其他css高性能实践
(1)避免使用@import
@import导入的新样式文件会阻止页面的并行下载,这样增加了文件的整体加载时间。
(2)避免使用IE浏览器独有样式:图片滤镜和css表达式
图片滤镜的使用会在图片加载时阻塞浏览器的加载和渲染,并会增加额外的内存开销。 Css表达式的作用是动态设置css属性,表达式不只是有兼容性问题,还有性能问题,例如浏览器大小改动、窗口改动时,会使得浏览器频繁计算,性能消耗极大。同样的效果可以用javascript来实现。
css3最佳实践
查看浏览器支持情况
在我们使用css3的过程中,问的最多的一个问题可能就是:兼容性如何?没办法,随着css的发展,它可以为我们之前遇到的很多不好解决的问题提供一个更好的方案,让我们忍不住去想能不能那样去做。PC端有饱受诟病的IE系列,到了移动端会好很多,但有些还是不太好。所以,查看浏览器支持情况几乎成了必备动作。 如果使用的特性仅仅是装饰点缀性的效果,不影响大局,则不需要考虑太多兼容问题,如果是出于设计要求,必须支持所有浏览器,则要特别的关注一下了。 开发者可以选择比如:caniuse.com、css3 Click Chart、css contents and browser compatibility这些在线工具来查看兼容性。
添加必要的浏览器前缀
对于刚使用css不久的朋友来说,如果偶尔在某网站源码当中看到诸如:“-webkit-、-moz-”等,可能会觉得很奇怪,这是什么?它们是对应不同的浏览器厂商所加上的前缀。
因为浏览器在支持css3时,可能仅仅实现了标准定义的一个早期版本,所以,尚不支持标准写法,给代码添加浏览器前缀也是无奈之举,会使得代码更多,更难维护。
但也不是为了“完美”而一定要去兼容所有的浏览器,一般可以按照浏览器或者系统的版本的市场占有率和目标用户使用浏览器的比例,来决定加不加前缀以及加几种前缀。而且相信随着逐步的发展,系统、浏览器的不断升级、更新,需要使用前缀的情况会减少。
问题又来了,既然需要添加必要的前缀,说明有些时候还是很有必要,那不得不加的情况下,那不是挺麻烦的?同样的一条规则要写三四遍,可能很多地方都要用,如何是好?别急,下面是几个对策:
1、使用工具来添加css属性的浏览器前缀
Prefixr,可以在开发的后期对代码进行处理。它会自动的添加需要的前缀和删去不必要的前缀。
Autoprefixer,如果想要在开发过程中更多的自主性,可以使用这个工具,开发者可以自定义浏览器支持范围,它也有多种使用方式,可以集成到多个开发环境中。 此外还有几种工具可供使用:cssFx、*css Agent*和-prefix-free。
2、借助css预处理技术
目前流行的有sass、less,具体方法是,针对css3样式特性定义一份模板样式。 优点是:避免大量重复代码,只需要维护一份定义。
3、不要过度添加浏览器前缀
有些开发者为了兼容所有浏览器,不管什么情况都为css代码加上了所有浏览器的前缀,这是一种消极的编码方式,增加了太多的重复代码,降低了浏览器的解析性能,增加了复杂度,同时某些前缀的属性可能没有被浏览器支持过。
4、添加css3标准属性定义
何为标准属性定义呢?就是不需要任何浏览器前缀,大家可能都会注意到,很多使用css3的地方都会在最后的地方写标准属性定义,为什么呢?因为当浏览器支持标准属性时,它可以覆盖前面添加了前缀的定义,css3中的属性标准定义才是符合规范的定义,添加了浏览器前缀的定义会随着浏览器的更新逐渐被淘汰。
当然,还有一点需要注意的是,某些属性,目前是属于Only webkit或者Only firefox的,那么就没有必要再写上标准定义及其他浏览器前缀了。
做好css3中新特性的兼容处理
说到兼容,就会提到低版本IE,比如很常见的圆角、透明图片等,有时候我们会给它们降级的处理,比如filter或者javascript,使用box-sizing、transform,推荐使用Modernizr,这个框架中包含了很多css3新特性的兼容方案。
无论是哪种方案,都会带来性能上的损耗,不能毫无章法的滥用,仍然是需要大家去权衡和选择。推荐一个如何更有效率的使用HTML5的建议网站:html5please。网站按照使用的方式把css3中的新特性分成了三类:
(1)直接使用
包含了大部分新特性,有些特性本身不会影响兼容性,如border-radius、media queries等,有些需要添加降级处理,如多背景图,要设置一个单背景图或者背景色作为备选。
(2)谨慎使用
这部分主要是性能问题,例如框阴影应用于占用很大区域的元素,页面滚动或鼠标悬停时,会引起不小性能问题。
(3)避免使用
这部分因为它们可能仅支持某个浏览器,比如倒影,则需要避免使用。
综上所述,css能够用来提高性能的方法还是蛮多的,但我们很容易忽略它们,因为它们所带来的影响似乎没有那么明显,而且,很多人可能为了图方便,任意挥洒着自己的才华,想怎么写就怎么写,能达到效果就行,这也有点小消极哈,忘了你的优秀工程师目标了麻?!~~css规则虽不不难,真正写好也不易,还是要有些追求极致的精神滴。诸君且写且珍惜吧!~
高维护性css
Css有些什么特点?
简单来说,使用方式:内联、内嵌、外联、import。为元素设置样式的方式:元素标签名、类名、id、各种选择器,以及它们的组合。所以,它是很灵活的,如果不做任何的规范的限制,就肯定会导致css代码的混乱和难以维护。
如何高效组织css代码?
结构清晰、模块分明,合理的代码组织结构可提高代码的重用性和可维护性,降低开发复杂度。那怎样组织呢?
首先是组织代码文件,可分为两大类:通用类和业务类。 然后,有一个文件用来重置,常见命名是reset或者default、normalize等。
有一个文件用来存放通用模块和一些基础样式,常命名为mod、common等,如页面对话框,提示框,头部,底部,侧边栏等,会在多个页面用到,这样方面各页面引用,提高代码复用度。
另外需要一个文件存在兼容旧版IE浏览器的样式,这样做的好处有二:
一、减少非IE浏览器加载样式文件的负担
二、如果未来决定不再支持旧版的IE浏览器,则只需要去修改一个文件,不需要多个文件到处找去修改。当然,在处理浏览器兼容问题上,有个原则是,是否有其他不存在兼容问题的方案,如果没有,则把要做兼容的部分单独放在一个文件中。
其余的css样式文件则用于业务模块,不同模块的样式文件放置于不同的文件夹中,原则上每个模块的样式文件不宜太大。
这样可能会造成一个问题,一个页面不是要引入很多文件了?页面加载的时候http请求不是多很多?其实并不矛盾,文件的划分只是为了方便开发和维护,发布的时候会使用工具把多个文件压缩合并成一个文件,所以不用担心引入多个文件的问题。
上面说的是文件的组织,那么在文件中也要按照一定规则来组织样式的声明。 比如,按照模块中元素的层级,如果是同级,则按照元素在页面中的位置,从上到下,或者从左到右,若存在多个元素共用相同声明,则应先声明共通样式。 如果觉得这样还不够,则可以使用一些更高级的方式,如less、sass,它们将css赋予了动态语言的特性,如变量、继承、运算、函数等。
以上是从几个大的方向去说的,下面涉及某几个点谈一谈
使用css reset 统一浏览器显示效果
首先,html的标签是有原始样式的,但问题是在不同浏览器中,标签的默认样式不尽相同,其中的某些差异给开发造成了麻烦,早在2004年,就有人开发了第一个重置样式文件,叫undohtml.Css,后续又有了多种重置方案,其中有个方案“火爆一时”,此方案总共就一行代码*{margin:0;padding:0;}。重置了所有标签默认的margin、padding样式,但有一个弊端是增加了后续开发的复杂度,并不能很有效的提高整体开发的效率。另外,此方案性能也不佳,当页面元素很多时就会影响页面渲染的性能。所以,人们还在逐渐的探索更好的重置方式,目前有多个流行的重置方案,有Eric Meyer开发的Reset CSS和雅虎公司前端技术团队开发的YUI Reset CSS。其实并不存在一种方案适合所有项目,所以最好还是选择参考别人的方案然后设计一套适合自己项目的方案。
需要考虑如下几点:
(1)HTML5新标签 需要重置它们的display样式,因为在低版本IE中没有定义它们的默认display样式。
(2)padding、margin、border 标签在浏览器中的差异主要是与这三个样式有关的默认样式产生的,但也不是需要重置全部元素的margin、padding、border,应根据实际情况。
(3)字体设置 <h1>~<h6>、<strong>、<em>等语义化标签都有默认字体,但实际当中所需要的字体大小或者粗细都跟默认不同,所以一般项目中都会对他们进行重置。
(4)其他元素的样式重置 典型的有li默认的列表项样式,table的单元格之间默认空间,a链接的下划线等。
给css定义排序
Css的逻辑性不强,随意的书写也不影响其作用,如果不借助工具对其排序也会很繁琐,所以,很少有人会在意,但是排序还是有好处的。
比如:
1、更整洁
2、防止重复定义
3、能够清晰查看定义
4、后续维护能快速定位
排序方式:
1、按类型 如,显示和浮动、定位、尺寸、字体等
2、按字母 按字母顺序排列,优点是规则简单
3、按定义长度 按照样式定义的字符长度排列
各有优劣,实际应用中,推荐使用第一种。 但是如果单靠前端工程师在编写过程中这么做的话也是很难的,可以在写的过程中按照效率最高的方式写,提交代码时使用工具为css排序。既提高效率,又方便后续代码阅读和维护。有一款免费工具是 CSScomb。
合理利用css的权重,提高代码重用性
何为权重,即css众多类型选择符的优先级,优先级高的样式会覆盖优先级低的样式。权重的更具体规则,大家可以查阅资料,这里不赘述。
这里说说如何依照选择符的权重定义合适的选择符:
(1)尽量不使用ID选择器
一个页面中不允许定义两个同样的ID,而且ID选择器权重很高,如果要覆盖使用了ID选择器的元素样式,就必须在其元素上添加新的选择符,或使用!important,这样的结果会使无法重用的样式代码变得更多。最佳实践是尽可能使用较低权重的选择符作为基础样式。
(2)减少子选择器的层级
也是降低子选择符整体权重的过程,同时,层级越少,对html结构的依赖就越低。引起Css层级过多的另外一个原因是sass、less等工具的滥用,这也是我本人在使用之初就有意识到的问题,因为你可以使用嵌套和引用等方式来定义样式了,这样以来给自己省了很多功夫,但文件最终还是要编译出来,我们不用反复的敲那么多代码了,但生成的代码依然还是会很多,所以,方便了自己的同时依然要特别注意减少选择器层级。
(3)使用组合的css类选择器
使用这种方式,开发者可以不用考虑css样式覆盖的问题,避开了计算选择符权重的过程,同时提高了代码的重用性,组合的概念是把一个复杂的父类中的可变部分和稳定部分分割开来,稳定部分作为主体类,可变部分分成几个简单的类,类与类之间没有继承,同样可以起到减少对html结构的依赖,提高代码重用性的作用。
如何兼容IE浏览器?
IE8及以下版本的IE浏览器一直是前端开发人员心中的痛。为了兼容它们做额外添加的代码成为hack代码,往往人们都不想去写那些代码。以下是兼容IE浏览器的一些实践方法。
(1)熟悉IE浏览器中常见的样式兼容问题
一类是浏览器本身的bug,一类是和标准不兼容或还不支持标准。
(2)分离样式兼容代码
按照浏览器的不同版本组织代码文件,然后使用判断语句,按需加载
em、px还是%?
谈及这个话题的原因是,如今页面功能变得越来越多,用来访问页面的设备越来越多,页面的布局就是一个颇具挑战的事情,而页面当中的元素的尺寸和字体、图片的大小等也跟布局息息相关。鉴于此,前端开发开始重视如何提高页面布局,核心思想是将页面元素的尺寸和字体大小设置为相对值。字体相对单位包括:em、ex、ch、rem。更多内容无需赘述,有更多的资料来讲解。下面给出几个最佳实践:
(1)尽量设置相对尺寸
所谓设置相对尺寸,并不是说页面整体的布局是自适应的,整体的尺寸可以是固定尺寸也可以是自适应的尺寸,这取决于页面的设计。
(2)只有在可预知元素尺寸的情况下才使用绝对尺寸
比如设计上要求使用绝对宽度,比如整体宽度,侧边栏宽度,页头页尾的高度固定等,在展示图片、视频的时候,合适的固定尺寸会让这些多媒体元素展示获得最佳的效果。
(3)使用em设置字体大小
使用px设置字体大小的可扩展性不好,使用百分比设置字体大小也不符合习惯,最佳方式是使用em设置字体大小,但随着字体设置的层级增多,这种方式反而增加了维护的成本,对于此,css3引入了rem单位,是相对于根元素的字体大小计算的,就避免了这个问题,目前除了IE8及以下,大部分浏览器都支持它。
此文很多东西都是点到为止,希望对一些新手来说有一定的引导作用,带来一定的帮助。每个人在自己逐步的实践当中都会有一些这样那样的感触和经验、教训等,经常的总结和放入到自己的下一步实践当中,相信是会很有好处的。大家一起加油!~