一、 常见CSS设计模式分析
oocss
Object Oriented CSS,面向对象的CSS,旨在编写高可复用、低耦合和高扩展的CSS代码。
OOCSS是以面向对象的思想去定义样式,将抽象(结构)和实现(样式)分离,抽离公共代码。
区分结构和样式
在定义一个可重用性的组件库时,我们仅创建基础的结构(html)和基础的类名,不应该创建类似于border, width, height, background等样式规则,这样使组件库更灵活和可扩展性。组件库在不同环境下的样式所要求不一样,若未能区分其结构和样式,给其添加样式,会使其变成一个特定的组件库,而难以重用。
以下是一个基础库创建的样式:
.metadata{
font-size: 1.2em;
text-align: left;
margin: 10px 0;
}
若在给其添加更多的样式:
.metadata{
font-size: 1.2em;
text-align: left;
margin: 10px 0;
/*在基础组件上新加的样式*/
width: 500px;
background-color: #efefef;
color: #fff;
}
这样就使前面创建的基础组件metadata变成了一个特定的组件了,使其在其他场景下较难复用。
区分容器和内容, 把容器和内容独立分区,使内容能作用于任何容器下。
#sidebar h3 {
font-family: Arial, Helvetica, sans-serif;
font-size: .8em;
line-height: 1;
color: #777;
text-shadow: rgba(0, 0, 0, .3) 3px 3px 6px;
}
上面我们定义了一个id为sidebar 中 h3的样式,但是我们发现在footer 中 h3的样式也基本一致,仅个别不一样,那么我们可能会这样写样式:
#sidebar h3, #footer h3 {
font-family: Arial, Helvetica, sans-serif;
font-size: 2em;
line-height: 1;
color: #777;
text-shadow: rgba(0, 0, 0, .3) 3px 3px 6px;
}
#footer h3 {
font-size: 1.5em;
text-shadow: rgba(0, 0, 0, .3) 2px 2px 4px;
}
甚至我们可能会用更糟糕的方式来写这个样式:
#sidebar h3 {
font-family: Arial, Helvetica, sans-serif;
font-size: 2em;
line-height: 1;
color: #777;
text-shadow: rgba(0, 0, 0, .3) 3px 3px 6px;
}
#footer h3 {
font-family: Arial, Helvetica, sans-serif;
font-size: 1.5em;
line-height: 1;
color: #777;
text-shadow: rgba(0, 0, 0, .3) 2px 2px 4px;
}
我们可以看到上面的代码中出现了不必要的duplicating styles。而OOCSS鼓励我们应该思考在不同元素中哪些样式是通用的,然后将这些通用的样式从模块、组件、对象等中抽离出来,使其能在任何地方能够复用,而不依赖于某个特定的容器。
<div class="header theme"></div>
<div class="footer theme"></div>
.header {
height: 100px;
width: 100px;
}
.footer {
height: 200px;
width: 100px;
}
.theme {
font-family: Arial, Helvetica, sans-serif;
font-size: 2em;
line-height: 1;
color: #777;
text-shadow: rgba(0, 0, 0, .3) 3px 3px 6px;
}
最终实现结构与样式分离,从而提高了样式代码的可复用性
SMACSS
Scalable and Modular Architecture for CSS,可扩展模块化的CSS,它的核心就是结构化CSS代码,提出了一种CSS分类规则,分为五种类型:
-
Base
-
Layout
-
Module
-
State
-
Theme
SMACSS定义了一种css文件的组织方式,其横向的切分,即按照功能模块划分,使css文件更具有结构化、高可维护性。
- Base
Base是默认的样式,是对单个元素选择器(包括其属性选择器,伪类选择器,孩子/兄弟选择器)的基础样式设置,例如html, body, input[type=text], a:hover, etc.
html, body {
margin: 0;
padding: 0;
}
input[type=text] {
border: 1px solid #999;
}
a {
color: #039;
}
a:hover {
color: #03C;
}
CSS Reset/Normalize就是一种Base Rule的应用.
Note: 在基础样式中不应该使用!important
- Layout
不明思议,是对页面布局元素(页面架构中主要和次要的组件)的样式设置,例如header, navigation, footer, sidebar, login-form, etc.
.header, footer {
margin: 0;
}
.header {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 9999;
}
.navs {
display: inline-block;
margin: 0 auto;
}
- Modules
对公共组件样式的设置,例如dropdown, tabs, carousels, dialogs, etc.
.dropdown, .dropdown > ul {
display: inline-block;
border: 1px solid #283AE2;
}
.dropdown li:hover {
background-color: #999;
}
.tabs {
border: 1px solid #e8e8e8;
}
.tabs > .tab--active {
border-bottom: none;
color: #29A288;
}
- State
对组件、模块、元素等表现行为或状态的样式修饰,例如hide, show, is-error, etc.
.hide {
display: none;
}
.show {
display: block;
}
.is-error {
color: red;
}
- Theme
对页面整体布局样式的设置,可以说是一种皮肤,它可以在特定场景下覆盖base, layout等的默认样式。
.body--theme-sky {
background: blue url(/static/img/body--theme-sky.png) repeat;
}
.footer--theme-sky {
background-image: blue url('/static/img/header--theme-sky.png') no-repeat center;
}
BEM
BEM 是我的方法的基础。如果你以前从未听说过 BEM,它代表 block , element 和 modifier。当你第一次接触它时,它看起来是那么的难看。
.block { /* styles */ }
.block__element { /* styles */ }
.block--modifier { /* styles */ }
当我第一次看见 BEM 的时候,我就很讨厌它,甚至没有给它一个机会。我不记得是什么驱使我尝试 BEM 的,但我现在深深的知道它有多么的强大。让我来完整地解释一下 BEM 是什么(当然,加入了我自己的理解)。
- 块
一个块就是一个组件。这有点抽象,所以让我们用示例来学习。
假设您正在建立一个联系表单。在这种情况下,这个表单可以是一个块。在 BEM 中,块被写为像 class 的名字一样,如下所示:
.form { /* styles */ }
BEM 使用 .form
而不是 <form>
元素的原因是因为 类允许无限的可重用性,而即使是最基本的元素也可能改变样式。
按钮很好地阐释了可以包含不同样式的块。如果将 <button>
元素的背景颜色设置为红色,则所有<buttons>
都将被强制继承红色背景。接下来,你必须通过覆盖你的<button>
元素来修复代码(并且可能会在修复中“伤及无辜” )。
button {
background-color: red;
}
.something button {
background-color: blue;
}
如果设置了一个 .button 类的按钮,则可以在任何<button>
元素上选择是否使用 .button 类。那么,如果你需要一个不同的背景颜色,你所做的就是改成一个新的 class
,比如说 .button--secondary
,很舒服吧!
.button {
background-color: red;
}
.button--secondary {
background-color: blue;
}
- 元素
元素是块的子节点。为了表明某个东西是一个元素,你需要在块名后添加__element。所以,如果你看到一个像那样的名字,比如 form__row ,你将立即知道 .form 块中有一个 row 元素。
<form class="form" action="">
<div class="form__row">
<!-- ... -->
</div>
</form>
.form__row {
/* styles */
}
BEM 元素有两个优点 :
- 你可以让 CSS 的优先级保持相对扁平。
- 你能立即知道哪些东西是一个子元素。
为了解释以上两点,考虑使用两个单独的 class 的替代方法(许多框架这么做的)。你可能会用这样的东西:
<form class="form" action="">
<div class="row">
<!-- ... -->
</div>
</form>
.form .row {
/* styles */
}
如果你使用 BEM
元素,则可以使用优先级为 10 而不是 20 的的选择器来为 .form__row
提供样式。此外,你可以立即分辨出(不论是在 HTML 还是 CSS 中).form__row
是 .form
的子节点。
- 修饰符
修饰符是改变某个块的外观的标志。要使用修饰符,可以将 --modifier 添加到块中。
从上面的按钮示例继续,修改的按钮将被命名为 .button–secondary。
在传统的 BEM 中,当你使用修饰符时,你应该 将块和修饰符添加 到 HTML 中,以便在新的 .button–secondary 中不重写 .button 样式。
<button class="button">Primary button</button>
<button class="button button--secondary">Secondary button</button>
.button {
padding: 0.5em 0.75em;
background-color: red;
}
.button--secondary {
background-color: green;
}
注意为什么没有必要在 .button–secondary 中重新声明 padding
,因为它已经在 .button
中声明了。这很棒,因为 BEM 确保你编写简洁的 CSS,而不需要付出大量的工作。
ITCSS
组织CSS的现代方法通常会退回到模块化或CSS对象来构造抽象思想。
倒三角形CSS的新思想是一种基于 CSS属性 的特异性和重要性的分层方法 。 与SMACSS和OOCSS相比,这是一种鲜为人知的方法-尽管两者都可以与ITCSS结合使用。
由于ITCSS 主要是专有的 ,因此不存在有关其用法的详细规则手册。 我们只能使用一组特定的原则 。 作者在下面的视频中谈到了它们。
默认情况下,ITCSS使用相同的原则OOCSS 但基于特异性更大的分离 。 因此,如果您已经熟悉OOCSS,请考虑尝试使用这种独特的替代CSS体系结构 。
以下是使用ITCSS的最大好处:
- 页面对象可以拆分为自己CSS / SCSS文件,以实现可重用性 。
- 复制/粘贴并将每个对象扩展到其他项目很简单 。
- 具体的深度取决于您 。
- 没有设置的文件夹结构 ,也不需要使用预处理工具。
- 您可以合并来自其他方法(例如CSS模块)的概念,以创建自己的混合工作流 。
从倒三角形的平坦顶部到底部尖端的定向流表示特异性的增加 。 由于专注于降低特异性 ,因此可以更轻松地在站点中多次重用类。
三角形的每个子部分都可以视为一个单独的文件或文件组,尽管您无需以这种方式编写代码。 由于具有导入功能,因此对Sass / Less用户更有意义。 只需将每个小节视为拆分和组织可重用CSS代码的方法即可 。
让我们快速看一下倒三角形从上到下的每个部分 。
- 设置 –预处理程序变量和方法(无实际CSS输出)
- 工具 – Mixins和函数(无实际CSS输出)
- 常规 – CSS重置,其中可能包括Eric Meyer的重置, Normalize.css或您自己的一批代码
- 元素 –没有类的单个HTML元素选择器
- 对象 -通常遵循OOCSS方法的页面结构类
- 组件 –用于设置任何页面元素和所有页面元素样式的美学类(通常与对象类的结构结合使用)
- Trumps –最重要的样式,用于覆盖三角形中的任何其他内容
倒三角形的每一层都可以调整以满足您的需要 。 因此,如果您不使用CSS预处理器,则不需要设置或工具层。
在实际项目中应当灵活使用。
ACSS
ACSS使用了紧密的类名库。 这些类名通常被缩写,并与它们影响的内容分开。 在ACSS系统中,您可以知道类名的作用; 但是类名称(至少不是样式表中使用的名称)与内容类型之间没有关系,即每一个样式对应一个类,也称原子类CSS。
.bg-a {
background-color: #a6d5fa;
}
.bg-b {
background-color: #aedbaf;
}
.bg-c {
background-color: #ffe8a5;
}
.bg-d {
background-color: #faaaa4;
}
二、CSS设计模式在UI库中的使用情况分析
-
ITCSS + BEM
-
ITCSS + BEM
-
ITCSS + OOCSS
-
ACSS
总结
- 在各流行UI库中CSS设计模式无处不在
- 我们应当积极在项目中实现自己的CSS设计模式组合以便优化我们项目的CSS架构
- 建议使用ITCSS架构,配合BEM命名规范,组织ACSS基础样式便于后续使用