Dev Series: Magento and BEM Methodology

When I started my first forays into web development, I was using tables for layout – don’t shoot me, this was in 1994! I then took on some work whilst in school that introduced me to <div> and style specific coding. At this time, it was inline, but everyone has to start somewhere.

After University I got my first job that embedded me in the world of web development, using stylesheets as they were meant to be, separating style from layout.

It wasn’t until recently that I true started looking solely at frontend technologies and standards (previously I was in more full stack roles). I can tell you itai??i??s a jungle out there!

Introduction into CSS Methodologies

There are several methodologies out there for frontend developers to use to provide an order to their stylesheets and reduce codebase bulk: OOCSS, BEM, SMACSS, Atomic to name but a few.

OOCSS

Object-Oriented Cascading Stylesheets encourages the creation of ‘objects’ that can be reused in much the same way as objects are used in ai programming languages.

BEM

Block-Element-Modifier has the main attraction of planning your class names so that they related directly to the HTML elements they are styling. More on this later…

SMACSS

Scaleable and Modular Architecture for CSS highlights splitting the style rules into different categories; Base, Layout, Module, State and Theme Rules.

Atomic

Atomicai??i??s aim is to break down from pages to templates, organisms, molecules and finally atoms, where atoms are the individual elements, molecules are groups of atoms that make up a page element such as a login form, building up to the full page.

In this article, and because Iai??i??ve become enamoured with it, I shall be looking at BEM specifically and how it can help make building Magento templates quicker and easier to amend down the line.

What is BEM?

As mentioned before, BEM splits elements on a page into sections, or blocks. A block might be something like a login form. These blocks contain elements, such as text fields and buttons. If an element has multiple states – maybe the button has a disabled state until the form in completed, then those would be setup as separate rules.

The syntax for BEM follows strict rules, but thankfully they’re really easy to understand:

.block__element–modifier

To give this some simple-form context:

<form class=ai???login-formai???>
	<label class=ai???login-form__labelai??? for=ai???usernameai???>Username</label>
	<input class=ai???login-form__inputai??? name=ai???usernameai??? />
<label class=ai???login-form__labelai??? for=ai???passwordai???>Password</label>
	<input class=ai???login-form__inputai??? name=ai???passwordai??? />
	<button class=ai???login-form__button login-form__button--offai???>Submit</button>
</form>

In the above example, there is one block,
.login-form.

There are three elements;
.login-form__label, .login-form__input and login-form__button.
There is one modifier,
.login-form__button–off.

The blocks say which element on the page the styles are for. Elements are the styles for the parts that make up the element (in this example, the login form). The modifier is the inactive state for the button in the case that no information is written in the above form.

I find that BEM lends itself very nicely to using sass to write CSS:

/* login form styles */
.login-form {
	...
	&__label {
		...
	}
	&__input {
		ai??i??
	}
	&__button {
		ai??i??
		&--off {
			...
		}
	}
}

I find that it allows me to better visualise the styles as they appear in the markup. I find that BEM allows you to also have a nice structure to your sass directory trees, have a different .sass file for each block. How deep you go with this depends on your own personal preferences and how you feel about the axe murderer who has to maintain the site you built.

Applying BEM to Magento

As BEM is a frontend methodology, it can be used on any project, bespoke or from a project such as Magento, so it is hard for me to think up a Magento specific use of BEM. Mainly because CSS methodologies are generally used to make a developerai??i??s life a bit easier, reduce code bloat and provide structure to styles.

In the end, it does indeed come down to personal preference. After researching multiple methods of structuring my CSS, I settled on BEM as being the one that would benefit my workflow the best.

This is because I can use BEM alongside my sass file structure and have a .scss file that might compliment the header.phtml template (logos, menus, search bar etc) and in that file, @import other files from a ai???blocksai??i?? folder which relate directly to the BEM structure, so I might have the following for header.scss

// skin/frontend/package/theme/scss/_header.scss
@import ai???blocks/logoai??i??;
@import ai???blocks/navigationai??i??;
@import ai???blocks/searchai??i??;

and then in my ai???blocksai??i?? folderai??i??

// skin/frontend/package/theme/scss/blocks/_search.scss
.header-search {
	&__label {
		@extend .ui__fieldlabel;
	}
	&__input {
		@extend .ui__textfield;
		border-color: #999;
		padding: 3px 15px;
}
	&__button {
		@extend .ui__btn;
		background: #53B240;
		&:hover {
			background: #82CC74;
		}
	}
}

These styles would relate to my form.mini.phtml:

<?php
// app/design/frontend/template/catalogsearch/form.mini.phtml

$catalogSearchHelper =  $this->helper('catalogsearch');
?>
<form id="search_mini_form" class="header-search" action="<?php echo $catalogSearchHelper->getResultUrl() ?>" method="get">
    <div class="form-search">
        <label for="search" class="headerssearch__label"><?php echo $this->__('Search:') ?></label>
        <input id="search" type="text" name="<?php echo $catalogSearchHelper->getQueryParamName() ?>" value="<?php echo $catalogSearchHelper->getEscapedQueryText() ?>" class="input-text headersearch__input" maxlength="<?php echo $catalogSearchHelper->getMaxQueryLength();?>" />
        <button type="submit" title="<?php echo $this->__('Search') ?>" class="button headersearch__btn"><span><span><?php echo $this->__('Search') ?></span></span></button>
        <div id="search_autocomplete" class="search-autocomplete"></div>
        <script type="text/javascript">
        //<![CDATA[
            var searchForm = new Varien.searchForm('search_mini_form', 'search', '<?php echo $this->__('Search entire store here...') ?>');
            searchForm.initAutocomplete('<?php echo $catalogSearchHelper->getSuggestUrl() ?>', 'search_autocomplete');
        //]]>
        </script>
    </div>
</form>

Using BEM methodologies during our latest build for high-end watch retailer Iconic Watches made much more sense when it came to organising the styles for some of the more complex parts, such as the tile flips for product listings. BEM coupled with the sass ampersand made the build of the front end theme quicker as I didn’t need to repeatedly rewrite the same class names over and over.

Useful Resources