css设计模式,打造一套稳健易拓展的css架构(一)
关于css,曾经有人说:“三个月80分, 三年90分”。确实,css很简单,简单的我们从来不曾将它当作一门编程语言,相比于js,自然花费的时间和精力少之又少。事实真的是我们想象的吗?从我个人角度来说,css应该值得我们重视,因为css的重构难度实在太大了,如果没有一套稳健的css规范,随着项目的扩展,css代码会越来越混乱,给我们带来的麻烦也会越来越多。比如样式覆盖、层级的问题有时候真的令人头疼。或许,我们可以在html代码中直接给写内连样式,但这显然并不是我们所期待的!为此,我也是找了一些学习视频,学习了一下关于css模式和架构的东西,在此希望对看到本篇文章的道友们有所帮助。
一、为什么要学习css模式、css架构?
我一直在维护一套价值好多钱的一套前端代码,是关于云原生PASS平台的。项目比较旧,使用到了AMD开发规范。底座用agular 1.2,业务层是用vue 2.x,内部的子产品模块用的是react 16.x。具体结构可以参照下图1。
图1
对于这样一套代码,理解成本还是很高的,当前我们在开发的时候,也体验不到像代码热更新,vuex这样便捷的工具。由于项目使用到nginx,每次编写代码后,还得深度刷新才能看到效果,一开始真的是苦不堪言!关于css,那就更乱了,每个组件中都充斥大量的内联样式,导致html代码的可读性很差。其次,因为代码的覆盖的,有时候导致弹出样式的层级出现问题,真可谓是难上加难!
二、css有哪些模式(架构)能帮助我们呢?
对于css,业界还是有好多解决方案。例如 OOCSS、BEM、SMACSS、ITCSS以及ACSS。下面我们就逐一看一下这几种模式。本篇文章,我们先来学习OOCSS。
三、OOCSS(Object Oriented CSS) 面向对象的CSS
1、什么是OOCSS?
“面向对象的概念”已经成为现代编程语言的一种基本形式,数据的抽象化、模块化和继承等特点在编写代码中得到了大规模的应用。面向对象的CSS是一种容易重用的一种CSS规则,也是OOP的概念,从而降低了页面的加载时间,提高了网面的性能。要理解OOCSS,还是得紧抓两个特性 。所有的这一切都是为了提高代码的可重用性,减少css的代码量,css代码更易扩展。
您可能在平时写代码时使用了这个概念,只不过可能不知道这个术语罢了,下面大家先来看一个实例,比如说,我们有下面三个容器,宽高都是100px,如果我们想给三个容器分别添加一个背景颜色#000 、#fff 、#ccc,我们常常给各个容器分别创建一个类,并把这些背景主题也一并加上。
Demo1:
<div class="container"></div>
<div class="container1"></div>
<div class="container2"></div>
把相应的样式加在这个容器上
.container1{ width: 100px; height: 100px; background: #000 }
.container2{ width: 100px; height: 100px; background: #fff }
.container3{ width: 100px; height: 100px; background: #ccc }
如果我们使用了OOCSS,那么我们的方式就可以是下面这种。定义一个基础的容器样式,单独对背景色(主题)进行扩展。
<div class="container blank"></div>
<div class="container white"></div>
<div class="container grey"></div>
把相应的样式加在这个容器上
.container { width: 100px; height: 100px; }
.blank{ background: #000 }
.white{ background: #fff }
.grey{ background: #ccc}
从上面的比较来看,使用了OOCSS之后,我们的代码语义化更强,可拓展性更强。在这里我们所说的对象其实很简单, 。
2、OOCSS的原则?
原则1: 独立的容器和内容
独立的结构和样式就是把布局样式和设计样式独立出来。实现这一点最好的方式就是使用网格布局系统,比如说BootStrap、Layer或者是你自己创建的布局。当然你也可以不使用网格系统,你只要定义页面上的主要对像的结构就行了。
假如我们有两个容器,容器中的内容都是一样的,如何采用这条原则来规范我们的样式编码呢?
<!--容器1-->
<div class="post">
<p class="metadata">ContentText</p>
</div>
<!--容器2-->
<div class="comment">
<p class="metadata">ContentText</p>
</div>
我们可能会采用这样的编码方式
.post .metadata{ css code }
.comment .metadata{ css code }
上面的这样方式违背了容器与内容分离的原则,正确的姿势应该如下:
.post { css code }
.comment { css code }
.metadata { css code }
原则2:独立的结构和样式
上面的Demo1正是依据此规则来设计的。独立的容器和内容所指的是把内容从容器中分离出来,换过句话说任何对象(容器),应该适应接受任何形式的内容。
3、如何使用OOCSS
在创建OOCSS第一步需要做的就是创建一个组件库,这也是创建OOCSS最烦锁的过程,所发时间也是最长的一个过程,但同时也是最关键的一个过程。因为你要去寻找哪些组件是可以重用的,然后给这些组件创建一个对应的HTML标签,并创建各自UI所需要的样式风格,例如一个博客中,有一个"meta data(作者发布时间相关信息)"将在一个页面不同地方出现,如下图所示:
经过观察和思考,你发现上图中三个"meta data"虽然位置在不同地,并且UI风格不一样,但他们都有一个共同点,就是HTML结构可以是一样的。这样一来,你就可以选择一个标记,作为HTML的基础结构,如:
Base Markup
<p class=”metadata”>
<a>Author name</a>commented on<a>21-02-2010</a>@
</p>
Base Css
.metadata{font-size:1.2em; text-align:left; margin:10px 0;}
这样我们就把“meta data”单独独立出来了,使用了一个相同的HTML模板,并且有一个一样的样式,不管他在页面什么位置出现,都会是一样的结构一样的样式。但是从上图我们明显可以看到,有多个组件在变化,说简单点就是"meta data"估页面不同地方,样式不一样,解决这样的我们都是使用css来处理。后面我们会进一步介绍如何来解决这样的不同样式效果。
独立的容器和内容,并且避免样式依赖位置也是用面向对象的方法创建CSS的基本要求之一,这里的核心思想是,把容器和内容独立出来,这样的好处是,内从插入到任何容器中都可以。但在页面制作中,常常碰到一个组件同时出现在不同的容器中,也出现在页面的不同位置之处。对于这样的现象,前端工程师一般都会通过其父元素容器给特定的组件设置不同的样式规则。
承接前面的实例,我们把“meta-data”放在不同的容器中,并给这个容器指定相应的类名或id名,如:
HTML Markup
/*post中的meta-data*/
<div class="post">
<p class=”metadata”>
<a>Author name</a>commented on<a>21-02-2010</a>@
</p>
</div>
/*comment中的meta-data*/
<div class="comment">
<p class=”metadata”>
<a>Author name</a>commented on<a>21-02-2010</a>@
</p>
</div>
/*userinfo中的meta-data*/
<div class="userInfo">
<p class=”metadata”>
<a>Author name</a>commented on<a>21-02-2010</a>@
</p>
</div>
CSS规则
.metadata{ css code }
.post {css code}
.comment {css code}
.userInfo {css code}
参考文档 https://www.w3cplus.com/css/oocss-concept (W3CPLUS)