网易邮箱的CSS开发(一)
网易邮箱是个庞大而且细节繁多的系统,注定了前端开发中样式管理的复杂程度非常高。如果没有一个合理的体系来管理样式,开发和维护的难度是不可想象的。从极速3.5版本开始,我们就一直遵循并不断改善这套规则,现在就来分享一下~
开发思想
在错综复杂的样式面前,CSS显得过于简陋。于是我们不得不人为的加上一些思维方式和规则来帮助我们管理样式。
我们借鉴了“面向对象”中的“封装”和“继承”来开发CSS,使我们能很大程度上重用CSS代码的同时又不至于在修改CSS代码时因为过度重用而难以下手。
每个页面都由很多元素(除非特别指出,本文的“元素”都不是指 这样的HTML元素)组成,元素可以大到整个界面框架,也可以小到一个图标。元素相互嵌套、组合,形成了最终的页面。
对于任意元素,我们建立这样一种模型:
1、所有的元素内部都可以嵌套其他元素;
如:“a”里可以嵌套“a的头”、“b”等。
2、元素内部的元素中,有的是“私有的”,只能在这个元素内使用,其样式也不会受父元素之外的CSS规则影响,有的是“公有的”,可以出现在任何位置;
如:“a的头”、“a的身体”是“a”的私有元素,“a的身体的某部分”是“a的身体”的私有元素,而“b”是公有元素,被“a”调用,“a”可以修改其内部的“b”的样式,但不能修改其他“b”的样式。
3、元素根据需要可以具备多种状态,可以给这个元素一个“参数”让它呈现不同状态;
如:设一个hasBorder=“true”可以让“a”有边框,设一个size=“big”可以让”a的身体的某部分”变大
4、可以从一类元素派生出另一类元素
如:我们需要和“a”类似的元素,但是需要对其进行扩展,这时我们新建一类“a2”元素,“a2”继承了“a”的所有样式和“私有元素”和“参数”
开发时,元素就像“类”一样被定义在CSS中,元素的“私有元素”、“参数”等也都定义在这个“类”中。
CSS类定义:
/* a类 =================================*/ /* a类的定义 */ .a {...} /* a类的私有元素 */ .a的头{...} .a的身体{...} .a的身体的某部分{...} /* a类的参数 */ .a(hasBorder时){...} .a(size为big时){...} HTML中的a类元素的两个“实例”: <div class="a" id="a1"> <div class="a的头"></div> </div> <div class="a" id="a2"> <div class="a的头"></div> <div class="a的身体"></div> <div class="b"></div> </div>
命名和编码规则
以上所说的模型并不是CSS与生俱来的,所以需要一些命名和编码规则来加以实现,不过这个并不复杂。
1、我们使用连字符“-”从逻辑上划分class名,使用驼峰式命名区分单词;
如:.a-b-helloWorld
2、有时我们会给class加上一个命名空间前缀,命名空间与class之间也用连字符“-”连接;
如:.WB3-a-b-helloWorld,在极速4中,WB3命名空间下的class名将被压缩成1~3个字母短名称。(注:WB3是网易邮箱前端吊丝们给极速4起的开发代号……三楼水吧WaterBar3,碉堡了-。-……)
3、“私有元素”必须以父元素的class名作为前缀;
如:“a的身体的某部分”的名称是j,而它的父元素“a的身体”的名称是bd,“a”的名称是a,那么最后连起来的class就是.a-bd-j。
/* a类定义 =================================*/ .a{...} .a-bd-j{...} /* 允许在a类中定义a类的私有元素 */ /* b类定义 =================================*/ .b{...} .a-bd-j{...} /* 不允许在a类外定义a类的私有元素 */
4、“参数”依然使用class实现,以能表达“是否”或具体取值的方式命名:
如:.hasIcon表达有图标,.hasBorder表达有边框,.sizeBig表达大尺寸的,.sizeSmall表达小尺寸的
***这里是一个理想状态(无IE6)下的命名方案,假设元素a提供以上状态,我们可以这样实现:
.a.hasIcon{...} .a.sizeBig{...} ...
为了IE6,我们不得不用这样的命名来兼容:
.a-hasIcon{...} .a-sizeBig{...} ...
5、从一类派生出另一类元素,命名上没有特别的要求,通过在HTML中的class同时写上基类和子类的class来实现;
/* 基类定义 =================================*/ .superclass{...} .superclass-element{...} /* 子类定义,扩展、重写基类定义 =================================*/ .myClass{...} .myClass-element{...} .myClass .superclass-element{...}