by

Using BEM to take Tridion implementations from good to great

Not too long ago, I was put on a new project at Tahzoo and I got to hear what many developers in the community (and even at Tahzoo) can only fantasize about:  “Be as cutting edge as you want.”. A coworker, Joe Shirley, and I, were given the freedom to use whatever tools, techniques, and technologies that we wanted to build a corporate intranet — our only limitation that it must degrade gracefully in IE8.

Now, Joe earned his blackbelt in JavaScript years ago, so his weapons of choice were require.js, grunt.js, and Karma. My weapons of choice? BEM and Stylus. What’s BEM? It’s my new best friend.

Semantics and Opinions

Any time more than one person is writing HTML for a project, you introduce risks.

First, the semantics

  • Inconsistent selectors e.g.: using IDs, classes, or elements
  • Inconsistent naming conventions e.g..imageLeft vs. .img.left
  • Cross over properties from duplicate classes e.g.: .image {padding: .618em} ..... .image {margin: 1.618em}

And then the opinions

Years ago, in a religious studies class I took in college, my professor explained the Jewish Talmud and their tradition of debate with a saying, “Where you find two Rabbis you have three opinions”.

Ask two developers how to write semantic markup, expect five opinions, and pray that the end result is a slanted mezuzah.

So, where we had three developers and a tech lead, there were enough opinions to keep us wandering a desert for 40 years… were it not for BEM (Block, Element, Modifier). The actual BEM website kind of stinks and does a less-than-spectacular job of explaining the approach. But, CSSWizardry has a much better explanation.

BEM and a CMS

As I mentioned, BEM is an acronym for Block, Element, Modifier — and it’s a methodology for writing your HTML and CSS. But to make it relevant, we should to look at its application in the context of a content management system.

B is for Block

The BEM approach is built on a core idea that your website or web application is a sum of its parts and is not a single entity. When we translate this into a content management system, the Block is a complete unit of content that a content author could add, edit, or remove from a page. In Tridion terminology, the Block equates to a schema or a component. So let’s look at a simplified version of a Tridion schema that came from the project I worked on.

Field Name Field Type
Schema Fields for bodyCopy
paragraph Rich Text
header Plain Text
image Component Link
imagePosition PlainText List
imageCaption Plain Text

In Tridion, the Block is the schema. Over in HTML-land, we’ll call the Block the outermost HTML wrapper. Now, a core principle of BEM is that everything gets a class, but the block class is the first and most important. So how do we decide on a good class name for the wrapper? I found an effective solution in making the Block class name the same as the XML name of the Tridion schema. It’s less information to store in my brain:

<article class="bodyCopy">

</article>

Since a core principle of BEM is giving everything a class, I want to elaborate why it’s classes, and not ID’s or butt-naked elements.

I am strongly against using IDs in my CSS, and I hope you are, too. Starting your CSS with IDs in your selectors leads to specificity bloat (having to use even higher specificities later). An ID is supposed to be that thing that makes an element absolutely unique, so it’s certainly appropriate to write JavaScript that targets by IDs, but I find it a nuisance to see an ID in a stylesheet when a class would have been fine.

The BEM methodology essentially removes the need to use IDs in your CSS because you end up creating a single, highly specific class name that’s almost as unique as an ID. Stay with me and watch how it happens. Because BEM is class-focused, that means that there’s no issue with switching your header for an h1; you now have a layer of semantics that isn’t predicated on choosing HTML4 over HTML5.

E is for Element

If the block is the a whole unit of content, the Element is an individual part. Coming from Tridion, the Element is a field in the schema. Since the Element is a field in the schema, I can use the XML name of that field as part of my element’s class name:

<article class="bodyCopy">
<header class="bodyCopy__header">
</header>
</article>

In BEM, all Elements are children of Blocks. Since an Element is a child of a Block, the warm and neighborly thing is to tell you this in the class name: I take the name of the Block, append a double underscore (__), and then add a the name of the element. Think of it as a last name and first name for the element.

Here’s what the completed markup looks like when we add in all the element classes:

<article class="bodyCopy">
<header class="bodyCopy__header">
</header>
<figure class="bodyCopy__image">

<figcaption class="bodyCopy__image__imageCaption">

</figcaption>
</figure>
<div class="bodyCopy__paragraph">

</div>
</article>

So what you realize is that, even with just a glance, you know what the wrapper is. Isn’t that helpful? Another thing I hope you noticed was the image caption; it’s actually a grand-child, isn’t it? In BEM, Elements can be parents, too. We use the double underscore to indicate the child nature of this HTML element.

In reality, the image field was an embedded schema, so what you would see in our markup are classnames that indicate grand-child and even great-grand-child relationships to the block.

Now, I bet you’re not thrilled about seeing so many double underscores…

Ugly folks have the best personalities

When I first looked at BEM, I had some serious objections: “Man, BEM gets ugly quick!”; “those class names get long!” “that just seems like a pain!”.

I like short, simple class names. And I’m the kind of guy that will use two sibling selectors and a descendant selector before I’ll even chain classes. I stick to DRY like beards stick to Chasidim.
So, let’s talk about the ugliness:

.bodyCopy__image__imageCaption{
margin: 1.618em
}

It isn’t pretty, but there’s absolutely no question as to what you’re styling. And guess what? the specificity is [0,0,1,0]. In fact, every class which you style will have that exact same specificity. How nice is that?

Not only did your stylesheet just get exponentially easier, writing the Razor is pretty easy now, too, since you’ve got a class name that’s paired to every field in the schema:

