本文基于工作学习与交流,做的整理笔记
当我们在搭建一个项目的时候,我们考虑的一个主要部分就是CSS架构问题。每当我们做完一个项目的时候,我们去不断维护一个项目的时候,让我们感觉到无比头痛的还是CSS架构问题。上周,在公司前端组内发起了一次关于“CSS架构”的探讨。结合自己的理解,整理后的内容如下。
前提条件:
只要会CSS就行,这里只是讨论如何让项目中的CSS更理想。
编码环境:
系统:OS X EI Capitan
版本:10.12.5
目录
| - 0.背景
| - 1.现有框架
| - 2.理想架构
| - 3.项目中实际问题
| - 4.结构梳理
| - 5.命名规范
| - 6.构建工具
| - 7.待讨论问题
| - 8.结束
由于当天有临时工作需要,并没有参加公司内部的这次讨论。我是在会议后阅读各位小伙伴为这次讨论准备的文档,以及正常讨论的会议纪要。文中内容的书写过程为:先进行个人思考,然后阅读小伙伴的文档和纪要,再进行内容优化及调整。
0.背景
当我们准备搭建一个项目时,以及做完一个项目进入到维护期时,我们都需要注意和思考的其中一个问题,就是关于CSS的问题。
项目开始前,我们思考:
该如何对一个项目的CSS进行架构,结构如何,命名如何,构建工具如何?
我们理想中的架构是怎么样的,而现实中我们遇到的实际问题,导致最终呈现出来的结果又是怎么样的。
1.现有框架
现在社会中常说的一句话就是“前端圈真乱”,各种前端脚手架、构建工具、UI框架层出不穷。说说UI框架,常用的就有Bootstrap,Foundation,Pure,Ant-Design,Semantic-UI,Material-UI,Element-UI,WeUI等等,好多好多,它们分别适用jQuery,React,Vue,Angular,WeApp,以及针对移动端等等。
每次我们在项目使用的时候,总有组件没有场景使用,也总有组件满足不了我们的需要,我们便开始在框架的CSS基础上不断扩展。
知乎上有个回答者说:“少用框架,会被框架绑架的。我觉得,用最少的代码实现轻巧的UI,才是王道”。大概我们理想中也是这样的,但是我们另一方面却还想快,项目的进度赶,找一个合适的框架就满足了这样的快。
2.理想架构
大概每个前端的心中都有一个理想架构,那个架构是随着开发经验的累积,不断优化,不断清晰的。那到底,我们想要的理想架构具有哪些特点?
- 结构清晰,一目了然,符合通用性,看后能马上清楚定位
- 命名规范,语义清晰,能分清全局还是局部,用在什么场景
- 低耦合,一方面是css类之间的耦合度降低,另一方面是和html代码之间的耦合降低
- 高复用,可扩展,多处可以使用,又可以轻易抽离
后面2点,其实不太好理解,甚至是有些矛盾。我们在实际应用中,不经意间就会加强类和类之间的耦合,会渗透污染,变得不易维护。高复用带来的是不敢轻易修改,因为不确定影响范围有多大。
查阅一些文献文章,我看到一些比较好的建议。一起看一下,在书写css的时候,我们应该避免哪些问题。以下用法应尽量避免,从而降低维护难度,不建议使用:
- 基于父组件来修改组件
.widget {
background: yellow;
border: 1px solid black;
color: black;
width: 50%;
}
//错误的
#sidebar .widget {
width: 200px;
}
//正确的
.widget-sidebar {
width: 200px;
}
- 过于复杂的选择器
//和html耦合太紧了,只要修改html结构必须要调整css
#main-nav ul li ul li div { }
#content article h1:first-child { }
#sidebar > div > h3 + p { }
- 过于通用的类名
//看起来没错,它阻止了样式影响相同类名的其他元素,被限制在widget元素内
//但是没有组织外部相同类名可能会影响它
.widget {}
.widget .title {}
.widget .contents {}
.widget .action {}
//如果外部有如下这个样式,则会污染它
.title {}
- 一个规则做太多事
//这个规则既控制了位置,又控制了外观
//外观一般可复用,但位置不行
.widget {
position: absolute;
top: 20px;
left: 20px;
background-color: red;
font-size: 1.5em;
text-transform: uppercase;
}
3.项目中实际问题
项目中,我们遇到最头痛的问题就是“越维护,越臃肿”,到最后,自己都不想看,想整理重构却又觉得时间不够,有心无力到放弃。
首先,我们按照分析事情的逻辑法则“谁、怎么样、为什么、怎么办”去看一下,我们去想想为什么会发生这种事:
- 贪图快,就修改一点样式或增加一点样式,随便扩展或增加一个class就好了
- 修改样式时为了避免影响其他地方的样式,我们只能.class .class对某一个样式进行扩展,甚至使用!important去强制
- 命名不规范,结构混乱,自己都很难找,很难确定
- 还有可能是设计师的锅,到处都不复用,到处个性化
- ...
可能还有好多原因,反正不知不觉间我们就埋了一个大坑留着日后自己跳进去。那个坑随着项目的页面增多、功能迭代,越挖越深,最后无力应对。
我们是否有一些好的原则,去应对导致这一结果的原因:
- 结构合理,命名规范
//这个是一开始就要考虑的问题,在执行过程要严格的遵守
- 专注,也就是类直接控制某一个元素的效果,这样容易预测,不会因为混乱
//不好的方式(容易引起混乱)
#main-nav ul li ul { }
//直接(可预测)
.subnav { }
- 模块化
//常见的就是使用页面类、容器类做限制
- 给类进行命名空间
//不好
.widget { }
.widget .title { }
//好
.widget { }
.widget-title { }
- 创建修饰符类来扩展组件
//不好
.widget { }
#sidebar .widget { }
//好
.widget { }
.widget-sidebar { }
4.结构梳理
一般按照文件的分类进行结构划分,大致如下:
|- style.sass 入口
|- _variable.sass 变量类
|- _normalize.sass 重置类
|- _base.sass 基础类
|- _layout.sass 布局类
|- _mixin.sass mixin
|- _media.sass 媒体类
|- _theme.sass 主题类
|- component 组件
|- index.sass 入口
|- _alert.sass 警告
|- _table.sass 选项卡
|- ...
|- page 页面/模块
|- index.sass 入口
|- _dashboard.sass 看板
|- _user.sass 用户
|- ...
具体根据自己的架构调整,没有一个标准。
5.命名规范
我们给自己的项目制定一套命名规范,其实就是希望能够更有逻辑的命名。这里,可以去阅读部分UI框架的命名,去参照。比如命名规范如下:
- 以‘-’为主,不建议过多‘-’,最多3个
- 配合‘--’表示分类
- 配合‘__’表示内部标签
我们通常把css分为几类,比如基础(base)、布局(layout)、模块(modules)、状态(state),以及JS使用的钩子类。要么通过前缀区分,要么通过结构实现。
再进行类名的命名时,我们还应该避免比如fs-14
、fs-16
、p-20
等命名,原因是那样子后续修改维护可能会带来困难。比如之前引用fs-14
的所有地方,我要把字号变成16,你需要修改所有引用的class,还是把fs-14
直接改为font-size:16px
。所以,应该通过更具备语义化等命名,比如:
- size (xs/sm/md/lg)
- status (default/primary/warning/danger/success/info)
- color (dark/gray/purple)
命名举例,以tab
组件为例:
.ui-tab 代表正常大小
.ui-tab-title 代表内部title
.ui-tab-content 代表内部content
.ui-tab__span 代表内部的span
.ui-tab__icon 代表内部的icon
.ui-tab--lg 代表大型
.ui-tab--sm 代表小型
.ui-tab--xs 代表超小型
6.构建工具
构建打包,这里就不详细说明了,比如使用grunt,gulp,webpack等等都可以,萝卜青菜各有所爱。
7.待讨论问题
遗留了一个关于类命名的争议点,就是如何去在OOCSS和BEM两种命名方式中去做取舍,去取一个平衡点。
8.结束
这篇文章主要讨论了一下CSS架构的相关问题。可以说,我们想的是一回事,但在实践中可能为了某些方便、快捷、或者是潇洒任性,我们慢慢的就跑偏了,这是理想和现实差距。不管怎么说,通过这样一次讨论,我们又开始留意到某些东西。那些曾被我们忽视的细节,再次引起了我们的注意,我们会一步步让项目的CSS架构优化,不断贴近可维护、可扩展的目标。
如有不对的地方,请留言指导,谢谢。
到这里,就先结束了。
学习是一条漫漫长路,每天不求一大步,进步一点点就是好的。