CSS也有作用域?—"css-modules"说它为什么要这么做!

把问题的结论放在开头,关于我的故事,感兴趣的同学或者觉得会对自己有帮助的同学慢慢欣赏吧,这样可以节省另外部分同学的时间。

1. css-modules是什么?

css-modules是将css赋予作用域概念的一种样式模块化解决方案。通过给样式名加hash字符串后缀的方式,实现特定作用域语境中的样式编译后的样式在全局唯一。

2. css-modules解决了什么问题?

当项目经由多位技术背景和水平参差不齐的开发者接手过后,项目的样式已经不能乖乖的被后面的同学搞了,不断的重构重构重构...... 嗯,是时候要有人拿小皮鞭来规范开发秩序了。css-modules的出现解决了全局样式污染,庞大的页面dom节点取名字的问题。

3. css-modules的科学实践

组件容器内样式作用域弱约束,页面区域间作用域强隔离。
例如页面结构为 header、main、aside、footer 这四个区域。header和aside共同使用了Navbar组件,Navbar的组件是复用了,样式一致,但是在header和aside中要有两种视觉效果。这时候把header和aside可以分别看做Navbar的两个实例容器,header和aside是用css-module管理的local作用域,在他们的local作用域中声明一个global作用域,通过.header :global .nav-bar{...}的方式覆写组件样式,实现同一组件在同一页面不同区域的样式自定义。

4. 对css-modules出现背景所做的反思

css对于专业前端来说是很熟悉的,通过命名前缀,结构化命名来描述页面结构。但这些都是人为经验去做的代码管理,在团队开发资源紧张的情况下,很多不熟悉css的后端同学也需要尽快完成前端的任务,导致大量的样式冲突和冗余。于是乎,标准化组件给大家更少的选择,更少的关注css...

当然以上是出于许许多多后端、客户端发者对web前端的理解基础上给出的解决方案。语言之间的思想是会互相影响的,就那这个模块化的方案结合es6来说,我感觉就很像python了。

下面是关于我对css-modules使用经历的小故事:

不久前换了工作,开始使用React来开发web。早先就听闻过React的大名,之前的工作是团队中就我一只前端,考虑到效率问题,工作中一直在用Angular 1.X 来霸道的进行开发,功能大而全,即使是一个人来同时做前后端,也可以很快的开发出可维护性的系统。那么现在开始用了React,初次的开发体验我选择了"ant-design"。

根据ant-design的快速上手教程,我搭建起来一个初始化的项目结构。但是当我需要按照设计图去还原视觉效果的时候,我懵逼了。jsx的语法,加上模块化的React组件,在开发界面功能的时候很方便,有种类似客户端的控件引入方式。不过在我需要按照视觉设计图去覆写组件样式的时候,我发现竟然没有对应的css样式!

经过调试发现,项目结构中引入了css-modules,在浏览器的开发者工具中会看到,页面中节点的className被加上了hash字符串,这也就意味着css有了作用域的概念。后来查css-modules的文档,如果是全局作用域的样式需要在样式前面包一层 :global,代码如下:

:global {  
  html, body, #root {    
    height: 100%;  
  }    
  body { background: #fafafa; }
}

在没有:global包裹的样式,编译后的结果是一下这种:
MainLayout.less

.main{...}

index.html

<div id="root">
  <div class="main"></div>
</div>

编译后的index.html

<div id="root">
  <div class="main___1gjAI"></div>
</div>

MainLayout.jsx

import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { DatePicker, message } from 'antd';
import styles from './MainLayout.less';

ReactDOM.render(
  <div className={styles.main}>
    <DatePicker onChange={value => this.handleChange(value)} />
  </div>, 
  document.getElementById('root')
);

这里想要让css样式生效,必须在对应的节点使用 "module.style"(模
块.样式属性)的方式绑定样式。这里就没办法通过外部容器的选择器来定位组件节点了。因为组件是在自定义渲染部分引入使用,组件节点是自动渲染的,如果组件没有开放子节点的className字段,是无法修改组件样式的。

不过,如果在组件没有使用css-modules的情况下,我们可以通过在页面节点-组件容器的css作用域来创建一个组件容器的全局作用域(该作用域存在于页面节点的local作用域内,页面其他区域的css作用域是隔离的),代码如下:

.main{
  :global{
    .ant-calendar-picker{
      /*这里可以覆写 DatePicker组件的样式了*/
    }  
  }
}

在经过一阵惊讶和反思后,结合我之前的工作经历不禁开始赞叹css-modules的牛逼。
说他牛逼并不是因为他在技术上的实现有多么复杂,而是他可以让项目的不确定性大大降低,代码的可维护性得以提升。

以前也跟朋友吐槽过,相信前端同学有的也有过这样的经历,入职后发现自己是唯一的前端,而且接手的项目之前是后台的同学开发的。素质高点的js不会乱引的太严重,然而大多数后台的同学是不熟悉css的,样式不仅冗余,而且很多因为优先级而相互覆盖的问题。

换个角度想想就发现了css-modules的价值,就是tmd让不熟css的同学乖乖的不要给人家挖坑。如果说真的需要接手这类的项目,即便是损失了css的灵活性,我也是会开心的笑出眼泪吧(毕竟比反复重构人家写的页面要好很多)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 最近学习到CSS的继承属性,正好看到这篇文章,便将它翻译出来。作者的思想,在平时的项目中或多或少都有用过,但是从来...
    hershin阅读 928评论 0 1
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,398评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 有一段时间很极端,觉得不应该随便给人贴标签,尤其爱说,不要给孩子随便贴标签。 随着认知的变化,更加理性。 家长不给...
    信时光阅读 150评论 0 0
  • 夜色温柔,是在一个人内心温柔,感动了自己,用无限柔情和宽容去看待周围的一切的时候。 它也许是晚归时,公交车窗外滑过...
    会游走的鱼阅读 836评论 0 0