Install via composer with
$ composer install kagagnon/bem-php
Configurations are static properties to the KAGagnon\BemPhp\Helpers\BemHelper
class. You can edit them before using BemPhp
:
<?php
/**
* Separator between block and element
*/
KAGagnon\BemPhp\Helpers\BemHelper::$element_separator = '__';
/**
* Separator between modifer and block/element
*/
KAGagnon\BemPhp\Helpers\BemHelper::$modifier_separator = '--';
/**
* Should @bem create a tag element
*/
KAGagnon\BemPhp\Helpers\BemHelper::$create_tag = false;
/**
* If create_tag is true, what's the default tag name
*/
KAGagnon\BemPhp\Helpers\BemHelper::$default_tag = 'div';
/**
* Prefix of BEM classes.
*/
KAGagnon\BemPhp\Helpers\BemHelper::$block_prefix = '';
It is recommanded to include a use
statement before using BemHelper
Class. Alternatively, you can create helper functions to shorten the use of the class.
You can create a new block with the directive BemHelper::startBlock( $block_name )
. Once the block if finished,
you can use BemHelper::endBlock()
to close the block. BEM block can be nested for sub-module. So this:
<?php
BemHelper::startBlock( 'block' );
BemHelper::startBlock( 'other-block' );
BemHelper::endBlock();
BemHelper::endBlock();
is a valid syntax.
To generate a class, you can use BemHelper::bemClass( [ string|array $element [, string|array $modifiers[, integer $parent_level = 0 ]]] )
.
- Passing no arguments generate the block name.
- Passing a string as first argument generate the block name with an element.
- Passing an array as first argument generate the block name with the modifiers.
- Passing a string and an array generate a block name with an element and its modifiers.
- Passing 2 strings generate a block name with an element and explode the string on spaces to generate the modifiers.
- Parent level integer allow to use a parent BEM class in nested loops.
Check the examples below:
<?php
BemHelper::startBlock( 'cup' ); // Init Block "cup"
BemHelper::bemClass(); // Generate : cup
BemHelper::bemClass( [ 'glass' ] ); // Generate : cup cup--glass
BemHelper::startBlock( 'spoon' ); // Init Block "spoon"
BemHelper::bemClass(); // Generate : spoon
BemHelper::bemClass( [ 'metallic', 'cold' ] ); // Generate : spoon spoon--metallic spoon--cold
BemHelper::bemClass( 'sugar' ); // Generate : spoon__sugar
BemHelper::bemClass( 'sugar', 'half-tea-spoon' ); // Generate : spoon__sugar spoon__sugar--half-tea-spoon
BemHelper::bemClass( 'spoon-holder', '', 1 ) // Generate : cup__spoon-holder
BemHelper::EndBlock();
BemHelper::bemClass( 'tea' ); // Generate : cup__tea
BemHelper::bemClass( 'coffee' ); // Generate : cup_coffee
BemHelper::bemClass( 'coffee' , 'with-sugar' ); // Generate : cup__coffee cup__coffee--with-sugar
BemHelper::bemClass( 'coffee' , [ 'with-sugar', 'with-milk'] ); // Generate : cup__coffee cup__coffee--with-sugar cup__coffee--with-milk
BemHelper::bemClass( 'coffee' , 'with-sugar with-milk no-foam' ); // Generate : cup__coffee cup__coffee--with-sugar cup__coffee--with-milk cup__coffee--no-foam
BemHelper::EndBlock();
##Conditional modifiers
Sometime, you might want to use conditions to set modifiers such as if it is the first or last iteration of the loop. To do so, you can set your modifiers by passing an array where the key is the classname and the value is the condition. That way, if the condition resolves as true, the modifier will be added to the list.
BemHelper::bemClass( 'coffee', [
'with-sugar' => $has_sugar == true
] );
You can mix conditional modifiers with other modifiers, and it also works with the startBlock
method.
BemHelper::startBlock( 'cup', 'div', [
'_modifiers' => [
'blue',
'is-cold' => !$has_hot_beverage,
'is-empty' => $finished
]
] );
<?php BemHelper::startBlock( 'article' ) ?>
<div class="<?php BemHelper::bemClass() ?>">
<h1 class="<?php BemHelper::bemClass( 'title' ) ?>">Article Name</h1>
<p class="<?php BemHelper::bemClass( 'content' ) ?>">Article text...</p>
<?php BemHelper::startBlock( 'meta' ) ?>
<div class="<?php BemHelper::bemClass() ?>">
<a href="..." class="<?php BemHelper::bemClass( 'link', 'inactive' ) ?>">0 comments</a>
<a href="..." class="<?php BemHelper::bemClass( 'link', 'clear danger' ) ?>">Delete</a>
<a href="..." class="<?php BemHelper::bemClass( 'link' ) ?>">Edit</a>
</div>
<?php BemHelper::endBlock(); ?>
</div>
<?php BemHelper::endBlock(); ?>
Result to :
<div class="article">
<h1 class="article__title">Article Name</h1>
<p class="article__content">Article text...</p>
<div class="meta">
<a href="..." class="meta__link--inactive">0 comments</a>
<a href="..." class="meta__link--clear meta__link--danger">Delete</a>
<a href="..." class="meta__link">Edit</a>
</div>
</div>
You can pass argument to startBlock()
to automatically generate an HTML tag.
To do so, you can pass the tag name as second argument and, optionally, an array of attributes.
You can also skip the tag name and pass an array as second argument. That will create an HTML element base on the default_tag
configuration.
Additionally, if you set create_tag
to true, startBlock()
will always create a tag base on
the default_tag
configuration if only 1 argument is passed.
To pass modifiers to the tag, simply pass _modifiers
in the array: an array for multi-modifiers or a string for single modifier.
<?php
// We assume `create_tag` is set to true
BemHelper::startBlock( 'block' ) // <div class="block">
BemHelper::endBlock() // </div>
BemHelper::startBlock( 'block', 'article' ) // <article class="block">
BemHelper::endBlock() // </article>
BemHelper::startBlock( 'block', 'quote', [ 'data-inspiration', 'class' => 'js-action' ] ) // <quote class="js-action block" data-inspiration >
BemHelper::endBlock() //</quote>
BemHelper::startBlock( 'block', [ 'id' => "anchor" ] ) // <div class="block" id="anchor">
BemHelper::endBlock() // </div>
BemHelper::startBlock( 'block', [ 'id' => "anchor", '_modifiers' => 'modifier' ] ) // <div class="block block--modifier" id="anchor">
BemHelper::endBlock() // </div>
BemHelper::startBlock( 'block', [ '_modifiers' => [ 'modifier1', 'modifier2' ] ] ) // <div class="block block--modifier1 block--modifier2">
BemHelper::endBlock() // </div>
This plugin comes with a Laravel integration. You can include the KAGagnon\BemPhp\BemServiceProvider
class in your application service providers list. The following directive will be mapped :
@bem( ... ) => BemHelper::startBlock
@bemclass( ... ) => BemHelper::bemClass
@endbem => BemHelper::endBlock
This plugin comes with a Twig integration. You can register the KAGagnon\BemPhp\Twig\BemTwigExtension
in Twig extensions. The following directive will be mapped :
{% bem( ... ) %} => BemHelper::startBlock
{{ bemclass( ... ) }} => BemHelper::endBlock
{% endbem %} => BemHelper::getBemClass