童鞋们新年好,2012年只发了两篇水文,就这么过去了,实在汗颜。话说大家都转移阵地去微博和github讨论问题了,谁让iteye还不支持markdown呢
。
今天说说我不熟悉的领域CSS,因为手里的项目实在需要,所以最近花了不少精力在我有限的CSS知识范围内寻找解决方案,也经过和很多同事讨论碰撞,不如记录一下。
CSS也需要模块化
CSS也需要模块化,这个其实不需要说太多,大家也都是这么做的。在开发阶段css伴随这个各个模块存在。隐约记得还有不少关于面向对象CSS的讨论,也有Less和SASS这种加强CSS结构化的工具。
而在上线前往往需要将各处散落的CSS文件统一合并,或更智能的实时combo。所以今天讨论的CSSLoader是开发时使用。
CSS模块间存在依赖关系,但用JS模块管理方式一并管理不够恰当
CSS模块间存在依赖关系,常见的情况是所有css都依赖框架的reset.css,然后可能各个css也都依赖项目通用css如project.css。
但是用js模块管理方式来管理css模块是不够合适的,有以下一些问题:
1. 当前的JSLoader,往往只支持,一个js模块依赖若干css模块,并非真正的支持css间的依赖。
2. css文件内,不支持js语法,所以无法描述它的依赖。内置的@import有它的问题,稍后讲讲。
在讨论中,我们发现还是从CSS的特点出发,为它量身定制Loader解决方案为佳。
CSS特点是有层次,那么理想的项目CSS规划怎样
CSS的全称是层叠样式表,这其实说明了CSS的特点是有层次的,而这一点在JS中表现的并不明显,特别大家通过模块化屏蔽了全局变量相互覆盖带来的影响之后。
CSS的层次的特点是,下层的CSS规则,可以覆盖上层的CSS规则,所以我觉得网页理想的CSS规划是每一个CSS模块都能明确其所属层次。
这样的网页CSS层次如下图所示,这也是我们当前项目中的结构:
1. reset.css : 底层类库提供的通用
2. project.css :项目内通用的css,在我们的项目中可能存在其他项目的project.css,因为我希望不同项目中间的组件可以共享
3. widget.css :组件的通用css
4. widgetInstance.css :组件实例特有的css
可以看出在css分层次规划的背景下,css文件的依赖次序是固定的,4 -> 3 -> 2 -> 1 。 回过头来css的加载顺序应该是1、2、3、4,必须串行。
我们看到这样的规划下css模块是一棵树,如果projcet2.css依赖widget1-1.css显然是不合理的。而js的模块依赖是一张没有闭环即可的图(闭环==循环引用)。
简单总结下
理想的CSS规划策略:
1. 为网页的css划分层次,让每个css模块有明确的层次属性
2. 同一层次内的不同css模块,相互间不应该存在冲突的定义
3. 下层css模块只可以覆盖其所依赖的上层css模块中的部分规则
CSSLoader的要点
精确的的onload事件
我们必须保证上层css加载进来、规则完全应用好之后才能加载下层css。这样我们就需要一个精确的onload事件,在早期的getScript方法加载css文件时,只要把请求发了就立即触发onload,以草草达到和js模块一致的回调。而最近这方面的研究已经比较完善,kissy1.2以及seajs的很早的版本就支持真正的css文件onload回调。推荐seajs的做法,因为404时同样会触发回调。代码在这里
https://github.com/seajs/seajs/blob/master/src/util-fetch.js#L82,测试用例在这里
http://seajs.org/tests/issues/load-css/test.html,感谢玉伯。
我们注意到这里的css加载实现是动态构建link节点,但是在IE下有效的link节点有个数限制,所以方案并不完美。那么其实其他所有为页面引入css的方法都可以用,但前提是需要有靠谱的回调。甚至可以研究下,让css文件也能将载入和规则应用分离开的高级样式引入方式。
并发处理
一定存在同时初始化多个widget的情况,那么并发加载inst1-1-1和inst1-1-2时,要确保其共同的上层,如projcet1.css最先加载并且不能重复加载。在这一点上可以,参照JSLoader的实现模式,将已经载入的模块记录在案。这一点也引出了@import的问题,如果两个inst里边都写了@import project1.css,那么可能会出现inst1-1-1覆盖projcet1的规则又被覆盖回去的情况。
更进一步,当一个加载任务队列正在进行时,又开启了另一个加载任务队列,如果我们能按照css模块的层次顺序,将两个队列merge成一个队列再继续执行,看起来会更好些。
API示意
简单构想了一下扩展后的API,一串CSS加载任务发起还是由JS模块承担。
基于Kissy的话,需要add方法,为js模块增加cssRequires配置项,区别于requires,cssRequires数组内的文件需要按顺序串行加载,能够标识css模块的层次更好。
KISSY.add('mywidget',function(){
//...
},{
requires:['mod-a','mod-b'],
cssRequires:['reset.css:1','projcet.css:2','widget.css:3','instance.css:4']
});
在KISSY.use的时候原有逻辑负责js的加载,同时丢一个任务给新实现的cssLoader,去按层次加载css。
脆弱的方案
这绝对不是一个完美的解决方案,当前的实现方案基于“理想的CSS规划策略”,需要分层、同层次不冲突、仅向依赖的上层覆盖,这三点完全做到,而这里最大的挑战似乎是如何技术化的保障同一层次的css不会出现冲突。
在天然的浏览器环境没有很好的提供我们需要的feature时,等待它进化还是不现实的,很多时候就是靠我们能掌控全局这一优势,在不同环节各退一步,达成一个可以勉强运转体系。
好在这个方案是在开发时运转,而且明确的css规划也为真正线上产品的css打包或自动combo提供了便利。
简单发散一下
让层次描述更灵活
约定4个层次,还是太死板了,我们可以参照zIndex的设计,让层次数值之间存在大量空隙供扩展。
其他实现方案
可能有把css写在js里的方案,有基于less、sass扩展的方案,有开发时跑一个本地服务的方案(类似grunt)。这些都好,但对于如今我们手上的项目来说不够敏捷。其实没准有人已经实现过,欢迎知道的同学推荐。
最后
真的不太会CSS,如果有误请帮忙指出,如果有好的方案或者相关的研究都推荐过来吧,谢谢~
- 大小: 98.9 KB
分享到:
相关推荐
纯cssloader动画特效代码.rar
CSS设计大师设计思路与实践 CSS设计大师设计思路与实践
下面小编就为大家分享一篇vue2.0安装style/css loader的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
如何在vue-cli中使用css-loader实现css module 【前言】 无论是vue还是react的css模块化解决方案都是依赖loader来实现的 在使用上,vue中用scoped属性实现样式的私有化,利用深度作用选择器/deep来实现样式的去...
支持css文件在flex 程序运行时加载
html+css+js实现炫酷网页特效html+css+js实现炫酷网页特效html+css+js实现炫酷网页特效html+css+js实现炫酷网页特效html+css+js实现炫酷网页特效html+css+js实现炫酷网页特效html+css+js实现炫酷网页特效html+css+js...
css3实现loader加载指示器特效.zip
CSS3实现烟花特效-图片+css
InstaSynchP-CSSLoader 用于加载和卸载 CSS url 的框架插件框架cssLoader插件可用于添加和加载样式。 可以有多个样式共享一个<style>以便它们可以相互替换。 为此,样式的 id 必须相同。 默认情况下,样式的...
在React Webpack中,用来配合css-loader模块中的modules使用
高仿小米商城,纯HTML5和CSS3实现 高仿小米商城,纯HTML5和CSS3实现 高仿小米商城,纯HTML5和CSS3实现 高仿小米商城,纯HTML5和CSS3实现 高仿小米商城,纯HTML5和CSS3实现 高仿小米商城,纯HTML5和CSS3...
首先,您需要安装postcss-loader和postcss : npm install --save-dev postcss-loader postcss 然后将插件添加到您的webpack配置中。 例如: file.js import css from "file.css" ; webpack.config.js module ...
两款纯css3实现的动画菜单
HTML、CSS代码实现的发票样式的模板
css-loader是一款简单实用的纯css3 loader加载指示器特效。虽然使用gif图片可以很好的完成loader指示效果,但是使用css3来制作loader指示器,可以避免使用图片,也更容易定制,效果更酷。
消息列表向上滚动,不使用js操作,纯css3实现向上无缝滚动。
css动画的一个应用,与此前的css走马灯同样的内容。只是一次不同的应用,具体实现如下 序号 姓名 年龄 性别 专业 </ul>
纯CSS3实现百叶窗动画效果 纯CSS3实现百叶窗动画效果
CSS实现的实现简单目录树例子,可以为一些网页制作的同学借鉴一下。