Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

qbem

scott-linenberger44GPL-3.0-or-later4.0.1TypeScript support: included

A Quick BEM helper!

bem, css, helper, util, style, classnames

readme

NPM version types coverage coverage coverage coverage License issues

Qbem

A quick [BEM][bem] helper! Flexible, Readable, BEM (Block, Element, Modifier).

-------------------------------------------------------------------
|                             QUICK! BEM                          |
-------------------------------------------------------------------
+<    ,ad8888ba,    88888888ba                                   >+
+<   d8"'    `"8b   88      "8b                                  >+
+<  d8'        `8b  88      ,8P                                  >+
+<  88          88  88aaaaaa8P'   ,adPPYba,  88,dPYba,,adPYba,   >+
+<  88          88  88""""""8b,  a8P_____88  88P'   "88"    "8a  >+
+< 'Y8,    "88,,8P  88      `8b  8PP"""""""  88     |88      88  >+
+<   Y8a.    Y88P   88      a8P  "8b,   ,aa  88    | 88      88  >+
+<    `"Y8888Y"Y8a  88888888P"    `"Ybbd8"'  88      88      88  >+
-------------------------------------------------------------------
* BLOCK         |           * ELEMENT           |        * MODIFIER
-------------------------------------------------------------------

Quick Start

Installation

yarn add qbem

OR

npm install qbem

Import or Require

/* import */
import { QBem } from 'qbem';

/* OR require */
require { QBem } from 'qbem';

Example

With React & Typescript with simple HTML templating

import React from 'react'
import { QBem } from 'qbem'

const bem = new QBem('qbem-demo')

const QBemDemo: React.FC = () => {
  /* demo puprposes only */
  const isDarkMode = true
  const isActivated = false

  return (
    <div
      className={bem.block(
        [{ ['dark-mode']: isDarkMode, activated: isActivated }],
        'demo'
      )}
    >
      <div className={bem.elem('header')}>
        <h2 className={bem.elem('title-primary')}>QBem Demo</h2>
        <h3 className={bem.elem('title-secondary')}>Flexible, Readable, Bem</h3>
      </div>
      <div className={bem.elem('content')}>
        <div>
          <span className={bem.elem('dropcap')}>Block</span>
          <span className={bem.elem('dropcap')}>Element</span>
          <span className={bem.elem('dropcap')}>Modifier</span>
        </div>
      </div>
    </div>
  )
}

Outputs

<div class="qbem-demo qbem-demo--dark-mode demo">
  <div class="qbem-demo__header">
    <h2 class="qbem-demo__title-primary">QBem Demo</h2>
    <h3 class="qbem-demo__title-secondary">Flexible, Readable, Bem</h3>
  </div>
  <div class="qbem-demo__content">
    <div>
      <span class="qbem-demo__dropcap">Block</span>
      <span class="qbem-demo__dropcap">Element</span>
      <span class="qbem-demo__dropcap">Modifier</span>
    </div>
  </div>
</div>

User Guide

Creating an instance of QBem

/* initializing a new instance of QBem with a block name */
const bem = new QBem('<block-name-here>')

Block Name

const bem = new QBem('block')
// ..
bem.block() // -> 'block'

Block Name with Static Modifiers

const bem = new QBem('block')
// ..
/* single modifier */
bem.block(['mod1']) // -> block block--mod1

/* multiple modifiers */
bem.block(['mod1', 'mod2', 'mod3']) // -> block block--mod1 block--mod2 block--mod3

Block Name with non-BEM Static Classes

const bem = new QBem('block')
// ..
/* single non-BEM class */
bem.block(null, 'classname-a') // -> 'block classname-a'

/* multiple non-BEM classes */
bem.block(null, 'classname-a', 'classname-b', 'classname-c') // -> 'block classname1 classname2 classname3'

Element Name

const bem = new QBem('block')
// ..
/* using `element` */
bem.element('element') // -> 'block__element'

/* using `elem` */
bem.elem('element') // -> 'block__element'

Element Name with Static Modifiers

const bem = new QBem('block')
// ..
/* single modifier */
bem.elem('element', ['mod1']) // -> 'block__element'
/* multiple modifiers */
bem.elem('element', ['mod1', 'mod2', 'mod3']) // -> 'block__element'
// 'block__element block__element--mod1 block__element--mod2 block__element--mod3'

/* single modifier */
bem.element('element', ['mod1']) // -> 'block__element'
/* multiple modifiers */
bem.element('element', ['mod1', 'mod2', 'mod3'])
// 'block__element block__element--mod1 block__element--mod2 block__element--mod3'

Element with non-BEM Static Classes

const bem = new QBem('block')
// ..

/* single non-BEM class */
bem.elem('element', null, 'classname') // -> 'block__element classname'
bem.elem('element', null, 'classname-a', 'classname-b', 'classname-c')
// -> 'block__element classsname-a classname-b classname-c

QBemConditionalKeys

To conditionally apply classnames and or modifier values, you can create a simple Javascript object with string properties that have boolean values.

Properties: become modifiers or classname, must be valid object properties Boolean: values determine if the property is applied

// modifiers example
{
  mod1: true, // apply this modifier
  mod2: false, // DO NOT apply this modifier
  ['mod-3']: true // apply this modifier
  ['mod-4']: false // DO NOT apply this modifier
}

// classes example
{
  class1: true, // apply this class
  class2: false, // DO NOT apply this class
  ['class-3']: true, // apply this class
  ['class-4']: false // DO NOT  apply this class
}

Block with Conditional Modifiers

const bem = new QBem('block')
// ..

/* single object, single key */
bem.block([{ mod1: true }]) // -> 'block block--mod1'

/* single object with multiple keys */
bem.block([
  {
    mod1: true,
    mod2: false, // NOT applied
    mod3: true
  }
]) // -> 'block block--mod1 block--mod2'

/* multiple objects with single key */
bem.block([{ mod1: true }, { mod2: false }, { mod3: true }]) // -> 'block block--mod1 block--mod2'

Block with Conditional Classes

const bem = new QBem('block')
// ..

/* single object, single key */
bem.block(null, { class1: true }) // -> 'block class1'

/* single object with multiple keys */
bem.block(null, {
  class1: true,
  class2: false, // NOT applied
  class3: true
}) // -> 'block class1 class2'

/* multiple objects, single key */
bem.block(null, [{ class1: true }, { class2: false }, { class3: true }])
// -> 'block class1 class2'

Element with Conditional Modifiers

const bem = new QBem('block')
// ..

/* single object, single key */
bem.elem('element', [{ mod1: true }])
bem.element('element', [{ mod1: true }]) // -> 'block__element block__element--mod1'

/* single object with multiple keys */
bem.elem([{ mod1: true, mod2: false, mod3: true }])
bem.element([
  {
    mod1: true,
    mod2: false, // NOT applied
    mod3: true
  }
])
// -> 'block__element block__element--mod1 block__element--mod3'

/* multiple objects, single key */
bem.elem([{ mod1: true }, { mod2: false }, { mod3: true }])
// -> 'block__element block__element--mod1 block__element--mod3'

Element with Conditional Classes

const bem = new QBem('block')
// ..

/* single object, single key */
bem.elem('element', null, { class1: true }) // -> 'block__element class1'

/* single object with multiple keys */
bem.elem('element', null, {
  class1: true,
  class2: false, // NOT applied
  class3: true
})
bem.element('element', null, {
  class1: true,
  class2: false, // NOT applied
  class3: true
}) // -> 'block__element class1 class3'

/* multiple objects, single key */
bem.elem(
  'element',
  null,
  { class1: true },
  { class2: false }, // NOT applied
  { class3: true }
)
bem.element(
  'element',
  null,
  { class1: true },
  { class2: false }, // NOT applied
  { class3: true }
) // -> 'block__element class1 class3'

Mixed Usage Example

const bem = new QBem('form')

const isDarkMode = true

bem.elem(
  'section-1', // element name
  [ // modifiers
    {
      ['theme-light']: !isDarkMode,
      ['theme-dark']: isDarkMode,
    },
    'required'
  ],
  'third-party-style' // class string
  {
    ['third-party-dark-mode']: isDarkMode // conditional class object
  }
) // -> 'form__section-1 form__section-1--theme-dark form__section-1--required third-party-style third-party-dark-mode'

Classes

classes is available as both a static method on the QBem class QBem.classes and as a standalone import from QBem for your convenience.

Classes with string classnames

import { QBem } from 'qbem'

const output = QBem.classes('a', 'b', 'c') // "a b c"

Classes with conditional classes

import { QBem } from 'qbem';

const output = QBem.classes('a', {
  b: false,
  ['dark-mode']: true,
}, 'c') // "a dark-mode c"
```

[bem]: http://getbem.com/naming/

changelog

QBem Changelog

[4.0.0] - 2025-06-09

Changed

  • bumped version to update stale README

[4.0.0] - 2025-06-09

Added

  • switch compilation from webpack & ts to tsup
  • Prettier config for code formatting
  • ESLint + TypeScript rules replacing deprecated TSLint

Changed

  • Jest config updated to use ts-jest for native TypeScript support
  • Internal helper logic cleaned up (e.g. modifier fallback returns base)
  • package.json modernized with exports, sideEffects, and new scripts

Removed

  • Webpack, Babel, TSLint, and ts-loader

Breaking

  • Internal build pipeline replaced; output paths and formats changed
  • Deep imports may need to be updated by consumers