第一次听到“CSS模块化”这个词是在WebReBuild的第四届“重构人生”年会上,当时我还想,“哈,CSS也有模块化,我没听错吧?”事实上,我没听错,你也没看错,早就有CSS模块化这个概念了。之所以我把这个拿出来讨论,是因为一个算是比较大的项目出现了一些重构上的危机,因此引发了我们对页面重构中的CSS进行模块化的思考。

首先,什么是CSS模块化?在谈CSS模块化之前我们先看一下百度百科对模块化的解释:

“模块化是指解决一个复杂问题时自顶向下逐层把系统划分成若干模块的过程。每个模块完成一个特定的子功能,所有的模块按某种方法组装起来,成为一个整体,完成整个系统所要求的功能。在系统的结构中,模块是可组合、分解和更换的单元。”

我对上面一段话的理解是,模块化就像我们玩乐高积木一样,一个积木就是一个单元,可以通过组合不同的积木来搭建一个玩具模型。对于一个玩具模型,也 可以更换部分积木而迅速变成另一个模型。而CSS模块化的关键,就是如何合适地构建这些单元,也就是一个一个的class,以及如何灵活运用这些单元来达 到我们所要的呈现效果。

说了一堆繁杂的话,连我自己都觉得乏味。作为一个热爱编程的页面仔,我想借用面向对象的三大特性来说明CSS模块化——封装、继承、多态。

一、 封装

HTML代码

1
2
3
4
5
6
7
8
9
10
11
12
<div class=”module-a”>
  <h3>标题1</h3>
  <p>描述文字</p>
</div>
<div class=”module-b”>
  <h3>标题2</h3>
  <ul>
<li>列表</li>
<li>列表</li>
<li>列表</li>
  </ul>
</div>

CSS代码

1
2
3
4
5
6
7
8
9
.module-a{.....}
.module-a h3{.....}
.module-a p{.....}
.module-b{.....}
.module-b h3{.....}
.module-b ul{.....}
.module-b ul li{.....}
.module-b ul li{.....}
.module-b ul li{.....}

封装是实现CSS模块化的最基本要求,封装成的各个单元就是基本的CSS模块,可灵活用于组建页面的各种显示样式。

二、 继承

HTML代码

1
2
<div class=” module module-A module-A-a”></div>
<div class=” module module-A module-A-b”></div>

CSS代码

1
2
3
4
5
6
7
.module {.....}
.module-A {.....}
.module-A-a {.....}
.module-A-b {.....}
.module-B {.....}
.module-B-a {.....}
.module-B-b {.....}

继承可谓是CSS模块化的关键所在,由于html元素可以拥有多个类,而且根据优先级,后面定义的属性可以覆盖前面的,正因为这样,继承这个特性发 挥了巨大的作用。对于某些多数样式属性相同,仅有几个不同样式属性的定义,可以用这个方法来实现。也可以在不改变某个通用样式类的同时,用HTML调用复 合类,突出局部特例。

三、 多态

HTML代码

1
2
3
4
5
6
7
8
9
10
<div class=”module-A”></div>
<div class=”part-A ”>
<div class=”module-A”></div>
</div>
<div class=”part-B ”>
<div class=”module-A”></div>
</div>
<div class=”part-C ”>
<div class=”module-A”></div>
</div>

CSS代码

1
2
3
4
.module-A {.....}
.part-A .module-A {.....}
.part-B .module-A {.....}
.part-C .module-A {.....}

多态主要用于同一模块在页面的不同部分或者不同页面之间呈现出不同的样式。对于CSS的多态,一个很经典而且常用的例子就是导航栏。我们知道,导航 栏往往需要标识出当前页面所在的导航链接。也就是说,对于导航栏的链接,通常有两种形态,一种是常态,一种是高亮态,比如处于主页时,主页的链接就是高亮 态的,其他导航链接是常态的。这个时候,很多人喜欢在li上加上一个current类,用来把该导航链接设置为高亮态,但是我觉得这种方式并不理想。

为什么呢?因为对于结构一样的导航栏,后台人员在处理时,往往是抽出成一个公共结构,然后各个页面都引入这个结构。这对于后期的维护是相当有效的, 因为涉及导航栏的修改仅需修改一次即可,如果不这么做,那么修改的次数将会等于页面的个数,而且容易出错。对于这种情况,多态就可以很好地解决,因为我们 可以在每个页面的body(或者其他地方)加上一个类来标识不同的页面(此类可以不定义任何样式)。那么,根据多态的特性,我们就可以为不同页面的导航设 置不同的形态,同时又保持了导航链接的结构一致性。举例如下:

HTML代码

主页:

1
2
3
4
5
6
7
<body class=”index”>
  <ul class=”nav”>
<li class=”index”><a href=”#”>主页</a></li>
<li class=”page1”><a href=”#”>内页1</a></li>
<li class=”page2”><a href=”#”>内页2</a></li>
  </ul>
</body>

内页1:

1
2
3
4
5
6
7
<body class=”page1”>
  <ul class=”nav”>
<li class=”index”><a href=”#”>主页</a></li>
<li class=”page1”><a href=”#”>内页1</a></li>
<li class=”page2”><a href=”#”>内页2</a></li>
  </ul>
</body>

CSS代码

1
2
3
4
5
6
7
8
9
/*定义常态*/
.nav{.....}
.nav .index{.....}
.nav .page1{.....}
.nav .page2{.....}
/*定义高亮态*/
.index .nav .index{.....}
.page1 .nav .page1{.....}
.page2 .nav .page2{.....}

这个就是多态的经典应用之一。

补充部分

joe哥指正,以上的这种对导航的处理办法不太好,因为导航是一个公用组件,所谓公用,就是应该结构和样式都是公用的,上面的那种方法没有做到样式上公 用,因为很明显定义高亮态那里需要用到其他页面的样式类,而且joe哥提到可移植性的问题,如果这个导航搬到其他地方,那么就需要为新的页面的body全 部都添加一个类(这个我真没想过导航还可以给多个网站重用,我眼光太短浅了)。那么,究竟什么做才是比较主流的呢?加current,没错,就是加 current,这个被我一开始就否决的方法。那么又回到原来的问题,既然我们是引入同一个导航文件,那么current能加到哪里呢?joe哥提出一个 被我们都忽略了的方法,脚本!可以是js,可以是php,原来我们可以动态添加current类到导航去,惊讶吧!

好吧,我承认我有点过于兴奋了,大伙儿看例子吧~

HTML代码

1
2
3
4
5
<ul class=”nav”>
  <li class=”index” id="index"><a href=”#”>主页</a></li>
  <li class=”page1” id="page1"><a href=”#”>内页1</a></li>
  <li class=”page2” id="page2"><a href=”#”>内页2</a></li>
</ul>

CSS代码

1
2
3
4
5
6
7
/*定义导航的样式*/
.nav{.....}
.nav li.index{.....}
.nav li.page1{.....}
.nav li.page2{.....}
/*定义高亮态*/
.nav li.current{.....}

JS代码

1
2
3
4
function addCurrent(class,html_id){
  //class为增加的样式类名,html_id为需要增加样式类的html元素的id
  document.getElementById(html_id).addClass(class); //这里的class就是‘current’,addClass方法的实现我这里就不多说了,你可以用jquery或者别的,甚至自己写
}

这种做法对于不同的页面,或者新增的页面,只需改js的一个参数即可,做到了把导航部分真正实现模块化、组件化,公用的部分就应该公用到底,不留一 点余地。不过我还想说一点是,如果你的current(高亮态)不是单独的换个背景颜色之类的,而是用雪碧图这类的方法,每个导航链接的current类 都是不同的,那么以上的这种方法,貌似还有待改进。

补充部分结束

事实上应该指出,我这里讨论的只是CSS模块化的一部分,可以说是比较微观的一部分。还有一些对CSS进行比较宏观地划分模块的说法,比如按页面来划分,一个页面或者说一个区域为一个模块,比如像“幸福收藏夹”上所说的划分方法:

网站的划分标准更大一些,是以网站的专题为模块,不幸的是,很多专题的页面风格都是类似的,导致各个模块间存在大量的冗余代码,这意味着对样式的改动将会相当麻烦,一个地方的改动需要同时修改多个css文件。

表面上看,虽然对CSS模块划分得细是一个不错的想法,但并不是越细越好。现在的一些开源系统,如dedecms,甚至说YUI框架的1.0版本, 都流行一种做法,就是把CSS模块细分成单属性,比如把宽度960px定义为.w960,把清除浮动定义.clear,把字体绿色定义为.green等 等。

这样做的好处是可以对页面元素的样式进行快速组装,通过引入多个类便可以达到我们想要的效果。但是,这样的做法会导致另外一个问题。大家想,这么做 与内联样式有什么区别?如果有一天,我们想要把多个地方的字体颜色由绿色改为红色,那么我们要做的不是改动css的color属性,而是把这些html元 素的class都由green改为red。请注意,我们的初衷是改变的页面表现,但最终我们需要改变结构来达到我们的目的,这样就做不到结构与表现的分离 了。

究竟怎么样划分CSS模块,又怎么来用这些模块来组建页面元素才是合适,其实很难找到一个标准,这不仅需要结合具体的页面要求,还需要一定的经验

转载于:https://www.cnblogs.com/crab/archive/2012/09/27/2706424.html

[转载] CSS模块化【封装-继承-多态】相关推荐

  1. Java继承_Hachi君浅聊Java三大特性之 封装 继承 多态

    Hello,大家好~我是你们的Hachi君,一个来自某学院的资深java小白.最近利用暑假的时间,修得满腔java语言学习心得.今天小宇宙终于要爆发了,决定在知乎上来一场根本停不下来的Hachi君个人 ...

  2. python多态的三种表现形式_python小结----面向对象的三大特征(封装,继承,多态)

    面向对象的三大特征: 封装,继承,多态 面向对象的编程思想核心:高类聚,低耦合–程序的设计模式范畴 封装 什么是封装: 在面向对象编程的思想中,对代码进行高度封装,封装又叫包装 封装就是指将数据或者函 ...

  3. python 参数类型的多态_【Python】面向对象:类与对象\封装\继承\多态

    六.Python面向对象--类与对象\封装\继承\多态 1.什么是面向对象编程 1.1 程序设计的范式:程序可控,易于理解 1.2 抽象并建立对象模型 1.3 程序是不同对象相互调用的逻辑.每个对象在 ...

  4. python--编写程序:实现乐手弹奏乐器,乐手可以弹奏不同的乐器而发出不同的声音------使用类的封装继承多态的问题/使用面向对象的思想,设计自定义类,描述出租车和家用轿车的信息

    编写程序:实现乐手弹奏乐器,乐手可以弹奏不同的乐器而发出不同的声音 ------使用类的封装继承多态的问题 class Instrumnet():#乐器类def make_sound(self):pa ...

  5. c语言编程 菲薄拉,C语言设计模式-封装-继承-多态

    快过年了,手头的工作慢慢也就少了,所以,研究技术的时间就多了很多时间,前些天在CSDN一博客看到有大牛在讨论C的设计模式,正好看到了,我也有兴趣转发,修改,研究一下. 记得读大学的时候,老师就告诉我们 ...

  6. 大数据笔记8—java基础篇4(面向对象-封装-继承-多态)

    面向对象 一.面向对象 1.面向过程 1.2.举例 1.3.总结 二.面向对象 1.简述 2.举例 3.思想特点 2.1.类的定义格式 2.1.1.简述 2.2.2.格式 2.3.3.示例 三.类的使 ...

  7. 小白理解——封装继承多态

                                      一.封装 是什么:首先是抽象,把事物抽象成一个类,其次才是封装.对外表示为一个对象,隐藏对象的属性和动作实现的细节,仅对外公开接口. ...

  8. Day55-每日一道Java面试题-Java 面向对象编程三大特性: 封装 继承 多态

    Java 面向对象编程三大特性: 封装 继承 多态 封装 封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问.但是如果一个类没有 ...

  9. 面向对象 编程及面向对象三大属性:封装 继承 多态

    面向对象 面向对象(Object Oriented,OO)是软件开发方法.面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统.交互式界面.应用结构.应用平台.分布式系统.网络管理结构. ...

最新文章

  1. class没有发布到tomcat_SpringBoot内置tomcat启动原理
  2. python response.json()报错_python:解析requests返回的response(json格式)说明
  3. android如何使用ios14组件,ios14小组件怎么添加 苹果ios14小组件添加使用教程
  4. php伪静态教程,DedeCMS实现全站PHP伪静态
  5. oracle轮询方式循环输出,LGWR的两种模式(POST/WAIT和POLLING)
  6. jsf集成spring_Spring和JSF集成:导航
  7. 以太坊2.0合约质押新增4.23万ETH
  8. jsf取js变量_javascript中如何获取jsf后台数据?
  9. 手机APP ~ MUI——创建页面方法
  10. 微信小程序中如何应用音频
  11. java模拟器触屏_jar模拟器-jar模拟器触屏版电脑版下载_暂未上线|好特下载
  12. (C语言)教师信息管理系统
  13. JavaScript之多小球非对心弹性碰撞
  14. Restorator软件使exe文件都不能打开,任务管理器不支持此接口
  15. python怎么做表格_零基础小白怎么用Python做表格?
  16. Android电视机(机顶盒)初次开发的一些经验分享
  17. 史上最全报表教程,还不快收藏!
  18. FastDFS作者余庆谈真正的开源精神
  19. vim 录制宏,自动循环执行组合操作
  20. 【JavaWeb】1—JavaWeb概述

热门文章

  1. MyBatis复习笔记6:MyBatis缓存机制
  2. 指定服务器无效,安装sqlserver2008r2 服务器配置,服务帐户配置出错,提示Sql server服务指定的凭据无效...
  3. XML 解析XML文档 XML约束
  4. 操作系统导论部分章节习题
  5. vue打包后图片找不到情况
  6. Sql Server 因为触发器问题导致数据库更新报错“在触发器执行过程中引发了错误,批处理已中止”的问题处理...
  7. Nagios之事件处理
  8. CentOS7启动图形界面
  9. Linux下task_struct详解
  10. lombox的用法(省去了set/get/NoArgsConstructor/AllArgsConstructor)