CSS Modules 实例代码


作者: 阮一峰

Demo01: Local Scope

demo / sources

CSS rules are global. The only way of making a local-scoped rule is to generate a unique class name, so no other selectors will have collisions with it. That is exactly what CSS Modules do.

The following is a React component App.js.

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

In above codes, we import a CSS module from App.css into a style object, and use style.title to represent a class name.

  1. .title {
  2. color: red;
  3. }

The build runner will compile the class name style.title into a hash string.

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

And App.css is also compiled.

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

Now this class name becomes unique and only effective to the App component.

CSS Modules provides plugins for different build runners. This repo uses css-loader for Webpack, since it support CSS Modules best and is easy to use. By the way, if you don't know Webpack, please read my tutorial Webpack-Demos.

The following is our webpack.config.js.

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

The magic line is loader: "style-loader!css-loader?modules", which appends the query parameter modules after css-loader enabling the CSS Modules feature.

Now run the demo.

  1. $ npm run demo01

Open http://localhost:8080, you should see the h1 in red.

Demo02: Global Scope

demo / sources

The syntax :global(.className) could be used to declare a global selector explicitly. CSS Modules will not compile this class name into hash string.

First, add a global class into App.css.

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

Then use the global CSS class in App.js.

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

Run the demo.

  1. $ npm run demo02

Open http://localhost:8080, you should see the h1 title in green.

CSS Modules also has a explicit local scope syntax :local(.className) which is equivalent to .className. So the above App.css could be written in another form.

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

Demo03: Customized Hash Class Name

demo / sources

CSS-loader's default hash algorithm is [hash:base64], which compiles.title into something like ._3zyde4l1yATCOkgn-DBWEL.

You could customize it in webpack.config.js.

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

Run the demo.

  1. $ npm run demo03

You will find .title hashed into demo03-components-App---title---GpMto.

Demo04: Composing CSS Classes

demo / sources

In CSS Modules, a selector could inherit another selector's rules, which is called "composition".

We let .title inherit .className in App.css.

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

App.js is the same.

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

Run the demo.

  1. $ npm run demo04

You should see a red h1 title in a blue background.

After the building process, App.css is converted into the following codes.

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

And the HTML element h1's class names should look like <h1 class="_2DHwuiHWMnKTOYG45T0x34 _10B-buq6_BEOTOl9urIjf8">,

Demo05: Import Other Modules

demo / sources

You also could inherit rules from another CSS file.

another.css

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

App.css

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

Run the demo.

  1. $ npm run demo05

You should see a red h1 title in a blue background.

Demo06: Exporting Values Variables

demo / sources

You could use variables in CSS Modules. This feature is provided by PostCSS and the postcss-modules-values plugin.

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

Add postcss-loader into webpack.config.js.

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

Next, set up your values/variables in colors.css.

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

Then import them into App.css.

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

Run the demo.

  1. $ npm run demo06

下载地址