Skip to content

Latest commit

 

History

History
194 lines (142 loc) · 5.39 KB

File metadata and controls

194 lines (142 loc) · 5.39 KB

BEM-like naming convention

There are only two hard things in Computer Science: cache invalidation and naming things.

-- Phil Karlton

We've had numerous naming conventions aiming for consistent naming across developers. It's hard.

BEM

Meet BEM. BEM, meaning Block, Element, Modifier, is a front-end methodology coined by developers working at Yandex. Whilst BEM is a complete methodology, here we are only concerned with its naming convention. Further, the naming convention here only is BEM-like; the principles are exactly the same, but the actual syntax differs slightly and is adopted from Harry Roberts guidelines.

It is a very smart way of naming your CSS classes to give them more transparency and meaning to other developers. They are far more strict and informative, which makes the BEM naming convention ideal for teams of developers on larger projects that might last a while. In other words: it exactly fits our needs at Procurios. It isn't a silver bullet, but sometimes feels like one.

BEM splits classes into three groups:

  • Block: The sole root of the component.
  • Element: Represents a descendent of Block that helps form Block as a whole.
  • Modifier: A variant, different state or extension of the Block.

To take an analogy (examples are CSS, but this obviously applies to HTML as well):

.person {
	...
}

.person__head {
	...
}

.person__head--small {
	...
}

.person__head--large {
	...
}

.person--tall {
	...
}

Harry Roberts wrote a great article explaining the BEM syntax. A quote:

The point of BEM is to tell other developers more about what a piece of markup is doing from its name alone. By reading some HTML with some classes in, you can see how – if at all – the chunks are related; something might just be a component, something might be a child, or element, of that component, and something might be a variation or modifier of that component. Think how the following things and elements are related:

.person {}
.person__hand {}
.person--female {}
.person--female__hand {}
.person__hand--left {}

BEMIT

Harry Roberts has extended the BEM naming convention with namespaces and responsive suffixes. We don't use those concepts (yet).

Namespaces

Namespaces are always an issue. Conflicting classnames can mess up layout in various unexpected ways. We don't use an explicit prefix or suffix to namespace classes, because we assume that our Block (Component) names are unique enough. The chance that two Components with the same name are used on the same page is small.

That leads to the following question: do we add complexity to our naming convention or live with the fact that there's a small chance that two Components share the same namespace (which may result in unwanting side effects)? We choose the latter for now, and will reconsider based on proof.

Responsiveness

We solve responsiveness with element queries (read more about those in our CSS style guide).

Text cases

Use camelCase to name your classes

<!-- bad -->
<div class='foo-bar'></div>
<div class='foo_bar'></div>
<div class='foo_bar--Baz'></div>
<div class='foo_bar--baz'></div>
<div class='FOOBAR'></div>

<!-- good -->
<div class='fooBar'></div>
<div class='fooBar__baz'></div>
<div class='fooBar__bazQux'></div>
<div class='fooBar--baz'></div>
<div class='fooBar--bazQux'></div>
<div class='fooBar__bazQux--quux'></div>
<div class='fooBar__bazQux--quuxCorge'></div>

Use PascalCase to name the Block of a Component

At Procurios isolated web components are conveniently named... Component. Mind the capital C. Use PascalCase to name the root Block of a the Component.

<!-- bad -->
<div class='fooComponent'></div>
<div class='foo-component'></div>
<div class='foo_component'></div>

<!-- good -->
<div class='FooComponent'></div>

Syntax

Delimit Elements with two underscores

/** bad */
.FooComponent-footer {
	...
}

.fooComponentFooter {
	...
}

/** good */
.FooComponent__footer {
	...
}

↑ back to top

Delimit Modifiers with two hyphens

/** bad */
.FooComponent-collapsed {
	...
}

.collapsedFooComponent {
	...
}

/** good */
.FooComponent--collapsed {
	...
}

↑ back to top

States

Use is- or has- as suffix for states.

/** bad */
.Panel--collapsed {}
.Panel--collapsing {}
.Menu--hidden {}

/** good */
.Panel--isCollapsed {}
.Panel--isCollapsing {}
.Menu--isHidden {}

File names

Our goal is to move all output of our platform to self-contained, isolated Components. A typical file structure of a Component:

/FooComponent
	/themes
		/1
			/FooComponent.html.twig
			/FooComponent.css
			/FooComponent.js

Please note that all root files have the name of the Component. If you split code into multiple files, use BEM in file names aswell:

/FooComponent
	/themes
		/1
			/partials
				FooComponent__bar.html.twig
				FooComponent__baz.html.twig
			/css
				FooComponent.css
				FooComponent__bar.css
				FooComponent__baz.css
			/FooComponent.html.twig

BEM works great as a model to name your files in any context. Apply the same file naming pattern if you (are unlucky enough to) work outside the context of a Component. Consistent naming rocks!