We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在最近的React项目中,遇到了CSS处理的问题:
平时的项目开发中,还会有一些类似的CSS问题:
使用CSS模块化可以很好的解决上述问题。目前主要分为两类:
一类是彻底抛弃 CSS,使用 JS 或 JSON 来写样式。Radium, jsxstyle ,react-style 属于这一类。优点是能给 CSS 提供 JS 同样强大的模块化能力;缺点是不能利用成熟的 CSS 预处理器(或后处理器) Sass/Less/PostCSS, :hover 和 :active 伪类处理起来复杂。
另一类是依旧使用 CSS,但使用 JS 来管理样式依赖,代表是CSS Modules。CSS Modules 能最大化地结合现有 CSS 生态和 JS 模块化能力。发布时依旧编译出单独的 JS 和 CSS。它并不依赖于 React,只要你使用 Webpack,可以在 Vue/Angular/jQuery 中使用。
CSS Modules 仅作用于class和id选择器 对其他选择器无效
CSS Modules 通过webpack配置引入项目,不依赖于任何框架,只要使用webpack配置后就可以用于React/Vue/Angular/jQuery 项目中.
在webpack.config.js的module中添加如下配置:
module.exports = { entry: __dirname + '/index.js', output: { publicPath: '/', filename: './bundle.js' }, module: { rules: [ ... { test: /\.css$/, use:[ {loader:'style-loader'}, { loader:'css-loader', option:{ modules:true } } ] }, ] } };
上面代码中,关键的是在style-loader的option里配置option:{modules:true},表示打开 CSS Modules 功能。
style-loader
option:{modules:true}
使用这种配置方式,css-loader默认将类名编译为唯一的hash串,但不利于class类名的语义化,如:
/*header.css*/ .root { text-align: center; } .header { background-color: #536587; height: 150px; padding: 20px; color: white; } .title { font-size: 1.5em; } /*header.js*/ import React fron 'react'; import styles from './header.css'; const Header =()=>{ return ( <div className={styles.root}> <header className={styles.header}> <h1 className={styles.title}>Welcome to React</h1> </header> </div> ) } export default Header;
<h1/>将被编译为:<h1 class="_1yHZnBWcll0vdb7BCk5Ufm">Welcome to React</h1>
<h1/>
<h1 class="_1yHZnBWcll0vdb7BCk5Ufm">Welcome to React</h1>
同时 style.css文件将被编译为
._1yHZnBWcll0vdb7BCk5Ufm { font-size: 1.5em; }
因此,需要在配置webpack时多做一点,定制编译生成的哈希类名:
rules:[ { test:/.css$/, use:[ {loader:'style-loader'}, {loader:'css-loader', option:{modules:true,localIdentName:'[path][name]__[local]-[hase:base64:5]'} ] } ]
配置localIdentName之后 上面的类名将生成 如下格式:
局部变量 默认 :local 构建时按照 localIdentName 做规则处理
:local
localIdentName
全局变量 需要声明全局变量时,使用:global,全局变量,编译后类名不变
:global
.normal { color: green; } /* 以上与下面等价 */ :local(.normal) { color: green; } /* 定义全局样式 */ :global(.btn) { color: red; } /* 定义多个全局样式 */ :global { .link { color: green; } .box { color: yellow; } }
对于样式复用,CSS Modules 只提供了唯一的方式来处理:composes 组合
composes
.userInfoBox { position: relative; padding: 0 24px 0 32px; height: 40px; color: white; line-height: 40px; background: #1f1f1f; transition: background .2s ease 0s; } .docDownloadBox { composes: userInfoBox; margin-right: 10px; border-right: 1px solid #444; }
使用docDownloadBox类的HTML
<a className={styles.docDownloadBox}> 文档&下载 </a>
编译为两个class
/* 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 语法,编译时会报错。就只能使用预处理器自己的语法来做样式复用了。
配合classnames使用
classnames
npm install --save classnames
/* components/submit-button.js */ import React, { Component } from 'react'; import classNames from 'classnames'; import styles from './submit-button.css'; export default class SubmitButton extends Component { render () { let text = this.props.store.submissionInProgress ? 'Processing...' : 'Submit'; let className = classNames({ [`${styles.base}`]: true, [`${styles.inProgress}`]: this.props.store.submissionInProgress, [`${styles.error}`]: this.props.store.errorOccurred, [`${styles.disabled}`]: this.props.form.valid, }); return <button className={className}>{text}</button>; } };
/* components/submit-button.js */ import React, { Component } from 'react'; import classNames from 'classnames/bind'; import styles from './submit-button.css'; let cx = classNames.bind(styles); export default class SubmitButton extends Component { render () { let text = this.props.store.submissionInProgress ? 'Processing...' : 'Submit'; let className = cx({ base: true, inProgress: this.props.store.submissionInProgress, error: this.props.store.errorOccurred, disabled: this.props.form.valid, }); return <button className={className}>{text}</button>; } };
CSS Moduels 本身没有变量的概念,如果需要使用变量,要借助预处理器/后处理器。
安装 PostCSS 和 postcss-icss-values。
npm install --save postcss-loader postcss-icss-values
把postcss-loader加入webpack.config.js。
{ test: /\.css$/, use: [ require.resolve('style-loader'), { loader: require.resolve('css-loader'), options: { importLoaders: 1, modules:true, localIdentName:'[name]--[local]--[hash:base64:5]' } }, { loader: require.resolve('postcss-loader'), options: { ident: 'postcss', plugins: () => [ require('postcss-flexbugs-fixes'), autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway ], flexbox: 'no-2009', }), require('postcss-icss-values') ], }, }, ], },
然后,定义变量,如variable.css
variable.css
@value primary #0c77f8; @value green #aaf200; /*变量和值之间 写不写冒号都可以,但如果和sass配合使用,不要写分号 一次只定义一个变量 */
App.css中引入变量
App.css
@value variables: "./variable.css"; @value primary from variables; //或者直接 @value primary from "variables.css" .title { background-color: primary; }
注意:red,blue,pink,green等颜色不会被当做变量处理
//variable.css @value primary #0c77f8; //App.js import { primary } from './variable.css'; console.log(primary); // -> #0c77f8
在webpack.conf.js中添加exclude/include配置,定义不同的解析规则即可
webpack.conf.js
exclude/include
// webpack.config.js 局部 { test: /\.css$/, exclude:/common.css/, use: [ require.resolve('style-loader'), { loader: require.resolve('css-loader'), options: { importLoaders: 1, modules:true, localIdentName:'[name]--[local]--[hash:base64:5]' } }, { loader: require.resolve('postcss-loader'), options: { // Necessary for external CSS imports to work // https://github.com/facebookincubator/create-react-app/issues/2677 ident: 'postcss', plugins: () => [ require('postcss-flexbugs-fixes'), autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway ], flexbox: 'no-2009', }), require('postcss-icss-values') ], }, }, ], }, { test:/\.css$/, include:/common.css/, use:['style-loader','css-loader','postcss-loader'] },
设置为全局规则的css类,不会被模块化处理。
babel-plugin-react-css-modules 可以实现使用styleName属性自动加载CSS模块。只需要把className换成styleName即可获得CSS局部作用域的能力,babel插件来自动进行语法树解析并最终生成className。改动成本极小,不会增加JSX的复杂度,也不会给项目带来额外的负担。
babel-plugin-react-css-modules
import React from 'react'; import './table.css';
export default class Table extends React.Component { render () { return <div styleName='table'> <div styleName='row'> <div styleName='cell'>A0</div> <div styleName='cell'>B0</div> </div> </div>; } export default Table;
使用babel-plugin-react-css-modules:
<div className='global-css' styleName='local-module'></div>
参考文献:
The text was updated successfully, but these errors were encountered:
No branches or pull requests
CSS Modules 详解及应用
在最近的React项目中,遇到了CSS处理的问题:
平时的项目开发中,还会有一些类似的CSS问题:
使用CSS模块化可以很好的解决上述问题。目前主要分为两类:
相关概念
CSS Modules是什么
原理
使用CSS Modules 有什么优势
启用方法
CSS Modules 通过webpack配置引入项目,不依赖于任何框架,只要使用webpack配置后就可以用于React/Vue/Angular/jQuery 项目中.
在webpack.config.js的module中添加如下配置:
上面代码中,关键的是在
style-loader
的option里配置option:{modules:true}
,表示打开 CSS Modules 功能。使用这种配置方式,css-loader默认将类名编译为唯一的hash串,但不利于class类名的语义化,如:
<h1/>
将被编译为:<h1 class="_1yHZnBWcll0vdb7BCk5Ufm">Welcome to React</h1>
同时 style.css文件将被编译为
因此,需要在配置webpack时多做一点,定制编译生成的哈希类名:
配置localIdentName之后 上面的类名将生成 如下格式:
CSS Modules的使用
局部变量和全局变量
局部变量 默认
:local
构建时按照localIdentName
做规则处理全局变量 需要声明全局变量时,使用
:global
,全局变量,编译后类名不变Compose 组合Class
对于样式复用,CSS Modules 只提供了唯一的方式来处理:
composes
组合复用内部样式
使用docDownloadBox类的HTML
编译为两个class
复用外部样式
==========
层叠多个class
配合
classnames
使用npm install --save classnames
直接使用
使用 classnames/bind
定义和使用变量
CSS Moduels 本身没有变量的概念,如果需要使用变量,要借助预处理器/后处理器。
定义变量
安装 PostCSS 和 postcss-icss-values。
把postcss-loader加入webpack.config.js。
然后,定义变量,如
variable.css
在其他css文件中使用变量,
App.css
中引入变量注意:red,blue,pink,green等颜色不会被当做变量处理
css和js共享变量
模块化样式和全局样式共存
在
webpack.conf.js
中添加exclude/include
配置,定义不同的解析规则即可设置为全局规则的css类,不会被模块化处理。
使用babel-plugin-react-css-modules
import React from 'react';
import './table.css';
使用
babel-plugin-react-css-modules
:<div className='global-css' styleName='local-module'></div>
参考文献:
The text was updated successfully, but these errors were encountered: