BEM class names generator
Friendly BEM class names generator. Great for React.
Bem-cn (aka BEM Class Name) is extra small (minified+gzipped less than 1.6Kb) and extremely simple client-side library and Node.js module.
Important! Only bem-cn@3.x+
compatible with react@16+
.
Please do not use version 2.x or lower.
More details about the problem.
Inspired by b_.
Justification
I spent a lot of time finding BEM class name generator, that meets my needs:
- Simple usage with React
- Support modifiers without value
- Mix multiple blocks
- Friendly API
When my efforts had led to naught I've created this micro library.
Install
With Node.js:
npm i --save bem-cn
yarn add bem-cn
Works with webpack and browserify:
var { block } = require('bem-cn');
import { block } from 'bem-cn';
API
const b = block('button');
b();
b('icon');
b({ type: 'text' });
b({ onlykey: true });
b({ without: false });
b('icon', { name: 'check' });
b('icon').mix('another');
b('icon').mix(['one', 'two']);
b.state({ hidden: true });
b.state({ hidden: false });
b.state({ hidden: true, error: true });
b.is({ loading: true });
b.has({ content: true });
import { setup } from 'bem-cn';
const block = setup({
el: '~~',
mod: '--',
modValue: '-'
});
const b = block('block');
b('element');
b({ mod: 'value' });
const block = setup({ ns: 'ns-' });
const b = block('block');
b();
b('element');
b({ mod: 'value' });
Try it with React
import block from 'bem-cn';
import React from 'react';
import ReactDOM from 'react-dom';
const b = block('popup');
const Popup = React.createClass({
render() {
const { skin, children } = this.props;
return (
<div className={b()}>
<span className={b('icon')} />
<div className={b('content', { skin })}>
{children}
</div>
</div>
);
}
});
ReactDOM.render(<Popup skin="bright">Hello!</Popup>, target);
Troubleshooting
Maigrate to version 3.x
@todo
PropTypes warnings
bem-cn@2.x
or lower has specific chainable API. As a result, each call returns function for a further call. But most components are expecting property className
as a string and using propTypes
object for check this. In this case, you will see a warning. There are the couple of ways to avoid these warnings below.
#1
Use final call without arguments to get a string
<CustomComponent className={b('icon')()} />
#2
Use explicit call of method toString()
:
<CustomComponent className={b('icon').toString()} />
#3
Use less specific propTypes rules:
let CustomComponent = React.createClass({
propTypes: {
className: React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.func
])
},
});
ES3 browsers
bem-cn
is fully compatible with ES5 browsers. If you are going to support ES3 browsers than just use es5 shim.