npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

better-bem

v2.0.3

Published

Chainable BEM classname generator with CSS Modules support

Downloads

136

Readme

better-BEM 2.x

better-BEM is a dynamic classname generator using BEM methodology (.block__element--modifier) which supports CSS Modules. better-BEM is chainable and allows modifier inheritance. Disclaimer: In contrast to what the package name suggests, better-BEM might not actually be better than other packages handling BEM classname generation. It definitely is better than better-BEM 1.x.

Getting Started

Installing

# install
npm i better-bem
// import
import bem from 'better-bem';

Usage

bem( [classNames [, mods [, classNameMap [, strict [, glue ] ] ] ] ] )

const className = bem('article').el('header').mod('large').el('title').mod('red').cn;

document.querySelector('h1').className = className;
// => <h1 class="article__header__title article__header__title--large article__header__title--red"> ...

Jump to examples.

Parameters

classNames

Classname(s) which will form the 'block' part of the generated classname(s).

Optional

Default: []

Accepts: String, object or array of strings and/or objects

Please refer to the ClassName parameter usage section for details on how this parameter works.

mods

Modifiers for the generated classnames. Modifiers are passed down the chain, see the section on Chaining and modifier inheritance.

Optional

Default: []

Accepts: String, object or array of strings and/or objects

See ClassName parameter usage for more details.

classNameMap

Object which maps input classnames to output classnames.

Optional

Default: {}

Accepts: Object

See using className maps

strict

When strict is true and when classNameMap isn't empty, classnames which aren't mapped in classNameMap will be ignored.

Optional

Default: true

Accepts: Boolean

See using className maps

glue

Object with strings which will be used to concat classnames. If not set these fall back to -- for modifiers, __ for element classnames and - for key-value modifiers. See examples.

Optional

Default: {}

Accepts: Object

Return value

Object { string cn, function el, function mod }

cn

Outputted classname string for current BEM chain. Note: All classnames are checked for valid characters using the following regular expression: /^(-[_a-zA-Z]|[_a-zA-Z][-_a-zA-Z0-9])[-_a-zA-Z0-9]*$/

el

function el( [ elementClassNames ] )

Function to push a new element on the BEM chain. See chaining for examples.

elementClassNames

Default: []

Accepts: String, object or array of strings and/or objects

See ClassName parameter usage for more details.

mod

function mod( [ modifiers ] )

Function to add a modifier the current BEM className and all descendants. See Chaining and modifier inheritance for examples.

modifiers

Default: []

Accepts: String, object or array of strings and/or objects

See ClassName parameter usage for more details.

ClassName parameter usage

bem(), el() and mod() all accept the same types of parameters. These types are:

  • a string containing a single classname or modifier
  • a string containing multiple classnames or modifiers separated by spaces
  • an object where the keys are used as classnames or modifiers when the related value is thruthy
    • for mod() key-value pairs are mapped as a key-value string when the value is a string or a number
  • an array containing any of the above

| Parameter value | classnames | modifiers | | :--- | :--- | :--- | | "foobar" | "foobar" | "--foobar" | | "foo bar" | "foo bar" | "--foo", "--bar" | | { foo: true, bar: 0, prop: "value" } | "foo mod" | "--foo", "--bar-0", "--prop-value" | | [ "foo bar", { prop: "value" } ] | "foo bar mod" | "--foo", "--bar", "--prop-value" |

Examples

Chaining and modifier inheritance

const header = bem('header');
console.log(header.cn); // "header"

const title = header.el('text title');
console.log(title.cn); // "header__text header__title"

const blueTitle = title.mod({ color: 'blue' });
console.log(blueTitle.cn);
// "header__text header__text--color-blue header__title header__title--color-blue"

const emphasizedText = blueTitle.el('emp').mod('bold');
console.log(emphasizedText.cn);
// "header__text__emp header__title__emp header__text__emp--color-blue
//   header__title__emp--color-blue header__text__emp--bold header__title__emp--bold"

// note that modifiers are inherited by child elements

Using CSS Modules

/* styles.css */
.header {
	font-size: 2em;
}

.header__title {
	font-weight: bold;
}

.header__title--blue {
	color: blue;
}
import styles from './styles.css';

const header = bem('header', 'blue', styles);
console.log(header.cn); // "header"
// note that "header--blue" is omitted from the output, because it's not defined in styles.css

const title = header.el('title');
console.log(title.cn); // "header__title header__title--blue"
// both the base classname and modified classname are outputted, since they are defined in styles.css
// note that the 'blue' modifier is still inherited

const nonStrictHeader = bem('header', 'blue', styles, false);
console.log(nonStrictHeader.cn); // "header header--blue"
// now strict is set to `false`, all classnames will be outputted

Custom glue strings

const defaultGlue = bem('element', [{ color: 'blue' }], {}, true).el('child');
console.log(defaultGlue.cn); // "element__child element__child--color-blue"

const customGlue = bem('element', [{ color: 'blue' }], {}, true, { el: '_', mod: '-', prop: '--' }).el('child');
console.log(customGlue.cn); // "element_child element_child-color--blue"

Built With

Versioning

better-BEM uses SemVer for versioning. For the versions available, see the tags on this repository.

Authors

License

This project is licensed under the ISC License - see the LICENSE file for details

Related