kagagnon/bem-php

PHP shortcodes to generate BEM class with a Laravel integration

0.1.12 2018-12-16 20:13 UTC

This package is not auto-updated.

Last update: 2024-04-28 03:03:46 UTC


README

Install via composer with

$ composer install kagagnon/bem-php

Optional configurations

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 = '';

How to use

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.

Blocks

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.

Classes

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
    ]
] );

HTML example

<?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>

Create node with startBlock()

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.

Example

<?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>

Use with Laravel (Blade directives)

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

Twig extension

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