您的位置:时时app平台注册网站 > web前端 > CSS Modules 详解及 React 中实践彩世界网址

CSS Modules 详解及 React 中实践彩世界网址

2019-10-11 04:47

写在前面

读文先看此图,能先有个差不离概念:

彩世界网址 1

读书本文须求 11m 24s。

零、示例库

本身为这些科目写了一个示例库,富含五个德姆o。通过它们,你能够轻巧学会CSS Modules。

先是,克隆示例库。

JavaScript

$ git clone

1
$ git clone https://github.com/ruanyf/css-modules-demos.git

然后,安装信任。

JavaScript

$ cd css-modules-demos $ npm install

1
2
$ cd css-modules-demos
$ npm install

继之,就能够运转第4个示范了。

JavaScript

$ npm run demo01

1
$ npm run demo01

开荒浏览器,访谈

CSS Modules 结合 React 实践

className 处直接使用 css 中 class 名即可。

JavaScript

.root {} .confirm {} .disabledConfirm {}

1
2
3
.root {}
.confirm {}
.disabledConfirm {}

import classNames from 'classnames'; import styles from './dialog.css'; export default class Dialog extends React.Component { render() { const cx = classNames({ confirm: !this.state.disabled, disabledConfirm: this.state.disabled }); return <div className={styles.root}> <a className={styles.disabledConfirm}>Confirm</a> ... </div> } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import classNames from 'classnames';
import styles from './dialog.css';
 
export default class Dialog extends React.Component {
  render() {
    const cx = classNames({
      confirm: !this.state.disabled,
      disabledConfirm: this.state.disabled
    });
 
    return <div className={styles.root}>
      <a className={styles.disabledConfirm}>Confirm</a>
      ...
    </div>
  }
}

小心,常常把组件最外层节点对应的 class 名为 root。这里运用了 [classnames](https://www.npmjs.com/package/classnames) 库来操作 class 名。

一旦你不想频仍的输入 styles.**,能够试一下 [react-css-modules](gajus/react-css-modules · GitHub),它经过高阶函数的样式来防止再一次输入 styles.**

CSS Modules 结合历史遗留项目施行

好的技艺方案除了作用强盛炫酷,还要能不负众望现成项目能平滑迁移。CSS Modules 在这里一点上显示的特别灵活。

表面怎么样覆盖局地样式

当生成混淆的 class 名后,能够化解命名冲突,但因为不可能预言最后 class 名,无法经过平时选取器覆盖。大家今天项目中的施行是能够给组件关键节点加上 data-role 属性,然后通过品质选取器来覆盖样式。

// dialog.js return <div className={styles.root} data-role='dialog-root'> <a className={styles.disabledConfirm} data-role='dialog-confirm-btn'>Confirm</a> ... </div>

1
2
3
4
5
// dialog.js
  return <div className={styles.root} data-role='dialog-root'>
      <a className={styles.disabledConfirm} data-role='dialog-confirm-btn'>Confirm</a>
      ...
  </div>

 

JavaScript

/* dialog.css */ [data-role="dialog-root"] { // override style }

1
2
3
4
/* dialog.css */
[data-role="dialog-root"] {
  // override style
}

因为 CSS Modules 只会变动类选取器,所以这里的性质采用器无需增添 :global

怎么与全局样式共存

前边三个项目不可幸免会引进 normalize.css 或别的一类全局 css 文件。使用 Webpack 能够让全局样式和 CSS Modules 的部分样式和睦共存。上边是大家项目中应用的 webpack 部总局署代码:

JavaScript

小说权归笔者全体。 商业转发请联系小编得到授权,非商业转发请注解出处。 笔者:camsong 链接: 来源:知乎 // webpack.config.js 局部 module: { loaders: [{ test: /.jsx?$/, loader: 'babel' }, { test: /.scss$/, exclude: path.resolve(__dirname, 'src/styles'), loader: 'style!css?modules&localIdentName=[name]__[local]!sass?sourceMap=true' }, { test: /.scss$/, include: path.resolve(__dirname, 'src/styles'), loader: 'style!css!sass?sourceMap=true' }] }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:camsong
链接:http://zhuanlan.zhihu.com/purerender/20495964
来源:知乎
 
// webpack.config.js 局部
module: {
  loaders: [{
    test: /.jsx?$/,
    loader: 'babel'
  }, {
    test: /.scss$/,
    exclude: path.resolve(__dirname, 'src/styles'),
    loader: 'style!css?modules&localIdentName=[name]__[local]!sass?sourceMap=true'
  }, {
    test: /.scss$/,
    include: path.resolve(__dirname, 'src/styles'),
    loader: 'style!css!sass?sourceMap=true'
  }]
}

JavaScript

/* src/app.js */ import './styles/app.scss'; import Component from './view/Component' /* src/views/Component.js */ // 以下为组件相关样式 import './Component.scss';

1
2
3
4
5
6
7
/* src/app.js */
import './styles/app.scss';
import Component from './view/Component'
 
/* src/views/Component.js */
// 以下为组件相关样式
import './Component.scss';

目录结构如下:

JavaScript

src ├── app.js ├── styles │ ├── app.scss │ └── normalize.scss └── views ├── Component.js └── Component.scss

1
2
3
4
5
6
7
8
src
├── app.js
├── styles
│   ├── app.scss
│   └── normalize.scss
└── views
    ├── Component.js
    └── Component.scss

那般有着全局的体制都放到 src/styles/app.scss 中引进就能够了。另外具备目录富含 src/views 中的样式都以一些的。

CSS 命名约定

规范化CSS的模块搞定决方案(比方BEM BEM — Block Element Modifier,OOCSS,AMCSS,SMACSS,SUITCSS)
但存在以下难题:
* JS CSS之间依然未有打通变量和选择器等
* 复杂的命名

CSS Modules 用法教程

2016/06/19 · CSS · Modules

初藳出处: 阮一峰   

学过网页开垦就能掌握,CSS 无法算编制程序语言,只是网页样式的一种描述方法。

为了让 CSS 也能适用软件工程措施,程序猿想了各类法子,让它变得像一门编制程序语言。从最先的Less、SASS,到后来的 PostCSS,再到近期的 CSS in JS,皆感觉着化解那几个标题。

彩世界网址 2

正文介绍的 CSS Modules 有所差异。它不是将 CSS 改形成编制程序语言,而是功用很单纯,只参与了一些效率域和模块正视,那恰好是网页组件最亟需的效应。

因此,CSS Modules 很容易学,因为它的法则少,相同的时间又丰富有用,能够确定保障某些组件的体制,不会影响到别的零件。

彩世界网址 3

CSS Modules 模块化方案

彩世界网址 4

CSS Modules 内部通过 [ICSS](css-modules/icss · GitHub) 来化解体制导入和导出那四个难点。分别对应 :import:export 五个新添的伪类。

JavaScript

:import("path/to/dep.css") { localAlias: keyFromDep; /* ... */ } :export { exportedKey: exportedValue; /* ... */ }

1
2
3
4
5
6
7
8
:import("path/to/dep.css") {
  localAlias: keyFromDep;
  /* ... */
}
:export {
  exportedKey: exportedValue;
  /* ... */
}

 

但直接行使那七个关键字编制程序太难为,实际项目中比非常少会直接使用它们,大家需求的是用 JS 来管理 CSS 的力量。结合 Webpack 的 css-loader 后,就足以在 CSS 中定义样式,在 JS 中程导弹入。
启用 CSS Modules

JavaScript

// webpack.config.js css?modules&localIdentName=[name]__[local]-[hash:base64:5]

1
2
// webpack.config.js
css?modules&localIdentName=[name]__[local]-[hash:base64:5]

加上 modules 即为启用,localIdentName 是设置生成样式的命名准绳。

JavaScript

/* components/Button.css */ .normal { /* normal 相关的具有样式 */ } .disabled { /* disabled 相关的有所样式 */ }

1
2
3
/* components/Button.css */
.normal { /* normal 相关的所有样式 */ }
.disabled { /* disabled 相关的所有样式 */ }

JavaScript

// components/Button.js import styles from './Button.css'; console.log(styles); buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

1
2
3
4
// components/Button.js
import styles from './Button.css';
console.log(styles);
buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

生成的 HTML 是

<button class="button--normal-abc53">Submit</button>

1
<button class="button--normal-abc53">Submit</button>

 

注意到 button--normal-abc53 是 CSS Modules 按照 localIdentName 自动生成的 class 名。在那之中的 abc53 是依据给定算法生成的种类码。经过这么模糊管理后,class 名基本正是独一的,大大收缩了档期的顺序中样式覆盖的概率。同期在生育遭受下修改法则,生成越来越短的 class 名,能够增加 CSS 的压缩率。

上例中 console 打字与印刷的结果是:

JavaScript

Object { normal: 'button--normal-abc53', disabled: 'button--disabled-def886', }

1
2
3
4
Object {
  normal: 'button--normal-abc53',
  disabled: 'button--disabled-def886',
}

CSS Modules 对 CSS 中的 class 名都做了拍卖,使用对象来保存原 class 和混淆后 class 的对应关系。

透过那些总结的管理,CSS Modules 达成了以下几点:

  • 具有样式都以 local 的,消除了命名冲突和大局污染难题
  • class 名生成准绳配置灵活,能够此来减弱 class 名
  • 只需援用组件的 JS 就能够消除组件全数的 JS 和 CSS
  • 依然是 CSS,大概 0 学习开支

体制暗许局部

使用了 CSS Modules 后,就一定于给每一个 class 名外加加了叁个 :local,以此来贯彻样式的局地化,假如您想切换成全局格局,使用相应的 :global

:local:global 的界别是 CSS Modules 只会对 :local 块的 class 样式做 localIdentName 准则管理,:global 的样式编写翻译后不改变。

JavaScript

.normal { color: green; } /* 以上与下部等价 */ :local(.normal) { color: green; } /* 定义全局样式 */ :global(.btn) { color: red; } /* 定义七个全局样式 */ :global { .link { color: green; } .box { color: yellow; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.normal {
  color: green;
}
 
/* 以上与下面等价 */
:local(.normal) {
  color: green;
}
 
/* 定义全局样式 */
:global(.btn) {
  color: red;
}
 
/* 定义多个全局样式 */
:global {
  .link {
    color: green;
  }
  .box {
    color: yellow;
  }
}

Compose 来整合样式

对此样式复用,CSS Modules 只提供了唯一的诀要来管理:composes 组合

JavaScript

/* components/Button.css */ .base { /* 全体通用的体裁 */ } .normal { composes: base; /* normal 另外样式 */ } .disabled { composes: base; /* disabled 别的样式 */ }

1
2
3
4
5
6
7
8
9
10
11
12
/* components/Button.css */
.base { /* 所有通用的样式 */ }
 
.normal {
  composes: base;
  /* normal 其它样式 */
}
 
.disabled {
  composes: base;
  /* disabled 其它样式 */
}

JavaScript

import styles from './Button.css'; buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

1
2
3
import styles from './Button.css';
 
buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

生成的 HTML 变为

<button class="button--base-fec26 button--normal-abc53">Submit</button>

1
<button class="button--base-fec26 button--normal-abc53">Submit</button>

由于在 .normal 中 composes 了 .base,编写翻译后会 normal 会造成五个class。

composes 还是能够整合外界文件中的样式。

JavaScript

/* settings.css */ .primary-color { color: #f40; } /* components/Button.css */ .base { /* 全体通用的体裁 */ } .primary { composes: base; composes: primary-color from './settings.css'; /* primary 另外样式 */ }

1
2
3
4
5
6
7
8
9
10
11
12
13
/* settings.css */
.primary-color {
  color: #f40;
}
 
/* components/Button.css */
.base { /* 所有通用的样式 */ }
 
.primary {
  composes: base;
  composes: primary-color from './settings.css';
  /* primary 其它样式 */
}

 

对此超越四分之二品类,有了 composes 后曾经不复供给Sass/Less/PostCSS。但一旦你想用的话,由于 composes 不是正经的 CSS 语法,编写翻译时会报错。就只可以选拔预管理器自个儿的语法来做样式复用了。
class 命名本事

CSS Modules 的命名规范是从 BEM 扩张而来。BEM 把体制名分为 3 个品级,分别是:

  • Block:对应模块名,如 Dialog
  • Element:对应模块中的节点名 Confirm Button
  • Modifier:对应节点相关的意况,如 disabled、highlight

综上,BEM 最后收获的 class 名字为 dialog__confirm-button--highlight。使用双标识 __-- 是为了和区块内单词间的相间符区分开来。固然看起来有个别离奇,但 BEM 被百般多的大型项目和集体利用。大家施行下来也很承认这种命名方式。

CSS Modules 中 CSS 文件名正要对应 Block 名,只要求再思索 Element 和 Modifier。BEM 对应到 CSS Modules 的做法是:

JavaScript

/* .dialog.css */ .ConfirmButton--disabled { /* ... */ }

1
2
3
4
/* .dialog.css */
.ConfirmButton--disabled {
  /* ... */
}

您也能够不依据完全的命名标准,使用 camelCase 的写法把 Block 和 Modifier 放到一同:

JavaScript

/* .dialog.css */ .disabledConfirmButton { }

1
2
3
/* .dialog.css */
.disabledConfirmButton {
}

如何贯彻CSS,JS变量分享

注:CSS Modules 中向来不改变量的概念,这里的 CSS 变量指的是 Sass 中的变量。

下面提到的 :export 关键字可以把 CSS 中的 变量输出到 JS 中。上边演示如何在 JS 中读取 Sass 变量:

JavaScript

/* config.scss */ $primary-color: #f40; :export { primaryColor: $primary-color; }

1
2
3
4
5
6
/* config.scss */
$primary-color: #f40;
 
:export {
  primaryColor: $primary-color;
}

 

JavaScript

/* app.js */ import style from 'config.scss'; // 会输出 #F40 console.log(style.primaryColor);

1
2
3
4
5
/* app.js */
import style from 'config.scss';
 
// 会输出 #F40
console.log(style.primaryColor);

JS CSS不能分享变量

复杂组件要动用 JS 和 CSS 来共同管理体制,就能产生有个别变量在 JS 和 CSS 中冗余,CSS预管理器/后甩卖器 等都不提供跨 JS 和 CSS 分享变量这种力量。

四、 Class 的组合

在 CSS Modules 中,三个采纳器能够连续另一个采用器的条条框框,这称之为”组合”(“composition”)。

在App.css中,让.title继承.className 。

JavaScript

.className { background-color: blue; } .title { composes: className; color: red; }

1
2
3
4
5
6
7
8
.className {
  background-color: blue;
}
 
.title {
  composes: className;
  color: red;
}

App.js不要修改。

JavaScript

import React from 'react'; import style from './App.css'; export default () => { return ( <h1 className={style.title}> Hello World </h1> ); };

1
2
3
4
5
6
7
8
9
10
import React from 'react';
import style from './App.css';
 
export default () => {
  return (
    <h1 className={style.title}>
      Hello World
    </h1>
  );
};

运转那几个示例。

JavaScript

$ npm run demo04

1
$ npm run demo04

打开

App.css编写翻译成下边包车型地铁代码。

JavaScript

._2DHwuiHWMnKTOYG45T0x34 { color: red; } ._10B-buq6_BEOTOl9urIjf8 { background-color: blue; }

1
2
3
4
5
6
7
._2DHwuiHWMnKTOYG45T0x34 {
  color: red;
}
 
._10B-buq6_BEOTOl9urIjf8 {
  background-color: blue;
}

对应地, h1的class也会编写翻译成<h1 class=”_2DHwuiHWMnKTOYG45T0x34 _10B-buq6_BEOTOl9urIjf8″>。

CSS Modules 详解及 React 中实践

2016/01/18 · CSS · CSS Modules, React

原来的书文出处: pure render - camsong   

彩世界网址 5

CSS 是前边一个领域中发展最慢的一块。由于 ES2016/二零一四 的高效广泛和 Babel/Webpack 等工具的迅猛发展,CSS 被远远甩在了后边,慢慢造成大型项目工程化的痛点。也变为了前面一个走向绝望模块化前必需消除的难点。

CSS 模块化的设计方案有那三个,但要害有两类。一类是根本放弃 CSS,使用 JS 或 JSON 来写样式。Radium,jsxstyle,react-style 属于这一类。优点是能给 CSS 提供 JS 同样强盛的模块化技术;劣点是不能够应用成熟的 CSS 预管理器(或后Computer) Sass/Less/PostCSS,:hover:active 伪类处理起来复杂。另一类是照旧使用 CSS,但使用 JS 来保管体制信任,代表是 CSS Modules。CSS Modules 能最大化地整合现成 CSS 生态和 JS 模块化技巧,API 简洁到差少之甚少零学习开支。发表时依旧编写翻译出单身的 JS 和 CSS。它并不依据于 React,只要你使用 Webpack,能够在 Vue/Angular/jQuery 中央银行使。是自己觉妥善前最棒的 CSS 模块消除决方案。近年来在档案的次序中山高校量使用,上面具体享受下实践中的细节和想方设法。

 

启用 CSS Modules

JavaScript

// webpack.config.js css?modules&localIdentName=[name]__[local]-[hash:base64:5]

1
2
// webpack.config.js
css?modules&localIdentName=[name]__[local]-[hash:base64:5]

加上 modules 即为启用,localIdentName 是安装生成样式的命名准则。

CSS

/* components/Button.css */ .normal { /* normal 相关的全数样式 */ }

1
2
/* components/Button.css */
.normal { /* normal 相关的所有样式 */ }

JavaScript

// components/Button.js import styles from './Button.css'; console.log(styles); buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

1
2
3
4
// components/Button.js
import styles from './Button.css';
console.log(styles);
buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`

生成的 HTML 是

XHTML

<button class="button--normal-abc53">Submit</button>

1
<button class="button--normal-abc53">Submit</button>

注意到 button--normal-abc53 是 CSS Modules 按照 localIdentName 自动生成的 class 名。在那之中的abc53 是依据给定算法生成的种类码。经过如此模糊管理后,class 名基本正是举世无双的,大大裁减了花色中样式覆盖的可能率。同一时候在生养条件下修改准则,生成更加短的 class 名,能够压实 CSS 的压缩率。

上例中 console 打字与印刷的结果是:

CSS

Object {   normal: 'button--normal-abc53',   disabled: 'button--disabled-def886', }

1
2
3
4
Object {
  normal: 'button--normal-abc53',
  disabled: 'button--disabled-def886',
}

CSS Modules 对 CSS 中的 class 名都做了处理,使用对象来保存原 class 和歪曲后 class 的应和关系。

通过这么些轻巧的拍卖,CSS Modules 完结了以下几点:
* 全数样式都是局地效率域 的,化解了全局污染难题
* class 名生成法则配置灵活,能够此来减弱 class 名
* 只需援引组件的 JS 就会消除组件全数的 JS 和 CSS
* 依旧是 CSS,差十分少 0 学习花费

三、定制哈希类名

css-loader私下认可的哈希算法是[hash:base64],这会将.title编译成._3zyde4l1yATCOkgn-DBWEL那样的字符串。

webpack.config.js在那之中能够定制哈希字符串的格式。

JavaScript

module: { loaders: [ // ... { test: /.css$/, loader: "style-loader!css-loader?modules&localIdentName=[path][name]---[local]---[hash:base64:5]" }, ] }

1
2
3
4
5
6
7
8
9
module: {
  loaders: [
    // ...
    {
      test: /.css$/,
      loader: "style-loader!css-loader?modules&amp;localIdentName=[path][name]---[local]---[hash:base64:5]"
    },
  ]
}

运营这么些示例。

JavaScript

$ npm run demo03

1
$ npm run demo03

你会发现.title被编写翻译成了demo03-components-App—title—GpMto。

CSS Modules 使用技能

CSS Modules 是对现存的 CSS 做减法。为了追求**简短可控**,小编提出根据如下原则:

  • 不应用选用器,只行使 class 名来定义样式
  • 不层叠多少个 class,只行使贰个 class 把持有样式定义好
  • 不嵌套
  • 使用 composes 组合来贯彻复用

地方两条标准约等于减弱了体制中最灵敏的有个别,初使用者很难接受。第一条实施起来难度相当小,但第二条如若模块状态过多时,class 数量将倍加上升。

无可置疑要知道,上边之所以称为提出,是因为 CSS Modules 并不强制你确定要这么做。听起来有一点点水火不容,由于多数 CSS 项目设有深厚的野史遗留难题,过多的限定就表示增添迁移成本和与外界合营的本金。早期使用中势一定要有的低头。幸运的是,CSS Modules 那一点做的很好:

1. 只要作者对二个因素采取多少个 class 呢?

没难题,样式如故生效。

2. 什么样自个儿在四个 style 文件中央银行使同名 class 呢?

没难题,这一个同名 class 编写翻译后固然只怕是随机码,但仍是同名的。

3. 例如自身在 style 文件中央银行使了 id 接纳器,伪类,标签选取器等呢?

没难题,全部那一个选用器将不被撤换,没有丝毫改变的出现在编写翻译后的 css 中。也等于说 CSS Modules 只会转移 class 名相关样式。

但注意,上面 3 个“纵然”尽量不要产生

CSS模块化方案分类

CSS 模块化的设计方案有不菲,但重视有三类。

五、输入任何模块

选用器也得以持续其余CSS文件之中的条条框框。

another.css

JavaScript

.className { background-color: blue; }

1
2
3
.className {
  background-color: blue;
}

App.css能够承袭another.css里面包车型客车条条框框。

JavaScript

.title { composes: className from './another.css'; color: red; }

1
2
3
4
.title {
  composes: className from './another.css';
  color: red;
}

运转这一个示例。

JavaScript

$ npm run demo05

1
$ npm run demo05

打开

总结

CSS Modules 很好的解决了 CSS 最近面前境遇的模块化难题。协助与 Sass/Less/PostCSS 等搭配使用,能丰盛利用现存本事积淀。同不经常候也能和全局样式灵活搭配,便于项目中稳步搬迁至 CSS Modules。CSS Modules 的兑现也属轻量级,以后有正统施工方案后能够低本钱迁移。若是您的产品中正好遇见类似主题材料,非常值得一试。

1 赞 2 收藏 评论

彩世界网址 6

CSS in JS

干净扬弃 CSS,用 JavaScript 写 CSS 准则,并内联样式。 React: CSS in JS // Speaker Deck。Radium,react-style 属于这一类。但存在以下难题:
* 不能使用伪类,媒体询问等
* 样式代码也会合世多量重新。
* 不能应用成熟的 CSS 预管理器(或后计算机)

二、全局成效域

CSS Modules 允许使用:global(.className)的语法,声美赞臣个大局法规。凡是那样申明的class,都不会被编译成哈希字符串。

App.css参加贰个大局class。

JavaScript

.title { color: red; } :global(.title) { color: green; }

1
2
3
4
5
6
7
.title {
  color: red;
}
 
:global(.title) {
  color: green;
}

App.js选取普通的class的写法,就能够援引全局class。

JavaScript

import React from 'react'; import styles from './App.css'; export default () => { return ( <h1 className="title"> Hello World </h1> ); };

1
2
3
4
5
6
7
8
9
10
import React from 'react';
import styles from './App.css';
 
export default () => {
  return (
    <h1 className="title">
      Hello World
    </h1>
  );
};

运维那一个示例。

JavaScript

$ npm run demo02

1
$ npm run demo02

打开

CSS Modules 还提供一种显式的局地效率域语法:local(.className),等同于.className,所以地点的App.css也能够写成下边那样。

JavaScript

:local(.title) { color: red; } :global(.title) { color: green; }

1
2
3
4
5
6
7
:local(.title) {
  color: red;
}
 
:global(.title) {
  color: green;
}

CSS 模块化遭受了什么样难点?

CSS 模块化首要的是要消除好八个难题:CSS 样式的导入和导出。灵活按需导入以便复用代码;导出时要力所能致隐敝其间成效域,避防导致全局污染。Sass/Less/PostCSS 等持续试图缓和 CSS 编制程序本事弱的难点,结果它们做的也真正美貌,但那并未缓慢解决模块化最根本的标题。Facebook程序员 Vjeux 首先抛出了 React 开垦中相遇的一雨后春笋 CSS 相关难题。加上本人个人的见识,总计如下:

  1. 全局污染

CSS 使用全局选取器机制来安装样式,优点是有利重写样式。短处是全数的样式都以大局生效,样式大概被错误覆盖,因而产生了拾壹分难看的 !important,甚至 inline !important 和复杂的[接纳器权重计数表](Selectors Level 3),提升犯错可能率和选择费用。Web Components 规范中的 Shadow DOM 能深透化解这些主题材料,但它的做法有些极端,样式深透局地化,形成外界不恐怕重写样式,损失了灵活性。

  1. 取名混乱

 

由于全局污染的主题材料,多少人一块开垦时为了制止样式矛盾,选用器越来越复杂,轻易产生差异的命名风格,很难统一。样式变多后,命大将特别混乱。

  1. 依赖管理不干净

组件应该相互独立,引进一个组件时,应该只引进它所急需的 CSS 样式。但现在的做法是除了要引进 JS,还要再引进它的 CSS,何况 Saas/Less 很难实现对各类组件都编写翻译出单身的 CSS,引进全部模块的 CSS 又导致浪费。JS 的模块化已经特别成熟,假如能让 JS 来治本 CSS 信任是很好的消除办法。Webpack 的 css-loader 提供了这种技艺。

  1. 力不能及分享变量

复杂组件要运用 JS 和 CSS 来共同处理体制,就能够导致某些变量在 JS 和 CSS 中冗余,Sass/PostCSS/CSS 等都不提供跨 JS 和 CSS 分享变量这种本领。

  1. 代码压缩不到底

由于移动端网络的不显明性,未来对 CSS 压缩已经到了变态的程度。相当多压缩工具为了省去多少个字节会把 ’16px’ 转成 ‘1pc’。但对非常长的 class 名却不能够,力未有用到刀刃上。

上边包车型大巴主题材料假使只凭 CSS 本身是心有余而力不足消除的,尽管是透过 JS 来治本 CSS 就很好化解,因此 Vjuex 给出的实施方案是全然的 CSS in JS,但这一定于完全扬弃CSS,在 JS 中以 Object 语法来写 CSS,估摸刚看见的同伴都震撼了。直到出现了 CSS Modules。

 

最后

CSS Modules 很好的缓和了 CSS 目后边临的模块化难点。帮忙与 CSS管理器搭配使用,能丰富利用现存手艺积淀。就算您的出品中恰恰遭遇类似主题素材,特别值得一试。

盼望我们都能写出健康而且可扩展的CSS,以上。

1 赞 2 收藏 评论

彩世界网址 7

六、输入变量

CSS Modules 辅助接纳变量,不过供给安装 PostCSS 和 postcss-modules-values。

JavaScript

$ npm install --save postcss-loader postcss-modules-values

1
$ npm install --save postcss-loader postcss-modules-values

把postcss-loader加入webpack.config.js。

JavaScript

var values = require('postcss-modules-values'); module.exports = { entry: __dirname '/index.js', output: { publicPath: '/', filename: './bundle.js' }, module: { loaders: [ { test: /.jsx?$/, exclude: /node_modules/, loader: 'babel', query: { presets: ['es2015', 'stage-0', 'react'] } }, { test: /.css$/, loader: "style-loader!css-loader?modules!postcss-loader" }, ] }, postcss: [ values ] };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var values = require('postcss-modules-values');
 
module.exports = {
  entry: __dirname '/index.js',
  output: {
    publicPath: '/',
    filename: './bundle.js'
  },
  module: {
    loaders: [
      {
        test: /.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          presets: ['es2015', 'stage-0', 'react']
        }
      },
      {
        test: /.css$/,
        loader: "style-loader!css-loader?modules!postcss-loader"
      },
    ]
  },
  postcss: [
    values
  ]
};

接着,在colors.css当中定义变量。

JavaScript

@value blue: #0c77f8; @value red: #ff0000; @value green: #aaf200;

1
2
3
@value blue: #0c77f8;
@value red: #ff0000;
@value green: #aaf200;

App.css能够援引这一个变量。

JavaScript

@value colors: "./colors.css"; @value blue, red, green from colors; .title { color: red; background-color: blue; }

1
2
3
4
5
6
7
@value colors: "./colors.css";
@value blue, red, green from colors;
 
.title {
  color: red;
  background-color: blue;
}

运作这么些示例。

JavaScript

$ npm run demo06

1
$ npm run demo06

打开

1 赞 3 收藏 评论

彩世界网址 8

CSS Modules 在React中的执行

这就是说我们在React中怎么利用?

一、局地作用域

CSS的条条框框都以全局的,任何几个零件的体裁准绳,都对全部页面有效。

爆发局地效用域的独一情势,正是行使多少个天下无敌的class的名字,不会与别的选择珍视名。那正是CSS Modules 的做法。

上边是三个React组件App.js。

JavaScript

import React from 'react'; import style from './App.css'; export default () => { return ( <h1 className={style.title}> Hello World </h1> ); };

1
2
3
4
5
6
7
8
9
10
import React from 'react';
import style from './App.css';
 
export default () => {
  return (
    <h1 className={style.title}>
      Hello World
    </h1>
  );
};

地点代码中,大家将样式文件App.css输入到style对象,然后引用style.title代表贰个class。

CSS

.title { color: red; }

1
2
3
.title {
  color: red;
}

塑造筑工程具会将类名style.title编写翻译成三个哈希字符串。

XHTML

<h1 class="_3zyde4l1yATCOkgn-DBWEL"> Hello World </h1>

1
2
3
<h1 class="_3zyde4l1yATCOkgn-DBWEL">
  Hello World
</h1>

App.css也会同一时候被编译。

JavaScript

._3zyde4l1yATCOkgn-DBWEL { color: red; }

1
2
3
._3zyde4l1yATCOkgn-DBWEL {
  color: red;
}

这样一来,那么些类名就改成天下无双了,只对App组件有效。

CSS Modules 提供各个插件,扶持区别的营造筑工程具。本文使用的是 Webpack 的css-loader插件,因为它对 CSS Modules 的援救最佳,何况很轻巧选拔。顺便说一下,若是您想学 Webpack,能够阅读小编的课程Webpack-Demos。

上边是以此示例的webpack.config.js。

JavaScript

module.exports = { entry: __dirname '/index.js', output: { publicPath: '/', filename: './bundle.js' }, module: { loaders: [ { test: /.jsx?$/, exclude: /node_modules/, loader: 'babel', query: { presets: ['es2015', 'stage-0', 'react'] } }, { test: /.css$/, loader: "style-loader!css-loader?modules" }, ] } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module.exports = {
  entry: __dirname '/index.js',
  output: {
    publicPath: '/',
    filename: './bundle.js'
  },
  module: {
    loaders: [
      {
        test: /.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel',
        query: {
          presets: ['es2015', 'stage-0', 'react']
        }
      },
      {
        test: /.css$/,
        loader: "style-loader!css-loader?modules"
      },
    ]
  }
};

地点代码中,关键的一行是style-loader!css-loader?modules,它在css-loader后边加了三个询问参数modules,表示张开CSS Modules 功能。

今昔,运转那几个德姆o。

JavaScript

$ npm run demo01

1
$ npm run demo01

打开 ,能够见见结果,h1标题突显为黑古铜色。

手动援引消除

className 处直接行使 css 中 class 名即可。

JavaScript

import React from 'react'; import styles from './table.css';   export default class Table extends React.Component {     render () {         return <div className={styles.table}>             <div className={styles.row}>             </div>         </div>;     } }

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';
import styles from './table.css';
 
export default class Table extends React.Component {
    render () {
        return <div className={styles.table}>
            <div className={styles.row}>
            </div>
        </div>;
    }
}

渲染出来的机件出来

XHTML

<div class="table__table___32osj">     <div class="table__row___2w27N">     </div> </div>

1
2
3
4
<div class="table__table___32osj">
    <div class="table__row___2w27N">
    </div>
</div>

动用JS 来治本体制模块

应用JS编译原生的CSS文件,使其颇负模块化的技术,代表是 CSS Modules GitHub – css-modules/css-modules: Documentation about css-modules 。

CSS Modules 能最大化地结合现成 CSS 生态(预管理器/后计算机等)和 JS 模块化工夫,差相当的少零上学花费。只要您利用 Webpack,能够在另外类型中利用。是小编觉稳当前最佳的 CSS 模块解决决方案。

babel-plugin-react-css-modules

babel-plugin-react-css-modules 能够达成应用styleName品质自动加载CSS模块。大家经过该babel插件来进展语法树分析并最终身成className

来走访组件的写法,以后您只须求把className换成styleName即可获得CSS局地效用域的技能了,是或不是特别轻易。

JavaScript

import React from 'react'; import styles from './table.css';   class Table extends React.Component {     render () {         return <div styleName='table'>         </div>;     } }   export default Table;

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';
import styles from './table.css';
 
class Table extends React.Component {
    render () {
        return <div styleName='table'>
        </div>;
    }
}
 
export default Table;

干什么我们须要CSS模块化

react-css-modules

就算您不想频仍的输入 styles.**,有一个 GitHub – gajus/react-css-modules: Seamless mapping of class names to CSS modules inside of React components.,它通过高阶函数的格局来变化className,然则不引入应用,后文子禽提到。

API也相当的粗略,给组件外包两个CSSModules就能够。

JavaScript

import React from 'react'; import CSSModules from 'react-css-modules'; import styles from './table.css';   class Table extends React.Component {     render () {         return <div styleName='table'>         </div>;     } }   export default CSSModules(Table, styles);

1
2
3
4
5
6
7
8
9
10
11
12
import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './table.css';
 
class Table extends React.Component {
    render () {
        return <div styleName='table'>
        </div>;
    }
}
 
export default CSSModules(Table, styles);

不过那样大家得以看看,它是亟需周转时的依赖,并且要求在运营时才获得className,品质损耗大,那么有未有有益又象是无损的艺术吧?答案是局地,使用babel插件babel-plugin-react-css-modulesGitHub – gajus/babel-plugin-react-css-modules: Transforms styleName to className using compile time CSS module resolution. 把className获得后置到编写翻译阶段。

CSS Modules介绍

CSS Modules是何等事物吧?首先,让我们从官方文书档案入手:
GitHub – css-modules/css-modules: Documentation about css-modules

A CSS Module is a CSS file in which all class names and animation names are scoped locally by default. CSS模块正是享有的类名都唯有一点点功用域的CSS文件。

故而CSS Modules既不是合法正式,亦不是浏览器的性状,而是在营造步骤(举个例子使用Webpack或Browserify)中对CSS类名选取器限定作用域的一种方法(通过hash完毕类似于命名空间的不二秘籍)。

It doesn’t really matter in the end (although shorter class names mean shorter stylesheets) because the point is that they are dynamically generated, unique, and mapped to the correct styles.在利用CSS模块时,类名是动态变化的,独一的,并标准对应到源文件中的种种类的体制。

那也是促成样式成效域的法规。它们被限定在特定的模版里。举个例子大家在buttons.js里引入buttons.css文件,并使用.btn的体裁,在其他零件里是不会被.btn影响的,除非它也引进了buttons.css.

可大家是由于什么样指标把CSS和HTML文件搞得这么零碎呢?大家为什么要动用CSS模块呢?

做事规律

那么该babel插件是怎么工作的啊?让大家从官方文书档案入手:

GitHub – gajus/babel-plugin-react-css-modules: Transforms styleName to className using compile time CSS module resolution.

小编不才 ,稍作翻译如下:
1. 营造每一个文件的有着样式表导入的目录(导入具备.css.scss扩展名的文件)。

  1. 使用postcss 解析相称到的css文件
  2. 遍历全部 JSX 成分注解
  3. styleName 属性解析成佚名和命名的部分css模块援引
  4. 检索与CSS模块引用相相称的CSS类名称:
    * 如果styleName的值是八个字符串字面值,生成三个字符串字面值。
    * 尽管是JSXExpressionContainer,在运行时利用helper函数来创设假若styleName的值是贰个jSXExpressionContainer, 使用协助函数([getClassName]在运行时组织className值。
  5. 从要素上移除styleName属性。
    7. 将扭转的className累积到存活的className值中(如果海市蜃楼则开创className属性)。

健全何况扩充方便的CSS

作为有追求的技术员,编写强壮并且扩充方便的CSS一贯是咱们的目的。那么怎么样定义强健何况扩大方便?有多当中央:

  • 面向组件 – 管理 UI 复杂性的精品实行便是将 UI 分割成三个个的小组件 Locality_of_reference 。如果你正在采纳七个理所必然的框架,JavaScript 方面就将原生支持(组件化)。举例,React 就鼓舞中度组件化和剪切。大家希望有三个 CSS 架构去相称。
  • 沙箱化(Sandboxed) – 假诺一个零件的体裁会对其他零件发生不要求以至意外的熏陶,那么将 UI 分割成组件并从未什么样用。就那位置来讲,CSS的大局意义域会给你产生担任。
  • 方便 – 我们想要全数好的东西,何况不想发生越多的劳作。也正是说,大家不想因为运用那一个架构而让大家的开拓者体验变得更糟。大概的话,大家想开垦者体验变得更加好。

CSS Modules 入门及 React 中实践

2017/03/25 · CSS · React

原稿出处: AlloyTeam   

CSS全局功效域难点

CSS的法则都以大局的,任何一个零件的样式准则,都对全部页面有效。相信写css的人都会遭受样式冲突(污染)的主题材料。

于是乎平时这么做(作者都做过):
* class命名写长一点啊,减少冲突的可能率
* 加个父成分的选取器,限制范围
* 重新命名个class吧,相比保障

故此亟待消除的主题材料便是css局部效率域防止全局样式冲突(污染)的标题

利用实例

在成熟的品类中,日常都会用到CSS预管理器可能后计算机。

那边以利用了stylusCSS预处理器为例子,大家来看下怎么着采纳。

  • 安装信任

Shell

npm install -save-dev sugerss babel-plugin-react-css-modules

1
npm install -save-dev sugerss babel-plugin-react-css-modules
  • 编写Webpack配置
JavaScript

// webpack.config.js module: {   loaders: [{     test: /\.js?$/,
    loader: [['babel-plugin-react-css-modules',{
          generateScopedName:'[name]__[local]',
          filetypes: {               ".styl": "sugerss"            }
     }]]   }, {     test: /\.module.styl$/,     loader:
'style!css?modules&localIdentName=[name]__[local]!styl?sourceMap=true'
  }, {     test: /\.styl$/,     loader:
'style!css!styl?sourceMap=true'   }] }

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-10">
10
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-11">
11
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-12">
12
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-13">
13
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-14">
14
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-15">
15
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-16">
16
</div>
<div class="crayon-num" data-line="crayon-5b8f6729d9ed4116610999-17">
17
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6729d9ed4116610999-18">
18
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6729d9ed4116610999-1" class="crayon-line">
// webpack.config.js
</div>
<div id="crayon-5b8f6729d9ed4116610999-2" class="crayon-line crayon-striped-line">
module: {
</div>
<div id="crayon-5b8f6729d9ed4116610999-3" class="crayon-line">
  loaders: [{
</div>
<div id="crayon-5b8f6729d9ed4116610999-4" class="crayon-line crayon-striped-line">
    test: /.js?$/,
</div>
<div id="crayon-5b8f6729d9ed4116610999-5" class="crayon-line">
    loader: [['babel-plugin-react-css-modules',{
</div>
<div id="crayon-5b8f6729d9ed4116610999-6" class="crayon-line crayon-striped-line">
          generateScopedName:'[name]__[local]',
</div>
<div id="crayon-5b8f6729d9ed4116610999-7" class="crayon-line">
          filetypes: {
</div>
<div id="crayon-5b8f6729d9ed4116610999-8" class="crayon-line crayon-striped-line">
              &quot;.styl&quot;: &quot;sugerss&quot;
</div>
<div id="crayon-5b8f6729d9ed4116610999-9" class="crayon-line">
           }
</div>
<div id="crayon-5b8f6729d9ed4116610999-10" class="crayon-line crayon-striped-line">
     }]]
</div>
<div id="crayon-5b8f6729d9ed4116610999-11" class="crayon-line">
  }, {
</div>
<div id="crayon-5b8f6729d9ed4116610999-12" class="crayon-line crayon-striped-line">
    test: /.module.styl$/,
</div>
<div id="crayon-5b8f6729d9ed4116610999-13" class="crayon-line">
    loader: 'style!css?modules&amp;localIdentName=[name]__[local]!styl?sourceMap=true'
</div>
<div id="crayon-5b8f6729d9ed4116610999-14" class="crayon-line crayon-striped-line">
  }, {
</div>
<div id="crayon-5b8f6729d9ed4116610999-15" class="crayon-line">
    test: /.styl$/,
</div>
<div id="crayon-5b8f6729d9ed4116610999-16" class="crayon-line crayon-striped-line">
    loader: 'style!css!styl?sourceMap=true'
</div>
<div id="crayon-5b8f6729d9ed4116610999-17" class="crayon-line">
  }]
</div>
<div id="crayon-5b8f6729d9ed4116610999-18" class="crayon-line crayon-striped-line">
}
</div>
</div></td>
</tr>
</tbody>
</table>
  • 零件写法

JavaScript

import React from 'react'; import './table.module.styl';   class Table extends React.Component {     render () {         return <div styleName='table'>         </div>;     } }   export default Table;

1
2
3
4
5
6
7
8
9
10
11
import React from 'react';
import './table.module.styl';
 
class Table extends React.Component {
    render () {
        return <div styleName='table'>
        </div>;
    }
}
 
export default Table;

如上,你可以透过布署Webpack中module.loaders的test路线Webpack-module-loaders-configuration,来分别样式文件是不是需求CSS模块化。
搭配sugerss这个postcss插件作为stylus的语法加载器,来支持babel插件babel-plugin-react-css-modules的语法深入分析。

谈起底大家回过头来看下,大家React组件只供给把className换成styleName,搭配以上构建配置,就可以兑现CSS模块化 。

CSS Modules 使用教程

本文由时时app平台注册网站发布于web前端,转载请注明出处:CSS Modules 详解及 React 中实践彩世界网址

关键词: