原文链接:https://github.com/AlloyTeam/AlloyTouch/wiki/Scoped-CSS

写在前面

问:什么是Scoped CSS规范?

Scoped CSS规范是Web组件产生不污染其他组件,也不被其他组件污染的CSS规范。

面对组件化的普及,组件的复用很普遍的需求,然而CSS相互污染是经常遇见的问题,建立规范让开发者放心使用各种组件,甚至跨生态的组件是很有必要的一件事情。

目前业界的一些方案

方案一:

如果用webpack的话,可以参考css-loader的这个功能:

一段hash + 组件名,这个可能兼顾了辨识度 + 命名污染的问题。

方案二:

用webpack和scss,less写成模块化css就可以一定程度避免CSS污染,不能完全避免

方案三:样式规范上,使用与组件同名的嵌套命名空间

如果只用自己的生态可以这么搞,但是有的时候会引入第三方生态,第三方和自己的命名空间一样还是很有可能,比如scroller插件,社区里也有很多scroller插件loading uplader插件等等。

现有方案的局限性

这里还是会有污染的情况,因为:

  • 模块化的粒度是大于等于组件化粒度,意思就是一个模块可能有多个组件
  • 非less和sass项目下的组件怎么保证
  • 难以保证不污染第三方组件
  • 难以保证不被第三方组件污染
  • 同名组件的问题
  • 组件在第三方项目使用的问题
  • 组件自身生态闭环的问题

所以得出:

用意念或者规范约定不然注入程序自动化避免冲突

好处:

  • 能保证不污染别的组件并且不被被的组件污染可以更放心的复用
  • Scoped CSS规范是运行时产生唯一id~~ 永远不会css碰撞
  • 返回的这个id那个指定给组件的顶层div就行,实施简单

如果把这个过程放在构建过程就是工程问题。但是组件单独抽离出来给第三方用,其实就是组件本身的问题。总之要保证:

  • 不污染第三方的项目或组件
  • 不被第三组件或项目污染(由于是层叠样式,这个无法完全保证)

Scoped CSS代码

