CSS知识总结之设计模式(持续学习中)

OOCSS

参考:http://coding.smashingmagazine.com/2011/12/12/an-introduction-to-object-oriented-css-oocss    作者:Louis Lazaris

oocss是Nicole Sullivan在Web Directions North中第一次提出,它代表了一种快、可维护、基于标准的CSS写法。

全称object-oriented-css,面向对象的CSS。既然是面向对象,那什么是OOCSS中的对象呢?OOCSS中所说的对象是一种可复用的视觉模型。OOCSS讲究复用,并快速高效的书写样式,且在日后便于修改、添加和维护。

OOCSS基本原则

1.结构与样式分离

代码示例:

使用OOCSS前:

#button {

    width: 200px;

    height: 50px;

    padding: 10px;

    border: 1px solid #ccc;

    background: linear-gradient(#ccc, #222);

    box-shadow: rgba(0, 0, 0, .5) 2px 2px 5px;

}

#box {

    width: 400px;

    overflow: hidden;

    border: solid 1px #ccc;

    background: linear-gradient(#ccc, #222);

    box-shadow: rgba(0, 0, 0, .5) 2px 2px 5px;

}

使用OOCSS后:

.button {

    width: 200px;

    height: 50px;

}

.box {

    width: 400px;

    overflow: hidden;

}

.skin {

    border: solid 1px #ccc;

    background: linear-gradient(#ccc, #222);

    box-shadow: rgba(0, 0, 0, .5) 2px 2px 5px;

}

前一种普通的CSS,用了id选择器,并且所有特性都独立存在每个元素中。后一种使用了OOCSS,通过class选择器,并且把公共的样式提取到一个名为skin的class中,复用到每个元素上。显而易见,代码量减小了,达到了重用的效果,如果需要修改box和button在页面中的表现,也只需要维护skin中的样式代码。代价仅仅多了一个class。

2.容器与内容分离

示例代码:

#sidebar h3 {

  font-family: Arial, Helvetica, sans-serif;

  font-size: 2em;

  line-height:;

  color: #777;

  text-shadow: rgba(0, 0, 0, .3) 3px 3px 6px;

}

/* other styles here.... */

#footer h3 {

  font-family: Arial, Helvetica, sans-serif;

  font-size: 1.5em;

  line-height:;

  color: #777;

  text-shadow: rgba(0, 0, 0, .3) 2px 2px 4px;

}

在这个例子中,后代选择器始终依赖于一个特定的容器(甚至是id选择器),根本无法复用。当我们基于OOCSS建立模块类,确保某些样式不依赖于外部容器,那我们的样式类就能够在任何地方复用。比如:

.h3-base {

font-family: Arial, Helvetica, sans-serif;

  font-size: 1.5em;

  line-height:;

  color: #777;

  text-shadow: rgba(0, 0, 0, .3) 3px 3px 6px;

}

#sidebar .h3-base {  // 像这样不想多加class的话,外部也来在所难免,看个人斟酌

  font-size: 2em;

}

#footer .h3-base {

  text-shadow: rgba(0, 0, 0, .3) 2px 2px 4px;

}

