CSS(Cascading Style Sheets),从诞生之初就决定了它无法编程,甚至连解释性语言都算不上,只能作为一种简单的层叠样式表,对 HTML 元素进行格式化。
在大多数开发场景下,会产生各种问题,例如:
- 组件关系越复杂,会产生命名困难
- 在团队协作中,产生相同命名定义冲突
- 选择器定义越来越长,层级结构越来越模糊
- 代码难以复用,维护越来越难
- 样式包文件越来越大,不利于生产环境加载渲染
- ...
在问题处理上,现在大多数团队都提出相应的规范和模块处理解决方案。
规范及约束
在css规范中提出:使用有意义的或通用的ID和class命名。ID和class的命名应反映该元素的功能或使用通用名称,而不要用抽象的晦涩的命名。反映元素的使用目的是首选;使用通用名称代表该元素不表特定意义,与其同级元素无异,通常是用于辅助命名;使用功能性或通用的名称可以更适用于文档或模版变化的情况。
常用命名(多记多查英文单词):page、wrap、layout、header(head)、
footer(foot、ft)、 content(cont)、menu、nav、main、submain、
sidebar(side)、logo、banner、 title(tit)、popo(pop)、icon、
note、btn、txt、iblock、window(win)、tips等
注:类型选择器避免同时使用标签、ID和class作为定位一个元素选择器;从性能上考虑也应尽量减少选择器的层级。
CSS模块化
模块是页面上数量最多,同时也是最重要的部分,它是代码复用的主体部分,是一个个按照功能划分的区域,如导航栏、轮播图、登录窗口、信息列表等等。模块之间相互独立,分布在页面上,嵌在框架的各个位置上,组成一个丰富多彩的页面。
==1. 通过组件来定义CSS模块化==
Yandex团队提出的一种前端命名方法论 BEM 。注意:它不是一个框架,它只是一种思想。
BEM的意思就是块(block)、元素(element)、修饰符(modifier)
// 块即是通常所说的 Web 应用开发中的组件或模块。每个块在逻辑上和功能上都是相互独立的。
.block{}
// 元素是块中的组成部分。元素不能离开块来使用。BEM 不推荐在元素中嵌套其他元素。
.block__element{}
// 修饰符用来定义块或元素的外观和行为。同样的块在应用不同的修饰符之后,会有不同的外观。
.block--modifier{}
优点:BEM 的优点在于所产生的 CSS 类名都只使用一个类别选择器,可以避免传统做法中由于多个类别选择器嵌套带来的复杂的属性级联问题。在 BEM 命名规则中,所有的 CSS 样式规则都只用一个类别选择器。因此所有样式规则的特异性(specificity)都是相同的,也就不存在复杂的优先级问题。这可以简化属性值的层叠规则。代码清单中的命名规则的好处在于每个 CSS 类名都很简单明了,而且类名的层次关系可以与 DOM 节点的树型结构相对应。
缺点: CSS 类名会比较长而且复杂。乍看之下,根据 BEM 命名规则产生的 CSS 类名都会很复杂,但实际上在熟悉了命名规则之后,可以很容易理解其含义。
面向对象 CSS(Object Oriented CSS / OOCSS)
是一种把面向对象方法学应用到 CSS 代码组织和管理中的实践。 OOCSS最关键的一点就是:提高他的灵活性和可重用性。这个也是OOCSS最重要的一点。OOCSS主张是通过在基础组件中添加更多的类,从而扩展基础组件的CSS规则,从而使CSS有更好的扩展性。
假设我们有一个容器是页面page的1/4宽,有一个蓝色的背景,1px灰色的边框,10px的左右边距,5px的上边距,10px的下边距,以前对于这样一个样式,我们常常给这个容器创建一个类,并把这些样式全部加上。像下面这样:
// template
<div class="size1of4"></div>
// style
.size1of4 {
background: blue;
border: 1px solid #ccc;
margin: 5px 10px 10px;
width: 25%;
}
然而使用oocss的话,我们不这样做,我把为这个容器创建更多的类,并且每个样式对应一个类,这样是为了后面可以重复使用这些组件的样式,避免重复写相同的样式,就拿这个实例来说,我们给这个容器增加下面的类:
// template
<div class="size1of4 bgBlue solidGray mts mlm mrm mbm"></div>
// style
.size1of4 {width: 25%;}
.bgBlue {background:blue}
.solidGray {border: 1px solid #ccc}
.mts {margin-top: 5px}
.mrm {margin-right: 10px}
.mbm {margin-bottom: 10px}
.mlm {margin-left: 10px}
优点:
- 减少CSS代码
- 具有清洁的HTML标记,有语义的类名,逻辑性强的层次关系
- 语义标记,有助于SEO
- 更好的页面优化,更快的加载时间(因为有很多组件重用)
- 可扩展的标记和CSS样式,有更多的组件可以放到库中,而不影响其他*
的组件 - 能轻松构造新的页面布局,或制作新的页面风格
- 适合大型应用
缺点:
- 如果没用巧妙的使用,创建组件可能对于你来说是一堆没用的东西,成为一烂摊子,给你的维护带来意想不到的杯具,说不定还是个维护的噩梦
- 实施成本较大
==2. 通过属性来定义模块化==
AMCSS(属性模块)
属性模块或者说AM,其核心就是关于定义命名空间用来写样式。通俗的讲就是,给一个元素加上属性,再通过属性选择器定位到这个元素。达到避免过多的使用class。
// template
<div am- Row ></div>
<div am- Column = "12"> Full < /div>
</ div> <div am- Row > <div am- Column = "4"> Thirds </div>
<div am- Column = "4"> Thirds </div>
<div am- Column = "4"> Thirds < /div> </ div>
// style
[am- Row ] { /* max-width, clearfixes */ }
[am- Column ~= "1" ] { /* 1/12th width, floated */ }
[am- Column ~= "2" ] { /* 1/6th width, floated */ }
[am- Column ~= "3" ] { /* 1/4th width, floated */ }
[am- Column ~= "4" ] { /* 1/3rd width, floated */ }
[am- Column ~= "5" ] { /* 5/12th width, floated */ } /* etc */
[am- Column ~= "12" ] { /* 100% width, floated */ }
优点:
- 避免过多的使用class
- 可以使用任何前缀名实现定义
缺点
- 确保属性模块不会与现有属性冲突
- 类似于1、4或12这样的值,要确保定义准确对应,否则造成冲突的机会很多