;(function () {

    function scoper(css) {
var id = generateID();
var prefix = "#" + id;
css = css.replace(/\/\*[\s\S]*?\*\//g, '');
var re = new RegExp("([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)", "g");
css = css.replace(re, function(g0, g1, g2) { if (g1.match(/^\s*(@media|@keyframes|to|from|@font-face)/)) {
return g1 + g2;
} if (g1.match(/:scope/)) {
g1 = g1.replace(/([^\s]*):scope/, function(h0, h1) {
if (h1 === "") {
return "> *";
} else {
return "> " + h1;
}
});
} g1 = g1.replace(/^(\s*)/, "$1" + prefix + " "); return g1 + g2;
}); addStyle(css,id+"-style");
return id;
} function generateID() { var id = ("scoped"+ Math.random()).replace("0.","");
if(document.getElementById(id)){
return generateID();
}else {
return id;
}
} var isIE = (function () { var undef,
v = 3,
div = document.createElement('div'),
all = div.getElementsByTagName('i'); while (
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
); return v > 4 ? v : undef; }()); function addStyle(cssText, id) {
var d = document,
someThingStyles = d.createElement('style');
d.getElementsByTagName('head')[0].appendChild(someThingStyles);
someThingStyles.setAttribute('type', 'text/css');
someThingStyles.setAttribute('id', id);
if (isIE) {
someThingStyles.styleSheet.cssText = cssText;
} else {
someThingStyles.textContent = cssText;
}
} window.scoper = scoper;
})();

Scoped CSS实施

var id = scoper("h1 {\
color:red;\
/*color: #0079ff;*/\
}\
\
/* h2 {\
color:green\
}*/");

scoper返回的id,在组件的JS里面赋给包裹的DOM便可以。这里详细说下生成id的过程:

function generateID() {
var id = ("scoped"+ Math.random()).replace("0.","");
if(document.getElementById(id)){
return generateID();
}else {
return id;
}
}

通过Math.random得到随机数并经过处理,然后通过document.getElementById去查询页面上有没有同名ID,有的话则继续重新生成,没有的话就使用当前id。这里需要特别注意的是,比如一些弹出层插件,display hide的时候有的组件是直接从body里面移除,所以这就带来了CSS碰撞的可能性,所以这里Scoped CSS 规范强行约定:后插入的HTML,一定要经过scoper过程重新生成唯一id。

最后,Scoped CSS规范已经在AlloyTouch插件里开始实施,并打算推广开来。

你有什么好的想法可以让跨生态跨项目跨技术栈的组件复用更加惬意,可以交流交流。

Scoped CSS规范草案的更多相关文章

  1. Atitit.css 规范 bem  项目中 CSS 的组织和管理

    Atitit.css 规范 bem  项目中 CSS 的组织和管理 1. 什么是BEM?1 1.1. 块(Block)2 1.2. 元素(Element)2 1.3. BEM树(和DOM树类似).3 ...

  2. 前端CSS规范整理_转载、、、

    一.文件规范 1.文件均归档至约定的目录中. 具体要求通过豆瓣的CSS规范进行讲解: 所有的CSS分为两大类:通用类和业务类.通用的CSS文件,放在如下目录中: 基本样式库 /css/core 通用U ...

  3. 瞬间从IT屌丝变大神——CSS规范

    CSS规范主要包括以下内容: CSS Reset用YUI的CSS Reset. CSS采用CSSReset+common.css+app.css的形式. app.css采用分工制,一个前端工程师负责一 ...

  4. [转]前端CSS规范整理

    一.文件规范 1.文件均归档至约定的目录中. 具体要求通过豆瓣的CSS规范进行讲解: 所有的CSS分为两大类:通用类和业务类.通用的CSS文件,放在如下目录中: 基本样式库 /css/core  通用 ...

  5. 新手不得不注意HTML CSS 规范

    作为一名新进的程序菜鸟,根本不知道从哪里开始学起好,前辈都说HTML CSS 规范是一个十分需要注意的点,要我记下,特地转来保存一下,大家相互学习 //总论 本规范既然一个开发规范,也是一个脚本语言参 ...

  6. 前端CSS规范大全

    一.文件规范 1.文件均归档至约定的目录中(具体要求以豆瓣的CSS规范为例进行讲解): 所有的CSS分为两大类:通用类和业务类.通用的CSS文件,放在如下目录中: 基本样式库 /css/core 通用 ...

  7. Web前端开发中的各种CSS规范

    Reference: http://yusi123.com/2866.html 一.文件规范 1.文件均归档至约定的目录中(具体要求以豆瓣的CSS规范为例进行讲解): 所有的CSS分为两大类:通用类和 ...

  8. 前端开发规范:命名规范、html 规范、css 规范、js 规范

    上周小组的培训内容是代码可读性艺术,主要分享如何命名.如何优化代码排版,如何写好的注释.我们都知道写出优雅的代码是成为大牛的必经之路. 下面感谢一位前端开发小伙伴总结的前端开发规范,通过学习相关开发规 ...

  9. Vue中scoped css和css module比较

    scoped css 官方文档 scoped css可以直接在能跑起来的vue项目中使用. 使用方法: <style scoped> h1 { color: #f00; } </st ...

随机推荐

  1. Form 表单提交参数

    今天因为要额外提交参数数组性的参数给form传到后台而苦恼了半天,结果发现,只需要在form表单对应的字段html空间中定义name = 后台参数名 的属性就ok了. 后台本来是只有模型参数的,但是后 ...

  2. DB2重启数据库实例

    DB2重启数据库实例时,有时停止实例会失败,此时需要先确认没有应用链接数据库,然后再关闭数据库实例,并重新启动. 1.查看是否有活动的链接 命令:db2 list applications for d ...

  3. Apache2.4:AH01630 client denied by server configuration

    问题说明:Apache服务总共有4个,是为了防止单点故障和负载均衡,负载均衡控制由局方的F5提供. 访问的内容在NAS存储上,现象是直接访问每个apache的服务内容都是没有问题,但是从负载地址过来的 ...

  4. Java版本:识别Json字符串并分隔成Map集合

    前言: 最近又看了点Java的知识,于是想着把CYQ.Data V5迁移到Java版本. 过程发现坑很多,理论上看大部分很相似,实践上代码写起来发现大部分都要重新思考方案. 遇到的C#转Java的一些 ...

  5. HBase笔记:对HBase原理的简单理解

    早些时候学习hadoop的技术,我一直对里面两项技术倍感困惑,一个是zookeeper,一个就是Hbase了.现在有机会专职做大数据相关的项目,终于看到了HBase实战的项目,也因此有机会搞懂Hbas ...

  6. SQL开发技巧(二)

    本系列文章旨在收集在开发过程中遇到的一些常用的SQL语句,然后整理归档,本系列文章基于SQLServer系列,且版本为SQLServer2005及以上-- 文章系列目录 SQL开发技巧(一) SQL开 ...

  7. StringBuffer 的 各种方法

    StringBuffer 其实提供了很多有用的方法, 以前用的多是 append, 其实还有: append(double) delete(int, int) deleteCharAt(int) re ...

  8. VS2013默认打开HTML文件没有设计视图的解决办法

    VS菜单->工具->选项->文本编辑器->文件扩展名,右侧输入html,再下拉列表选HTML(Web窗体)编辑器,点添加,确定. 重新打开html文件,就出现“设计”视图了

  9. BVT & BAT (版本验证测试和版本验收测试)

    BVT & BAT 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.BVT: (Build Verification Test ) BVT的概念: BVT(版本验证测试)是在所有开发 ...

  10. Memcached和Redis比较

    一.存储 Memcached基本只支持简单的key-value存储方式.Redis除key-value之外,还支持list,set,sorted set,hash等数据结构:Redis支持数据的备份, ...