如何避免模块间的 CSS 冲突

问题

在最近的推荐模块改版中,遇到了一个模块之间的样式冲突问题,特在这里记录一下自己的心得。
那是一个阳光明媚的下午,我像往常一样在工位上写代码,窗外的麻雀在电线杆上多嘴。这一天,仿佛将会像往日一样平静地过去。
突然,我的聊天工具惨叫一声:“叮咚!”是测试同学发来的消息,我知道,这一切没有想象中那么简单。 屏幕中浮现出15个黑色的小字:推荐模块样式有问题。
“怎么可能?我明明仔细测试过了,不应该啊…… 不行,他一定是在骗我。”那一刻我的内心几乎是崩溃的,我开始自怨自艾,想逃离这种喧嚣,可是,责任告诉我,我不能就这么坐着什么也不做,于是我立即把状态设为隐身。

原因

事件的起因就是推荐模块的图标样式被页面的另一个模块覆写了,添加了 padding-left: 20px; 所用的图标 class 为 icon

另一个模块定义了 .icon 样式

仔细一看,原来是收藏夹页面的基础样式,看来是自己对页面样式环境不熟悉所致。顺便,我又查看了另一个页面,发现也有类似css样式

可想而知,如果以后要在其他页面编写区块,还会遇到这种问题。

对应页面的前端同学告诉我,你起的class名字太简单大众了,难怪会起冲突,需要加上前缀啊混蛋。

想想也不是没有道理,这样是可以在一定程度上解决这类问题,不过我还是有一些疑惑,既然这些各页面的基础样式也不是通用的,而且还有差异,为什么不充分利用派生选择器添加命名空间或者添加前缀呢?这样带来的问题就是每个区块开发者都要事先看一遍页面的基础样式,发现潜在的冲突,或者不看,测试的时候让测试同学帮忙看,或者所有class添加前缀,显得冗余。

如何解决这类问题?

我觉得多人协作页面开发还是应该遵循一些css规范,比如:

  1. 首先不能影响别人

    1. 对于模块开发者,他不需要关心除了全局样式框架之外的任何 class 冲突问题,模块的样式都是在顶部模块class基础上派生,这也保证了不会影响其他模块

    2. 对于样式框架开发者(或者各页面的base.css),你可以定义样式模型,但你必须考虑到模型内部可能会嵌套他人的模块,因此模型以及模型内部元素class必须带上完整的层次结构,例如:

1
2
3
4
.module-a {}
.module-a-head {}
.module-a-body {}
.module-a-body-xx {}

如某网站头部的html结构

这样既保证了不会影响内部模块,也不会被内部模块的派生式样式所影响。虽然这样带来了一定的html代码量增加,不过却是值得的,因为你没办法保证模型内部不会出现class为head的元素,所以你不能像模块开发者一样使用:

1
2
3
.module-a {
.head {}
}

如果需要继承某个样式模型,可以使用覆盖式class扩展的方式,例如:

1
<div class="module-a module-a-can_fly"></div>
1
.module-a-can_fly { /* 我是覆盖样式,只有帅气的人才看得到 */ }

这保留了元素的类型信息,便于脚本操作。

  1. 不能被别人影响

    1. 模块开发者需要 reset 可继承样式,例如 text-align, line-height, color 等,不然当区块被引入到另外的页面时,结果可能不是你想要的。

    2. 如果页面未遵循第一条第二点,那么你应该那么做。

说的不对的地方请大大们指出 :)