Giter VIP home page Giter VIP logo

react-css-modules's Introduction

React CSS Modules

Travis build status NPM version

React CSS Modules implement automatic mapping of CSS modules. Every CSS class is assigned a local-scoped identifier with a global unique name. CSS Modules enable a modular and reusable CSS!

What's the Problem?

CSS Modules are awesome. If you are not familiar with CSS Modules, it is a concept of using a module bundler such as webpack to load CSS scoped to a particular document. CSS module loader will generate a unique name for a each CSS class at the time of loading the CSS document (Interoperable CSS to be precise). To see CSS Modules in practice, webpack-demo.

In the context of React, CSS Modules look like this:

import React from 'react';
import styles from './car.css';

export default class Car extends React.Component {
    render () {
        return <div className={styles.car}>
            <div className={styles.frontDoor}></div>
            <div className={styles.backDoor}></div>
        </div>;
    }
}

Rendering the component will produce a markup similar to:

<div class="car__car___32osj">
    <div class="car__front-door___2w27N">front-door</div>
    <div class="car__back-door___1oVw5">back-door</div>
</div>

and a corresponding CSS file that matches those CSS classes.

Awesome!

However, this approach has several disadvantages:

  • You have to use camelCase CSS class names.
  • You have to use styles object whenever constructing a className.
  • Mixing CSS Modules and global CSS classes is cumbersome.
  • Reference to an undefined CSS Module resolves to undefined without a warning.

React CSS Modules component automates loading of CSS Modules using styleName property, e.g.

import React from 'react';
import styles from './car.css';
import CSSModules from 'react-css-modules';

class Car extends React.Component {
    render () {
        return <div styleName='car'>
            <div styleName='front-door'></div>
            <div styleName='back-door'></div>
        </div>;
    }
}

export default CSSModules(Car, styles);

Using react-css-modules:

  • You are not forced to use the camelCase naming convention.
  • You do not need to refer to the styles object every time you use a CSS Module.
  • There is clear distinction between global CSS and CSS Modules, e.g.
<div className='global-css' styleName='local-module'></div>
  • You are warned when styleName refers to an undefined CSS Module (errorWhenNotFound option).
  • You can enforce use of a single CSS module per ReactElement (allowMultiple option).

The Implementation

react-css-modules extends render method of the target component. It will use the value of styleName to look for CSS Modules in the associated styles object and will append the matching unique CSS class names to the ReactElement className property value.

Awesome!

Usage

Setup consists of:

Module Bundler

webpack

{
    test: /\.css$/,
    loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]')
}
  • Setup extract-text-webpack-plugin plugin:
new ExtractTextPlugin('app.css', {
    allChunks: true
})

Refer to webpack-demo or react-css-modules-examples for an example of a complete setup.

Browserify

Refer to css-modulesify.

Decorator

/**
 * @typedef CSSModules~Options
 * @see {@link https://github.com/gajus/react-css-modules#options}
 * @property {Boolean} allowMultiple
 * @property {Boolean} errorWhenNotFound
 */

/**
 * @param {Function} Component
 * @param {Object} styles CSS Modules class map.
 * @param {CSSModules~Options} options
 * @return {Function}
 */

You need to decorate your component using react-css-modules, e.g.

import React from 'react';
import styles from './car.css';
import CSSModules from 'react-css-modules';

class Car extends React.Component {
    render () {
        return <div className='car'>
            <div className='front-door'></div>
            <div className='back-door'></div>
        </div>;
    }
}

export default CSSModules(Car, styles);

Thats it!

As the name implies, react-css-modules is compatible with the ES7 decorators syntax:

import React from 'react';
import styles from './car.css';
import CSSModules from 'react-css-modules';

@CSSModules(styles)
export default class extends React.Component {
    render () {
        return <div className='car'>
            <div className='front-door'>front-door</div>
            <div className='back-door'>back-door</div>
        </div>;
    }
}

Awesome!

Refer to the react-css-modules-examples repository for an example of webpack setup.

Options

Options are supplied as the third parameter to the CSSModules function.

CSSModules(Component, styles, options);

or as a second parameter to the decorator:

@CSSModules(styles, options);

allowMultiple

Default: false.

Allows multiple CSS Module names.

When false, the following will cause an error:

<div styleName='foo bar' />

errorWhenNotFound

Default: true.

Throws an error when styleName cannot be mapped to an existing CSS Module.

SASS, SCSS, LESS and other CSS Preprocessors

Interoperable CSS is compatible with the CSS Preprocessors. To use a preprocessor, all you need to do is add the preprocessor to the chain of loaders, e.g. in the case of webpack it is as simple as installing sass-loader and adding !sass to the end of the style-loader loader query (loaders are processed from right to left):

{
    test: /\.scss$/,
    loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!sass')
}

Global CSS

CSS Modules does not restrict you from using global CSS.

:global .foo {

}

However, use global CSS with caution. With CSS Modules, there are only a handful of valid use cases for global CSS (e.g. normalization).

Multiple CSS Modules

CSS Modules promote composition pattern, i.e. every CSS Module that is used in a component should define all properties required to describe an element, e.g.

.button {

}

.active {
    composes: common;

    /* anything that only applies to active state of the button */
}

.disabled {
    composes: common;

    /* anything that only applies to disabled state of the button */
}

Composition promotes better separation of markup and style using semantics that would be hard to achieve without CSS Modules.

To learn more about composing CSS rules, I suggest reading Glen Maddern article about CSS Modules and the official spec of the CSS Modules.

That said, if you enable allowMultiple option, you can map multiple CSS Modules to a single ReactElement. react-css-modules will append a unique class name for every CSS Module it matches in the styleName declaration, e.g.

.button {

}

.active {

}
<div styleName='button active'></div>

This will map both Interoperable CSS CSS classes to the target element.

react-css-modules's People

Contributors

erikras avatar gajus avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.