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

sass-bem-constructor

v1.1.0

Published

BEM Constructor is a Sass library for building immutable and namespaced BEM-style CSS objects.

Downloads

263

Readme

BEM Constructor Build Status npm version Bower version Gem Version

BEM Constructor is a Sass library for building immutable and namespaced BEM-style CSS objects.

By enforcing a consistent and programatic way of defining objects (blocks, elements and modifiers) it ensures a more structured, robust and secure object codebase that is easy to understand and maintain. Objects defined using the constructor are impossible to modify and reassign by mistake or omission.

Jump to :hamburger: The Burger Example™ to see the mixins in action.

Key ideas

The key ideas behind this library are well explained by Harry Roberts in his articles Immutable CSS, More Transparent UI Code with Namespaces and MindBEMding – getting your head ’round BEM syntax,

1. Immutability

Some CSS objects in your project shouldn't be able to change (mutate). They have a very specific role and you need to make sure they're not reassigned somewhere else in your codebase. In order to ensure immutability you'll need three things: a way of defining those objects, a way of recognising them and a way to guarantee you won't be able to modify them later on. By constructing objects programatically you can be confident that they are assigned once and just once.

2. Namespacing

Objects have a clear function. Whether they are components, utilities, or dirty hacks, we need a consistent way of telling them apart. By namespacing objects, our UI code becomes more transparent and understandable. BEM Constructor supports the following object types:

  • Objects
  • Components
  • Utilities
  • Themes
  • States
  • Scopes
  • Hacks

Read Harry's post on namespaces to get a deep look at why and how they are used.

3. BEM structure

BEM objects are composed of a block and any number of elements and/or modifiers. Using the BEM syntax for naming classes you'll produce structured code that helps you and other developers understand at a glance the relationship between those classes. The BEM constructor takes care of generating bem-compliant selectors.

4. Responsive suffixes

With responsive suffixes you are able to denote conditional states or breakpoints where permutations to an object may occur. This is specially useful when dealing with media queries that modify the base values of a given UI element.

Installation

There are 4 ways of installing BEM Constructor:

Download

Download bem-constructor.scss and place it in your Sass directory.

Bower

Run the following command:

bower install --save-dev bem-constructor

NPM

Run the following command:

npm install sass-bem-constructor --save-dev

Compass extension

  1. gem install bem-constructor
  2. Add require 'bem-constructor' to your config.rb

Usage

Import it into your main stylesheet:

@import 'bem-constructor';

block($name, $type)

Constructs a new block element of a given type. $type being one of: 'object', 'component' or 'utility'.

@include block($name, $type) { ... }

object($name)

A shortcut for block($name, $type: 'object')

component($name)

A shortcut for block($name, $type: 'component')

utility($name)

A shortcut for block($name, $type: 'utility')

element($name...)

Creates a new element of the parent block. It should always be nested within a block constructor. You can create multiple elements at once by passing a comma separated list (Arglist) of element names.

@include element($name...) { ... }

modifier($name...)

Creates a new modifier of the parent block or element. Should always be nested within a block or element constructor. You can declare multiple modifiers at once by passing a comma separated list (Arglist) of modifier names.

@include modifier($name...) { ... }

modifies-element($modified-elements...)

When declaring a block modifier, a theme, a state or a hack you may need to target and modify some of the block elements too. Use the following mixin to scope the ruleset to those elements.

@include modifies-element($modified-elements...) { ... }

theme($themes...)

Style your objects given a parent theme class.

@include theme($themes...) { ... }

state($states...)

Modifies objects by appending a state class

@include state($states...) { ... }

hack()

Signals that the following code is a hack.

@include hack() { ... }

scope($name)

Creates a new scope

Scopes allow you to isolate code you don't have control over.

@include scope($name) { ... }

suffix($name)

Adds a suffix

Denotes a conditional breakpoint that modifies the properties and/or values of an UI

@include suffix($name) { ... }

Options

Namespaces

Switch namespaces on/off by setting the following variable:

$bem-use-namespaces: false; // defaults to true

Override the default block namespaces:

