@include block('name') { … @include element('child') { … } @include modifier('light') { … } @include state('active') { … } }
.name { … } .name__child { … } .name--light { … } .name.is-active { … }
Install
Bemify can be installed as a Ruby Gem, NPM-module, via bower, or manually. As a NPM module, bemify supports eyeglass. Bemify is also on Sache.
Ruby Gem
$ gem install bemify
NPM
$ npm install bemify --save-dev
Bower
$ bower install bemify
Manual Install
Clone the repository or download sass/_bemify.scss
. Put _bemify.scss
in the directory of your sass/scss code where you deem fit.
Using bemify
First, import bemify (note that the path might need to be adjusted depending on your installation method):
@import "bemify";
Then you can use bemify to write bem-style scss source for your components. The output will be full, non-nested bem-style class selectors.
@include block('my-block') { … @include element('child') { … } @include modifier('small') { … } @include state('state') { … } }
.my-element { … } .my-element__child { … } .my-element--small { … } .my-element.is-active { … }
By default, bemify will output combined .block.state
/ .block__element.state
selectors. Bemify can also be configured to output full .block--state
/ .block__element--state
selectors. For details, see Configuration below.
Nesting
The mixins can be nested to create modifiers for subcomponents:
@include block('my-element') { @include element('child') { … @include modifier('bad') { … @include state('happy') { … } } } @include modifier('large') { … } @include state('active') { … } }
.my-element { … } .my-element__child { … } .my-element__child--bad { … } .my-element__child--bad.is-happy { … } .my-element--large { … } .my-element.is-active { … }
Scoping
Bemifys mixins can be used inside a scope. Whether scoping is to be considered true BEM remains open for dicsussion though.
.scope { @include block('my-block') { … @include element('item') { … } } }
.scope .my-block { … } .scope .my-block__item { … }
Configuration
Bemify uses configuration variables to adjust the block-element and block-/block-element-state separator, as well as the state prefix. To overwrite bemify's config with your own configuration file, just import your variables before using one of the mixins.
@import "my_config";
@import "bemify";
@include block('my-block') {
…
}
If you are not using a configuration file, you can directly override the appropriate variables after importing bemify. The configuration variables and their defaults are:
$combined-state-selectors
:true
true
will ouput.block.is-active
,false
will output.block--is-active
.$element-separator
:__
$modifier-separator
:--
$state-prefix
:is
Note that $state-prefix
can be overridden with each call to the state mixin as a second argument, so you can use both --is-active
and --has-error
using the same configuration:
@include state('error', 'has') {
…
}
Aliases
Not everyone thinks in the categories of 'block, element, modifier', but many of us still want to write modularized, component-based CSS. There are a couple of aliases included for those who think in terms of components, parent-child / -subcomponents included.
@include block('name') {}
== @include component('name') {}
@include element('name') {}
== @include child('name') {}
== @include subcomponent('name') {}
== @include sub('name') {}
It is also straightforward to add your own aliases:
@mixin my-block-alias($name) {
@include block($name) {
@at-content;
}
}
Resources
Some highly recommended reading re CSS structure, decoupling markup and styles, BEM, and why this makes sense: