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

bem-css

v0.4.0

Published

This is a set of tools for working with CSS—specifically for writing CSS that adheres to BEM.

Downloads

14

Readme

BEM CSS

This is a set of tools for working with CSS—specifically for writing CSS that adheres to BEM.

The guiding principles are enforcing correctness of the CSS, being helpful to its users, while recognizing that CSS may not be the best language to write CSS in.

There are two sets of tools: One for creators of the BEM CSS and another for consumers.

  1. For creators
    • A way to define blocks, elements, and modules with their CSS, in JavaScript.
    • A function that transforms the input to some sort of output. Right now, this is
      1. An object with each individual file/block under their respective block name.
      2. All the CSS concatinated (so you can save it where you want)
      3. A bem tree which descripes the structure of the CSS (see uses below)
  2. For users
    • A function for creating the class names needed.
    • If configured with the bem tree, then it'll provide helpful help messages if you are trying to create a class name that does not point to anything defined in the css.

Api

Creating BEM CSS

Let's create a card block, with a title (we will ignore content for simplicity). There is a variant in red. We will also create button block, with only a green modification.

// src/card.js
modules.export = block(
  // We provide the css as an array
  [
    backgroundColor('yellow'), // css properties are done with function calls
    padding(10)                // numbers are converted to px. Here "10px"
  ],

  modifier('red', [
    backgroundColor('pink')
  ]),

  element(
    'header',
    [
      fontSize(20)
    ],
    modifier('red', [
      color('#c00')
    ])
  )
)

Since each file is its own block (with the name of the file), we have to create another file for the new block.

// src/button.js
modules.export = block(
  [
    borderRadius(5),
    padding(4, 10)
  ],

  pseudo([":hover", ":active"], [
    boxShadow(0, 0, 3, "rgba(0, 0, 0, .2)")
  ]),

  modification('green', [
    backgroundColor('#0c0')
  ])
)

A few things should stand out to you here.

  1. We use JavaScript to write CSS. This means you have access to everything that javascript can do.
  2. One file per block. This is to ease trying to find said blocks later when you need to correct the CSS.
  3. We use a lot of global variables for creating css. I understand this is not for everyone, so you can disable this and import everything as needed.

Let's build it.

// build.js
const make = require('bem-css/make')

make(path.join(__dirname, 'src'))
  .then(console.log)

The output is an array with results. I suggest you just inspect it (because this is all very much a work in progress), but as of writing we get five things: "all css", "single css", "bem tree", "warnings", and "error".

If the error is defined, you should not trust any of the other output (they will most likely be null anyway).

// all css
.card {
  background-color: yellow;
  padding: 10px;
}
.card--red {
  background-color: pink;
}
.card__header {
  font-size: 20px;
}
.card__header--red {
  color: #c00;
}

.button {
  border-radius: 5px;
  padding: 4px 10px;
}
.button:hover, .button:active {
  box-shadow: 0px 0px 3px rgba(0, 0, 0, .2);
}
.button--green {
  background-color: #0c0;
}
// single css
{
  "card": "...",  // the "card" part of the css above
  "button": "..." // the "button" part above
}
// bem tree
{
  // Some json representation of the blocks above
}

Using BEM CSS

Say we saved the "all css" into a file: all.css, and the content of the "bem tree" into bemTree.json in another product that we are building as an SPA. I will just use React for illustration.

// util/cx.js
import cx from "bem-css/src/cx"
import bemTree from "./bemTree.json"
cx.configure({bemTree})
export default cx

Now, in some React component somewhere, we can do:

import cx from "../util/cx"

const myBtnClass = cx("button", {green: true}) // "button button--green"
const myBtnClass = cx("button", {green: false}) // "button"
const myCardClass = cx("card") // "card"
const myCardHeaderClass = cx("card", "header") // "card__header"
const myRedCardHeaderClass = cx("card", "header", ["red"]) // "card__header card__header--red"
// and so on...

Notice that modifiers are inserted with either an object or an array.

If cx was configure with the bemTree, then it will (unless env.NODE_ENV === "production") warn you if you are trying to create a class name that does not exist in the bem tree.