高质量的CSS
应用CSS的能力应该分成两个部分:一部分是CSS的API,重点是如何用CSS控制页面内的元素的样式;另一部分是CSS框架,重点是如何对CSS进行组织。
组织CSS
1、组织划分
1)、对CSS的组织见仁见智,可以按功能划分:将控制字体的CSS集中在font.css文件里,将控制颜色的CSS集中的在color.css文件里,将控制布局的CSS放在layout.css文件里。
2)、按区块划分:将头部的CSS放在head.css里,底部放在font.css里,侧边栏放在sidebar.css里,主体放在main.css里。
3)、按职能划分,base.css+common.css+page.css。将网站内的所有样式,按照职能分成base,common,page。任何一个网页的最终表现都是由这三者共同完成,这三者不是并列结构,是层叠结构。
2、base层
这一层位于三者的最底层,提供CSS reset功能和粒度最小的通用类—原子类。这一层会被所有页面引用,是页面样式所需依赖的最底层。这一层与UI设计师无关,无论何种风格的设计都可以应用它,所以base层要力求精简和通用。如果将用CSS控制页面样式比喻建房子,这一层的核心职能就是为房子打好地基(CSS reset),并将建房用的砖块(原子类)准备充足。因为所有的房子都要打地基,也都需要砖块,所以base层具有高度可移植性,不同的设计风格的网站都可以使用同一个base层。因为这一层的内容很少。所以可以简单的放在一个文件里,例如base.css。base层相对稳定,基本上不需要维护
3、common层
这一层位于中间,提供组件极的CSS类。提到组件,就让人想起模块化,”模块化”可以从样式和行为两个层面来考虑,与common层相关的样式的模块化。我们可以讲页面内的元素拆分成一小块一小块功能和样式相对独立的“模块”,这些“模块”有些是很少重复的,有些会大量重复,我们可以将大量重复的“模块”视为一个组件,我们从页面里尽可能提取出来,放在common层里,common层就相当于MVC模式中M(Model,模型)。为了保证重用性和灵活性,M需要尽可能将内部实现封装,对可能会经常变化的部分提供灵活的接口,
Common层就像建房时用到的门窗,小元件,比如玻璃,门板,钥匙孔,门窗可以整体移动、增减,但门窗本身的构造是相对稳定的。房子的门窗就好比这个网站选用的UI组件。门窗最好与整个房子的保持一致,同样,网站最好让UI组件的风格保持相同,UI组件是网站中的单位,在网站内部可以高度重用,但不同的网站可能会有不同的UI组件,所以common是网站级,不同的网站有不同的common层,同一个网站只有一个common层,但是网站规模很大也可以进行拆分,common_form.css,common_imageList.css,common层最好一个负责,统一管理。
第一个技巧:模块与模块之间尽量不要包含想听的部分,如果有相同的部分,应将它们提取出来,拆分成一个独立的模块
第二个技巧:模块应在保证数量尽可能少的原则下,做到尽可能简单,以提高重用性。
4、page层
网站高度重用的模块,我们把她们视为组件,放在common层;非高度重用的模块,可以把它们放在page层,page层位于最高层,提供页面级的样式。同样,page层就好比是房间内的装饰画,不同的房间张贴的装饰画各不相同,它不像砖块,所有的房子都相同,也不像门窗,同一个房间里都相同,它对重用性没有要求,可根据各个房间布置的需要任意张贴,这个page层也可以分离出来,page1.css,page2.css,page3.css。但可能会产生大量的css文件,有些page的css非常小,带来维护上的麻烦,如果网站不够大,建议把page层的代码放在一个page.css文件里,根据页面配上注释,分块书写,便于维护..
5、总结:base层基本上不需要维护,common层修改的幅度不会很大,通常一个人负责维护,到Page层,代码可能由很多人开发,如何避免冲突是个需要注意的问题,通常我们通过命名规则来避免冲突。
CSS的命名
CSS的命名推荐使用英语,不要使用汉语拼音。头部用head,底部用foot,主体用main,导航用nav,菜单用menu,如果程序员非要用拼音也不是不行,但为了方便阅读和理解,提高可维护性,我推荐用这样的命名方式,也为了我们的英语能够得到提高,扩大词汇量,可以阅读国际的一手资料。
当一个容器需要两个单词来表达,比如一个关于时间的无序列表取名为timelist,time和list,但他们连在一起,很难一眼认出来,可读性不好,如果命名需要用到两个或两个以上的单词,通常做法,两种
、骆驼命名法,例如,timeList,dropMenu,subNavMenu
、划线命名法
、中划线,例如drop-menu、sub-nav-menu
、下划线,例如drop_menu、sub_nav_menu
、推荐,两种方式组合
骆驼命名法用于区别不同单词,划线用于表明从属关系,比如一个列表,ul的名字是timeList,然后这个列表的最后一个是不同于其他的样式,比如下划线不需要,那么有些人用timeList:last伪类实现,但是如果存在浏览器的兼容,不兼容伪类的时候,那么我们就可以在最后li给他一个.last,那么.last是个过于简单且常用的命名,编写代码要时刻保持“团队合作”意识,将冲突降到最低,如果工程师A过于依赖子选择符,那么使CSS中大量存在,.timeList .last,.nameList .last,.ageList .last等选择符的层叠,产生意料之外的影响,除了.list,还有.first,.item等,为了将风险降到最低,我们最后一个用.timeListLastItem,为了表示从属关系,可以改进为.timeList-lastItem,这样写就能够表示这个lastItem是timeList列表下面的最后一列,这样可以进一步提高CSS命名的可读性,不仅可以从命名中清楚看出各个单词,还能了解到从属关系,很明显.timeList-lastItem是timeList下面的lastItem。既然划线用于表明从属关系,那么不推荐.timeListLastItem或者.tiem-list-first-item这些方式。
、common层由一个人负责,那么只需要考虑page层发生冲突的问题,解决page层发生冲突的问题加前缀。比如工程师A有一个时间列表.timeList,工程师B也有一个时间列表,也取名为.timeList,工程师A没有注意到工程师B的代码,就导致代码的冲突那么在写page层的时候,比如吴贞囡,wzn-timeList,密迎明写成mym-timeList那么各自的page层都加上自己的前缀,加了唯一前缀之后,工程师A和工程B都可以专心于自己负责的代码,不用担心冲突问题。这个引申出来的一个问题就是命名可能比较长,比如nav-item-select,wzn-timeList-lastItem-img,这个命名长,但是可以带来很好的可读性,可以避免多人合作的冲突,就算会增加Page层的代码量,但权衡两者,长命名影响的只是css纯文件,比起IMG,flash,等并不是很大,这个带来的坏处在可接受范围内,好处就很明显
、总结,用Java的面向对象来解释,base,common相当于public公有属性,page相当于private私有属性。
挂多个class还是新建一个class—多用组合,少用继承
方案一:
<style>
.numberList1{ border:1px solid #ccc; padding:10px; }
.numberList1 li{ height:20px; line-height:20px; font-size:12px; }
.numberList2{ border:1px solid #ccc; padding:10px; }
.numberList2 li{ height:20px; line-height:20px; font-size:16px; }
.numberList3{ border:1px solid #ccc; padding:10px; }
.numberList3 li{ height:20px; line-height:20px; font-size:12px; color:red; }
</style>
<body>
<ul class=”numberList1”>
<li>111111111</li>
<li>222222222</li>
<li>333333333</li>
</ul>
<ul class=”numberList2”>
<li>444444444</li>
<li>555555555</li>
<li>666666666</li>
</ul>
<ul class=”numberList3”>
<li>77777777</li>
<li>88888888</li>
<li>99999999</li>
</ul>
</body>
方案一实现了想要的结果,但是它非常冗余“.numberList1”,“.numberList2”,“.numberList3”的CSS设置相同,“.numberList1 li”,“.numberList2 li”,“.numberList3 li”有一部分CSS一致,我们对它进行改进
方案二
<style>
.numberList1,.numberList2,.numberList3{ border:1px solid #ccc; padding:10px; }
.numberLsit1 li,.numberList2 li,.numberList3 li{ height:20px; line-height:20px; font-size:12px;}
.numberList2 li{ font-size:16px; }
.numberList3 li{ color:red; }
</style>
<body>
<ul class=”numberList1”>
<li>111111111</li>
<li>222222222</li>
<li>333333333</li>
</ul>
<ul class=”numberList2”>
<li>444444444</li>
<li>555555555</li>
<li>666666666</li>
</ul>
<ul class=”numberList3”>
<li>77777777</li>
<li>88888888</li>
<li>99999999</li>
</ul>
</body>
方案二,还有另外一种思路,方案三
<style>
.font12{ font-size:12px; }
.font16{ font-size:16px; }
.cred{ color:red; }
.numberList{ border:1px solid #ccc; padding:10px;}
.numberList li{ heighr:20px; line-height:20px; }
</style>
<body>
<ul class=”numberList font12”>
<li>111111111</li>
<li>222222222</li>
<li>333333333</li>
</ul>
<ul class=”numberList font16”>
<li>444444444</li>
<li>555555555</li>
<li>666666666</li>
</ul>
<ul class=”numberList font12 cred”>
<li>77777777</li>
<li>88888888</li>
<li>99999999</li>
</ul>
</body>
总结:方案一将图中的三个模块视为完全不同的模块,彼此独立,分别是.numberList1,numberList2,.numberList3,并对他们设置了样式,缺点是代码冗余,方案二跟方案一的思路相同,仍将三个模块视为独立的个体,只是使用css技巧将三个类提取出来,去除代码的冗余,方案三换了一种思路,提取更小的粒度更小的类,通过类的组合实现设计
从这里看,方案二的调用简单,一个模块只要挂一个类,方案三调用稍麻烦,但也有效的控制了冗余,代码精简,看起来,方案二,方案三都不错,但是我现在,要三个ul种再加一个ul,字体16,红色,边框,边距同上
<style>
.numberList1,.numberList2,.numberList3.numberList4{ border:1px solid #ccc; padding:10px; }
.numberLsit1 li,.numberList2 li,.numberList3 li,.numberList4 li{ height:20px; line-height:20px; font-size:12px;}
.numberList2 li,.numberList4 li{ font-size:16px; }
.numberList3 li,.numberList4 li{ color:red; }
</style>
<body>
<ul class=”numberList1”>
<li>111111111</li>
<li>222222222</li>
<li>333333333</li>
</ul>
<ul class=”numberList2”>
<li>444444444</li>
<li>555555555</li>
<li>666666666</li>
</ul>
<ul class=”numberList3”>
<li>77777777</li>
<li>88888888</li>
<li>99999999</li>
</ul>
<ul class=”numberList4”>
<li>77777777</li>
<li>88888888</li>
<li>99999999</li>
</ul>
</body>
按照方案三的思路
<style>
.font12{ font-size:12px; }
.font16{ font-size:16px; }
.cred{ color:red; }
.numberList{ border:1px solid #ccc; padding:10px;}
.numberList li{ heighr:20px; line-height:20px; }
</style>
<body>
<ul class=”numberList font12”>
<li>111111111</li>
<li>222222222</li>
<li>333333333</li>
</ul>
<ul class=”numberList font16”>
<li>444444444</li>
<li>555555555</li>
<li>666666666</li>
</ul>
<ul class=”numberList font12 cred”>
<li>77777777</li>
<li>88888888</li>
<li>99999999</li>
</ul>
<ul class=”numberList font16 cred”>
<li>77777777</li>
<li>88888888</li>
<li>99999999</li>
</ul>
</body>
按照方案三的思路,我们无需扩展新的类,只需在html标签的class里将之前定义的类重新组合就好了
多用组合,少用继承(面向对象编程中,一个很重要的原则)
因为前面有java的菜鸟基础,在面向对象编程里,也有类似的情况,继承与组合,继承是将一个复杂且包含变化的类,拆分成几个复杂但稳定的自雷,首先明确一个抽象的父类,父类有这几乎所有的方法和属性,子类继承父类,根据需求,添加新的方法和属性,覆盖掉与父类有变化的方法和属性,但使用继承的话,任何一个小的变化都需要重新定义一个类,很容易引起类的爆炸式增长,产生一大堆细微不同的自雷,
组合的思路是将一个复杂的类分成容易产生变化和相对稳定的部分拆分出去,每一种可能的变化设计成一个个单独的类,这样,讲一个复杂的类拆分成了几个简单的类,类之间没有继承关系,这遵循了面向对象的“单一原则”,这写容易变化的类,实现了类的组合,用组合的方式,可以大大减少类的数量
方案三借鉴了编程领域类的组合的思想,如果能灵活运用这点可以大大的减少类的数量,一方面减少代码量,一方面提高了可维护性,另一方面使类的职责单一,弹性更强,增加了类的重用性,提高了开发效率。
挂多个class会不会让HTML标签看起来臃肿
这样做固然不好看,但它带来的好处是不容忽视的,挂多个class,html标签看起来不太轻盈,yahoo的前端开发,阿里的前端开发,携程的前端开发也喜欢挂多个class的方式
低权重原则—避免滥用子选择器(选择符:标签,class,id)
1、
<style>
span { font-size:40px; }
.test{ color:red; }
</style>
<span class=”test”>123456789</span>
123456789既可以得到”font-size:40px”的样式,又可以得到color:red的样式,如果两个不同的选择符设置的样式有冲突,又会如何
<style>
span { font-size:40px; color:green; }
.test{ color:red; }
</style>
<span class=”test”>123456789</span>
123456789的颜色会是什么呢?是对”span”设置成绿色的还是红色的,这就涉及到CSS选择符的权重问题了。
CSS的选择符是有权重的,当不同选择符的样式设置有冲突时,会采用权重高的选择符设置的样式,html标签的权重是1,class的权重是10,id的权重是100
所以得出,span的权重是1,”.test”的权重是10,所以“123456789”的颜色是红色
2、
<style>
span { font-size:40px; }
.test1{ color:red; }
.test2{ color:green; }
</style>
<span class=”test2 test1”>123456789</span>
span标签同时挂了test1,test2两个class,它们的权重都是10,那么123456789的权重又是哪个呢?
如果css选择符权重相同,那么样式遵循就近原则,哪个选择符最后定义,就采用哪个选择符的样式,那么此处为绿色,这个挂class的先后顺序没有关系,text1 test2和test2 test1没有区别
CSS权重是个很容易疏忽的问题,但事实上如果不太注意选择符权重,常会出现意想不到的麻烦
3、
现在需要将“很重要”三个字设置为红色,我们应该怎么做?
方案一:
<style>
#test{ font-size:14px; }
#test span{ color:red; }
</style>
<p id=”test”>css选择符权重<span>很重要</span></p>
方案二:
<style>
#test{ font-size:14px; }
.font{ color:red; }
</style>
<p id=”test”>css选择符权重<span class=”font”>很重要</span></p>
很多工程师推荐使用方案一,因为使用子选择器避免新增class,让html代码更简洁,这么考虑是有道理的,但如果现在有变化了,需要添加新的文字进来
<style>
#test{ font-size:14px; }
#test span{ color:red; }
</style>
<p id=”test”>css选择符权重<span>很重要</span>,我们要小心处理</p>
要求我们将“小心处理”这几个字设置为绿色,我们可以这么做,
<style>
#test{ font-size:14px; }
#test span{ color:red; }
.font{ color:green; }
</style>
<p id=”test”>css选择符权重<span>很重要</span>,我们要<span class=”font”>小心处理</span></p>
本以为小心处理会变成绿色,但它却被选择符权重更高的,#test span设置成了红色,子选择器无意中影响到了我们新添加的代码,如果想达到预期
<style>
#test{ font-size:14px; }
#test span{ color:red; } //100+1=101
#test .font{ color:green; } //100+10=110
</style>
<p id=”test”>css选择符权重<span>很重要</span>,我们要<span class=”font”>小心处理</span></p>
而使用方案二,会如何
<style>
#test{ font-size:14px; }
.font1{ color:red; }
.font2{ color:green; }
</style>
<p id=”test”>css选择符权重<span class=”font1”>很重要</span>,我们要<span class=”font2”>小心处理</span></p>
我们新挂上class,就可以顺利的完成样式设置
为了保证样式容易被覆盖,提高可维护性,CSS选择符需保证尽可能低。
少使用子选择器,就需要多添加class,在web盛行的初期(前几年),很多工程师认为多添加class是不好的,如果能使用子选择器就应尽量使用,使用大量的class叫做”多class症”,在经过大量实践后,我不认为多class会有太大坏处,相反,与使用子选择器相比,新增class反而更有利于维护
CSS编码风格
多行式还是一行式
.test{
width:100px;
height:50px;
color:#ccc;
}
.demo{
background-color:green;
font-size:20px;
}
.test{width:100px; height:50px; color:#ccc;}
.demo{background-color:green;font-size:20px;}
、多行式的编码风格可读性强,缺点是容易css文件行数过多,编辑样式时,需要来回拖动文本编辑器的滚动条,影响开发速度
、过多的空白,增大CSS文件的大小
、一行式的编码风格在可读性方面稍差一点,但可以有效减小CSS文件的行数,有利于提高开发速度,同时也可以减小CSS文件的大小
、随着前端调试工具的强大,比如火狐,谷歌自带的样式检测工具,已经不需要仔细阅读CSS文件了,一行式编码风格逐步取代多行式的编码风格,成为主流,推荐一行式
2、同一个网页,相同的id只能出现一次,不可重复,class可以任意出现多次,id权重是100,class权重是10,js原生提供getElementById,不提供getElenmentByClass,id不能重用,使用id会限制网页的发展,比如,设计某个模块只出现过一次,我们使用id,没问题,但需求变了,同样的模块再增加一个,问题就出现了,因为使用Id,不能重用,所以,一般情况下,尽量使用class,少用id
后期hack
解决超链接访问候hover样式不出现的问题
块级元素和行内元素的区别
display:inline-block经典3px
relative,absolute,float区别
居中,垂直,任意居中,任意垂直的写法