$bem-block-namespaces: (
    'object': 'obj',     // defaults to 'o'
    'component': 'comp', // defaults to 'c'
    'utility': 'helper', // defaults to 'u'
);

Override the default theme namespace:

$bem-theme-namespace: 'theme'; // defaults to 't'

Override the default state namespace:

$bem-state-namespace: 'has'; // defaults to 'is'

Override the default suffix namespace:

$bem-suffix-namespace: '-at-'; // defaults to ''\\@''

Override the default hack namespace:

$bem-hack-namespace: 'it-wasnt-me-'; // defaults to '_'

BEM separators

By default BEM Constructor uses the following BEM convention:

  • Two underscores (__) for elements
  • Two hyphens for modifiers (--).

You can customize them to whatever fits your needs:

$bem-element-separator: '-'; // Defaults to '__'

$bem-modifier-separator: '-_-_'; // Defaults to '--'

Suffixes

By default BEM Constructor uses @ to denote suffixes (e.g. .o-media@large).

You can customize the suffix to whatever fits your needs:

$bem-suffix-namespace: '---'; defaults to '\\@'

:hamburger: The Burger Example™

Disclaimer: the following Sass code may not compile into a real burger.


    @include object('burger') {
        texture: juicy;

        @include element('lettuce', 'tomato') {
            quality: fresh;
        }

        @include element('cheese') {
            type: gouda;

            @include modifier('parmigiano') {
                type: parmigiano;
            }
        }

        @include element('extra-topping') {
            ingredient: bacon;
        }

        @include element('meat') {
            type: beef;
        }

        @include modifier('veggie') {
            texture: smooth;

            @include modifies-element('meat') {
                type: lentils;
            }

            @include modifies-element('extra-topping') {
                ingredient: avocado;

                @include hack() {
                    ingredient: bacon;
                }
            }
        }

        @include theme('mexican') {
            spicy: hell-yeah;
        }

        @include state('cold') {
            taste: terrible;
        }

        @include suffix('children') {
            size: mini;
        }
    }

The compiled CSS:


    /* The main Burger object */
    .o-burger { texture: juicy; }

    /* Lettuce and Tomato elements */
    .o-burger__lettuce, .o-burger__tomato { quality: fresh; }

    /* Cheese element */
    .o-burger__cheese { type: gouda; }

    /* Cheese modifier */
    .o-burger__cheese--parmigiano { type: parmigiano; }

    /* Extra topping element */
    .o-burger__extra-topping { ingredient: bacon; }

    /* Meat element */
    .o-burger__meat { type: beef; }

    /* Veggie Burger block modifier */
    .o-burger--veggie { texture: smooth; }

    /* Veggie Burger block modifier modifies the Meat element too */
    .o-burger--veggie .o-burger__meat { type: lentils; }

    /* Veggie Burger block modifier modifies the Extra Topping element too */
    .o-burger--veggie .o-burger__extra-topping { ingredient: avocado; }

    /* But as hackers we couldn't resist the urge to add some Bacon back */
    .o-burger--veggie ._o-burger__extra-topping { ingredient: bacon; }

    /* When the party Theme is Mexican, we make everything spicy */
    .t-mexican .o-burger { spicy: hell-yeah; }

    /* And we're all sad when a burger Is Cold */
    .o-burger.is-cold { taste: terrible; }

    /* Mini burgers for children */
    .o-burger\@children { size: mini }

Visual debugger

BEM constructor visual debugger

Perform a visual healthcheck against your UI using the debugger mixin.

bem-debug($targets...)

@include bem-debug('modifiers', 'components'); // Outlines all modifiers and components

Available targets are classes,modifiers,elements,objects,components,utilities and hacks.

Use it empty to outline all target types: @include bem-debug();

Customize outline styles by overriding the $bem-debug-styles map.

$bem-debug-styles: (
    'classes'    : 5px solid #ddd,
    'modifiers'  : 5px solid #aaa,
    'elements'   : 5px solid #111,
    'objects'    : 5px solid #FFDC00,
    'components' : 5px solid #FF851B,
    'utilities'  : 5px solid #0074D9,
    'hacks'      : 5px solid #FF4136,
);
```