说在前头
关于网易NEC,(想瞧一瞧请点击这里)我最早听说是在三个月前;是一位三年多工作经验的前端大牛,推荐的;然后自己看了一下觉得非常不错。也就在公司项目中使用了,并逐渐喜欢了这种风格。现在,差不多用了三个多月;今天呢,再次拜读了新浪前端大牛--曹刘阳的《编写高质量代码--Web前端开发修炼之道》(想下载请点击这里),这本书是10年出来的,里面关于css样式文件如何分类,整理;样式如何命名,如何写出简洁,高效,可复用的css的见解,很多都能在NEC中找到影子;很多地方都不谋而合。所以呢,我就再次拾人牙慧,说说自己的使用心得。
正题,正题,正题
首先呢,将css文件分为3类
公共型样式:主要包括了以下2个部分:
“标签的重置reset和设置默认值(主要是为了消除标签的默认样式在各个浏览器中的差异)”
“统一调用背景图,清除浮动”、“网站通用布局”、“通用模块和其扩展”、“元件和其扩展(按钮,输入框等)”、“功能类样式(诸如display,浮动,字体大小,样式等)”、“皮肤类样式”。这部分主要是一方面提供了决定网站的整体布局和网站基本控件的样式皮肤风格,同时提供了布局中常用的功能性样式。
特殊型样式:当某个栏目或页面的样式与网站整体差异较大或者维护率较高时,可以独立引用一个样式:“特殊的布局、模块和元件及扩展”、“特殊的功能、颜色和背景”,也可以是某个大型控件或模块的独立样式。这部分主要是页面具体模块,具体业务相关的差异性css。
皮肤型样式:如果产品需要换肤功能,那么我们需要将颜色、背景等抽离出来放在这里。主要是为了为网站更换风格提供拓展。
上面NEC关于样式的分类,不仅让我想起《编写高质量代码--Web前端开发修炼之道》中作者提到的建议整站的css分为base.css(提供css重置,默认和功能性的边距,定位,宽度文字排版等等);common.css(元件,UI组件等高度复用的css),page.css(具体模块的页面级相关样式);是不是很像?接着往下说。
上面说的是css文件的分类,那么css具体的内容该如何分类呢?
NEC中将其分为8类;并对各个类型的命名做出了相关建议。
重置(reset)和默认(base)(tags)
上面说了,这部分主要是消除默认样式和浏览器差异,同时,设置部分标签的初始样式(这个根据具体情况而定)。总而言之,保证整站在常见浏览器上的一致性,以及初始化标签的样式。
统一处理
建议在这个位置统一调用背景图(这里指多个布局或模块或元件共用的图)和清除浮动(这里指通用性较高的布局、模块、元件内的清除)等统一设置处理的样式!
布局(grid)(.g-)
Grid顾名思义就是讲页面进行结构上的分割,一般分为头部、主体、主栏、侧栏、尾部等等!
模块(module)(.m-)
这个一般是一个语义化的可以重复使用的较大的整体!比如导航、登录、评论、搜索等根据业务和功能分类后的独立个体!
元件(unit)(.u-)
通常是一个不可再分的较为小巧的个体,经常被重复用于各种模块之间的通用的小控件等!比如常见的按钮、输入框、loading、图标,label等!
功能(function)(.f-)
这部分主要指常用的定位,浮动,margin,padding宽度,字体样式等一些常用样式,将这些使用率较高的样式剥离出来,按需使用,通常这些选择器具有固定样式表现。
皮肤(skin)(.s-)
如果你需要把皮肤型的样式抽离出来,通常为文字色、背景色(图)、边框色等,非换肤型网站通常只提取文字色!非换肤型网站不可滥用此类!
状态(.z-)
为状态类样式加入前缀,统一标识,方便识别,她只能组合使用或作为后代出现,比如:.u-ipt.z-dis{},.m-list li.z-sel{},.m-listli.z-active{}等表示选中,禁用,激活等状态。
关于CSS命名NEC也提出来几点建议。
1.选择器使用(建议使用类选择器,避免使用id)
首先要说的就是ID;我们知道Id在页面中是唯一的,不可重复了;这也就决定了一旦使用id选择器,意味着,下面的样式就无法重用了;也就违背了nec的初衷;而,类选择器则是不唯一的,自然可以实现复用。
2.分类的命名方法:使用单个字母+"-"为前缀
这个上面关于css内容分类,已经给出来相关的命名规范,不多说。
3.后代选择器命名
约定不以单个字母+"-"为前缀且长度大于等于2的类选择器为后代选择器,如:.item为m-list模块里的每一个项,.text为m-list模块里的文本部分:.m-list .item{}.m-list.text{}。
一个语义化的标签也可以是后代选择器,比如:.m-listli{}。
不允许单个字母的类选择器出现
通过使用后代选择器的方法,你不需要考虑他的命名是否已被使用,因为他只在当前模块或元件中生效,同样的样式名可以在不同的模块或元件中重复使用,互不干扰;在多人协作或者分模块协作的时候效果尤为明显!
后代选择器不需要完整表现结构树层级,尽量能短则短。
注:后代选择器不要在页面布局中使用,因为污染的可能性较大;
命名应简约而不失语义
相同语义的不同类命名
方法:直接加数字或字母区分即可(如:.m-list、.m-list2、.m-list3等,都是列表模块,但是是完全不一样的模块)。
其他举例:.f-fw0、.f-fw1、.s-fc0、.s-fc1、.m-logo2、.m-logo3、u-btn、u-btn2等等。
模块和元件的扩展类的命名方法
当A、B、C、...它们类型相同且外形相似区别不大,那么就以它们中出现率最高的做成基类,其他做成基类的扩展。
方法:+“-”+数字或字母(如:.m-list的扩展类为.m-list-1、.m-list-2等)。
补充:基类自身可以独立使用(如:class="m-list"即可),扩展类必须基于基类使用(如:class="m-list m-list-2")。
如果你的扩展类是表示不同状态,那么你可以这样命名:u-btn-dis,u-btn-hov,m-box-sel,m-box-hov等等,然后像这样使用:class="u-btnu-btn-dis"。
如果你的网站可以不兼容IE6等浏览器,那么你标识状态的方法也可以采取独立状态分类(.z-)方法:.u-btn.z-dis,.m-box.z-sel,然后像这样使用:class="u-btnz-dis"。
模块和元件的后代选择器的扩展类
有时候模块内会有些类似的东西,如果你没有把它们做成元件和扩展,那么也可以使用后代选择器和扩展。
后代选择器:.m-login.btn{}。
后代选择器扩展:.m-login.btn-1{},.m-login .btn-dis{}。
同样也可以采取独立状态分类(.z-)方法:.m-login.btn.z-dis{},然后像这样使用:class="btnz-dis"。
注:此方法用于类选择器,直接使用标签做为选择器的则不需要使用此命名方法。
注:为防止后代选择器的扩展类和大类命名规范冲突,后代选择器不允许使用单个字母。
比如:.m-list.a{}是不允许的,因为当这个.a需要扩展的时候就会变成.a-bb,这样就和大类的命名规范冲突。
分组选择器有时可以代替扩展方法
有时候虽然两个同类型的模块很相似,但是你希望他们之间不要有依赖关系,也就是说你不希望使用扩展的方法,那么你可以通过合并选择器来设置共性的样式。
使用本方法的前提是:相同类型、功能和外观都相似,写在同一片代码区域方便维护。
防止污染和被污染
这一点是最让人烦躁和无语的,有些时候命名不注意,名字或者选择器使用不当出现改了一个地方其他地方样式错乱;或者被污染,自己不得不加强选择符的权重覆盖样式。当模块或元件之间互相嵌套,且使用了相同的标签选择器或其他后代选择器,那么里面的选择器就会被外面相同的选择器所影响。
所以,如果你的模块或元件可能嵌套或被嵌套于其他模块或元件,那么要慎用标签选择器,必要时采用类选择器,并注意命名方式,可以采用.m-layer.layerxxx、.m-list2 .list2xxx的形式来降低后代选择器的污染性。
说在最后
最后呢,觉得NEC关于css规范的建议和划分,非常合理和实用;可以解决如何组织整站css,如何写出简洁规范,高度复用,可维护的css等问题。目前,我们的项目中都是采用这个写法。而且,我们还引入了less;这样在上面这些规范的引导下使用LESS书写css更加高效和方便。