我们将项目中基本的h3的特性剥离出来,放在一个名为h3-base的类里,在不同的情况(#sidebar和#footer)下,覆盖各自特有的特性。来让常用样式得以在任何地方复用。

下面这个例子更加清楚的说明了这一原则:

.header-inside {

  * width: 980px;

  height: 260px;

  padding: 20px;

  * margin: 0 auto;

  * position: relative; (使内部有定位的元素,根据这个容器来定位)

  * overflow: hidden;(创建BFC,块级格式化上下文, 清除浮动)

}

如果是在一个宽度为980px,页面内容始终居中的网站中,header-inside中有很多带 * 符号代码的样式完全可以抽出来以备复用(用于宽度980px,居中,绝对独立的容器)。

.globalwidth {    //这里主要是外部容器的通用样式

  width: 980px;

  margin: 0 auto;

  position: relative;

  overflow: hidden;

} 

.header-inside {  //这里可以看做影响内部内容的样式

  padding: 20px;

  height: 260px;

}

相信globarwidth这个类名,可以在上面提到的应用场景中充分被复用。只需要加一个globarwidth class就能搞定一个外层容器。

学习进阶文章:

http://www.w3cplus.com/css/facebook-status-message-design-with-css  CSS制作Facebook的媒体对象

http://www.w3cplus.com/css/oocss-core  OOCSS——核心篇

关于OOCSS个人总结:OOCSS是一种思想概念,重点在于:减少对html的依赖,增加样式的复用性。将样式抽象模块化,增加样式的复用性,它减小了CSS样式表的大小,额外增加了class标记,让html文件更大了。虽然如此,但小小的标记结构的牺牲换来了样式表现性能的提升(样式表是能够被浏览器缓存的),和更高的工作效率,以及能够持续维护的样式模块,也更具有可读性。但是在抽象的过程中,需要对需求,设计有更深层次更全面的理解和抽象,同时也需要设计和需求较为稳定,尽量没有大的需求或设计改动,如果设计不断改动,需求不断变化,那么很多抽象的类将会被破坏,最终容易造成代码混乱不堪。所以在小的项目中有些大材小用。

 使用OOCSS的注意事项(可能帮助你快速上手):

  1. 避免后代选择器(如不要使用类似于.sidebar h3):这会产生外部容器的依赖;
  2. 避免用id作为样式钩子:id是唯一的,无法复用;
  3. 避免在你的样式表中给类名附属一个元素名
  4. 除非一些很少的情况,避免使用!important:暴力方法,代码将会难以维护;
  5. 使用CSS网格(布局重用必备)

SMACSS

SMACSS中把样式根据逻辑划分为了5个类别:

1.base:

base类似于我们常用的reset,就是设定标签的预设值。在这一部分样式的要求是:不要出现任何的id selector和class selector,但可使用 属性选择器和伪类选择器。

代码示例:

html{ … },   input[type=text]{ … },  a:hover { … }

2.layout:

大区块的位置、布局样式。在这里是使用id selector和class selector。

代码示例:

#header { margin-top: 20px 0; }, .container { margin: 0 auto; width: 960px; }

3.Module:

module即组件样式,需要能在任何地方复用的,自觉和bootstrap中的components非常相似。这里使用class selector和 descendent selector(后代选择器).

代码示例:

 .button { background-color: #foo; border: …; width: …;  box-shadow: …; padding: …;}

 .button a { color: #ddd; } 或者 .button .link { color: #ddd; } (多用class,少用tag)

4.state:

状态,故控制module各个状态下的表现的样式。使用class selector。

.button.hovered { background: …; }

.button.actived { background: …; }

5.theme:

主题,也就是项目特有的主题下的样式,主视觉效果,主题的样式去override上面的样式,来达成需要的视觉效果,就类似于皮肤skin。在google material设计中,就用了md-default-theme这样的类名来为各个module添加额外的样式,比如background-color之类的skin,它也支持用户自己配置theme的色彩样式,大爱!

关于SMACSS的个人总结:根据CSS rules自身不同的逻辑作用去分门别类非常的cool,使用前一定要花功夫去认真分类样式,如果分类混乱,将难以复用。像OOCSS,在需求设计改变频繁时,很难把控。

ACSS(atomic CSS、原子CSS)

ACSS即为原子CSS,就像自然界中把整个的物体不断拆分最后都是由原子之类构成的(化学没学好),这样也就不存在物体之间的差别了,所有事物都是原子,也就方便了描述。ACSS把每一条CSS rule都看做一个原子,给rule一个class类名。

示例代码:

.mr-1 { margin-right: 10px; }   .mr-2 { margin-right: 20px; }

<div class=“mr-1 of-h foo foo foo foo foo foo ”></div>

就用这一个个class复合在一起,来实现样式表现。这样的好处是什么呢?很容易看懂,每个class对应的就是那条rule,会CSS的人都能看懂。它声称自己语义化的优势,一个好的命名就是在任何时候,都不改变名称,它做到了。 并且在需求和设计频繁改变时,只需要在改变的元素上修改class属性就搞定了,相当方便,面对改变游刃有余。

但是,ACSS会在你的html文件中添加无数的class,污染html,可读性大大降低,如果元素的样式复杂,很难想象上面有几十个class该怎么去阅读。

关于ACSS的个人总结:ACSS最大的优点是,应对变化相当灵活,在页面较简单的情况下,很适合使用,但在复杂的场景中,html的混乱也会导致严重后果。我个人更愿意在项目或者模块开发之初使用ACSS,这样可以应对频繁修改的需求和设计。当需求和设计趋于完整稳定时,再去用模块化的思想重构它,把杂乱无章的class抽丝剥茧。所以ACSS让CSS代码的重构变得更容易了。

BEM(Block____Element——Modifier)

BEM:Block(块)、Element(元素)、Modifier(修饰符)

BEM本身是有一套自己的工作流的,指的是由Yandex团队提出的一种前端命名方法论。BEM的命名约定更严格,包含更多的信息。

Block:独立的、更高级别的组件化抽象。Class selector only。

Element:Block的后代,是Block的构成元素。Class selector only。

Modifier:注明了Block的不同状态或不同版本。

命名约定的模式如下:

.block {}

.block____element {}

.block——modifier {}

它们中使用两个下划线或者两个破折号只是为了同其他的命名规范区别开,避免相互影响。它们之间的符号是可以更换的,没有强制约定。

下面我们来看一个例子,看看BEM是如何让元素之间建立起联系的:

.car {} //  创建了一个car block

.car____tire {} //car里面有组成元素(后代元素)  tire

.car——china {} //car有一个china造 的形态

.car——china____tire {}  //既然car有tire组成元素,那china car当然也有tire噢

.car____tire——new  //car里的tire 有new(old)的状态

代码理解:汽车是一个block,汽车有一个组成部分就是轮胎,有的汽车是中国制造,中国制造的车也是有轮胎的,汽车轮胎是新的。

BEM同样能将这样的信息传递同你合作,或者维护你的代码的人。尽力在团队里建立起这样的命名规范,将使你和团队的代码都更加健壮,更易维护。

但BEM并不是任何地方都能使用的,比如下面这种情况:

.underline {  text-decoration:  underline;  }

.caps {  text-transform:uppercase;  }  

这些仅仅是一条单独的样式,并不需要使用BEM格式的命名。

再看看下面这段存在于网站header块内的logo的代码:

.site-logo{ … } 

用BEM格式写作:

.header{}

.header__logo{} 

虽然logo确实是在header内,但作为一个希望被复用的block,logo也可能出现在footer,side里面,所以并不一定总是存在header中,故不该使用BEM。正确辨别BEM的使用场景尤为重要。

关于BEM的个人总结:“class属性是对tag的细化描述”,并且表达的意思清晰,使用起来也很简单。“会说话”的class使得样式代码语义化,更容易维护,也提高了复用性。但是要用好BEM需要不断的积累和思考,使BEM命名标记的使用准确。好东西!

Summary

踏上前端的路差不多有一年了,在团队里主要负责页面部分的工作。每天混迹在各个前端群里,大部分时候人们都在讨论js的问题,作为页面仔的我还是忍不住为CSS报不平。一年前,正是codepen上面那些酷炫的web动画将我带上了这条路。CSS,作为完全为内容表现服务的语言,它应该得到重视。CSS不断被支持的新特性使web一次次的让用户惊艳。Sass、Less等预处理器也让CSS如虎添翼,高性能,多样化的动画效果对用户体验的提升产生了不可替代的作用。喜欢编写CSS代码,在今后的路上继续学习CSS,力图写出优雅的CSS代码!酷炫的web特效~!

对页面特效情有独钟,CSS3过渡,动画,D3数据可视化+动画一直激励着我上下求索~谢谢一直指导我的良师益友De。

最后,引用一句慕课网上的《CSS框架迷思》的作者的话:“ 没有语义化的CSS,只有语义化的html和它的表现形式 ”。

上一篇:Timesten 日常管理命令合集


下一篇:Android碎笔录1——基本布局