<article class="bodyCopy">
<header class="bodyCopy__header">
<h2>@fields.header</h2>
</header>
<figure class="bodyCopy__image">
<img class="bodyCopy__image__img" src="@fields.image" />
<figcaption class="bodyCopy__image__imageCaption">
@fields.imageCaption
</figcaption>
</figure>
<div class="bodyCopy__paragraph">
@fields.paragraph
</div>
</article>

So is it ugly? Yeah, a little, but it’s got personality.

M is for modifier

What you haven’t seen me address yet is a field in that schema for image position. That’s because it’s a modifier. In BEM, you start with a core element or block, and then allow for deviations from that core version. When there’s an alternate version of something, it gets a modifier class, too.

Let’s evaluate the case of image positions. Consider that my image could be positioned statically, OR it could be floated left/right:

<article class="bodyCopy bodyCopy">
<header class="bodyCopy__header">
</header>
<figure class="bodyCopy__image bodyCopy__image--left">

<figcaption class="bodyCopy__image__imageCaption ">

</figcaption>
</figure>
<div class="bodyCopy__paragraph">

</div>
</article>

The point of emphasis is the figure — in particular the classes that are on it. What I’ve done is kept the original class, .bodyCopy__image, and then I’ve added another class to it: .bodyCopy__image--left. The double hyphen is my indicator that this is a modification of an original.

b…but it’s ugly

If your primary objection is the appearance of long class names, my response is that you have a specificity of [0,0,2,0] and you can add all the margin adjustments and padding changes you want to that --left class, which you can’t do if you’re just adding .left to the element.

It means you can have this:

.bodyCopy__image{
margin: 0;
padding: 1em;
}
.bodyCopy__image--left{
float:left;
margin-right: .618em;
padding: 1.15em;
}

instead of this crap:

.bodyCopy__image{
margin: 0;
padding: 1em;
}
.left{
float:left
}
.bodyCopy__image.left{
margin-right: .618em;
padding: 1.15em;
}

So you’re not chaining classes in your stylesheet any more. This is a good thing; the browser is doing less work and you have less debugging to do. And, keep in mind that, since Blocks and Elements can be modified, you’re better equipped to deal with cases where fields in your component are conditional.

In the current project, the image field was actually entirely optional, so we use modifier classes to give us a necessary hook for styling the elements differently.

<article class="bodyCopy bodyCopy--hasImage">
<header class="bodyCopy__header">
</header>
<figure class="bodyCopy__image bodyCopy__image--left bodyCopy__image--hasCaption">

<figcaption class="bodyCopy__image__imageCaption ">

</figcaption>
</figure>
<div class="bodyCopy__paragraph">

</div>
</article>

Some Elements of our Block will always be there, because they’re required. But for the fields that aren’t required, we consider it a modification to the parent— when they are filled in. This is why you see that .bodyCopy has the additional class .bodyCopy--hasImage and likewise for the image caption. It can live with out the image, but it’s modified when it has the image.

Won’t stylesheets be a pain?

In a separate post, I’ll address how we eliminated the pain and suffering of writing super long selectors in our stylesheets. In short, the answer is a CSS preprocessor called Stylus. If you haven’t used it, I’d recommend you read up on it.

The Big Idea

If you have control over the markup at all, and you have a team of people writing it, you need a systematic methodology for writing semantic markup.

If you have any say at all into the markup, I’d recommend BEM. It’s a proven methodology that made it a cakewalk to write semantic HTML without endless debates about using article over an aside . A whole team can write CSS without tripping each other up along the way. BEM also makes it easy to produce markup that demonstrates a relationship with the schema and template that’s produced it, which means that Tridion development can move faster and be debugged more efficiently.

4 Comments


  1. //

    Hi Frank, interesting post! I had a question about what this does to the size of the CSS? It must make it bigger, but any idea by how much?


    1. //

      Hi Hendrik,

      That’s a great question and I’ll answer it in detail in an upcoming post. In a nutshell, our CSS did NOT get larger as a result. I worked on this client’s public-facing website a year earlier, and this intranet shared many of the same features. The public facing website had a 143kb compressed CSS file, the intranet was 43KB.

      A big part of the reason that BEM didn’t bloat our CSS file is because we used a CSS preprocessor to help us. Stylus let us create variables, mixins’, and functions which were hugely helpful in making sure that we were able to stay DRY.

      Another thing to point out is that, it actually ~doesn’t~ make the CSS as big as you’d think, because, after all, you’re using a single selector to target the element.


  2. //

    I think it’s good to look at points where the CSS parts in Tridion can be improved and kept more consistent. Tools like Stylus or SASS can make this job a lot easier.

    I’m not sure if BEM is the answer though. It seems you can still have inconsistent naming when you work with more than one person.

    I’m also a bit worried about the reusability of the selectors. How will BEM affect the reusability of your selectors?


    1. //

      All on its own, it certainly is possible for BEM to still remain inconsistent because the name of the “block” can be picked arbitrarily. That’s why we chose to forgo any arbitrary name-picking and use the root element of the XML schema, and the schema field XML names. That was what made BEM a winner for the team; the inconsistency was taken out of our hands and pushed into the schema designers.

      Now, reusability of selectors is a great point. Essentially, you don’t get reusable selectors in BEM – and that’s actually kind of the point; a single selector targets a single element with a super low specificity…… and yes, I agree, this makes it sound like a buzz kill to our DRY sensibilities. But, don’t let that dissuade you, CSS pre processors are what make it all better…

      In fact, I’d say that BEM shouldn’t be implemented WITHOUT the help of a CSS pre-processor… because the pre-processor is where you can get DRY again. More on that in the next post.

Comments are closed.