Skip to content
This repository has been archived by the owner on Jan 6, 2020. It is now read-only.

6. Styling

Jon Roobottom edited this page Jan 4, 2016 · 1 revision

If the acronym BEM fills your eyes with child-like wonder and your heart with delight then you've come to the right place! Yes, the rumours you've heard are true, we do indeed use BEM as our main methodology for styling of the DOM in Firefly.

If you're new to BEM a good place to start is this article on CSS Tricks. What follows is a description of the particular flavour of BEM we use round these parts, what we like to call Firefly-BEM.

Top level name-spaces

It shouldn't come as any great surprise that the top level name spaces we use for our classes match the types of blocks in the pattern library, namely:

  • ff_grid
  • ff_container
  • ff_module
  • ff_util
  • ff_icon

Blocks

You guessed it, the "B" in "BEM" stands for "Block". No great shakes, but what does that mean when writing styles in Firefly? Well, in Firefly-BEM the Block consists of namespace + block so for the salad spinner, that's:

ff_module-salad-spinner

Some rules:

  • A block is always a namespace + block
  • We hyphenate-our-bock-names
  • We use British-English spelling (think colour not color)
  • We use full words (think navigation not nav)

Elements

Wow, you're really getting good at this! As you've rightly guessed, "E" stands in stead of "Element". These are separated from the block with a double underscore __ like this:

ff_module-salad-spinner__leaves

Some rules:

  • Elements don't cascade, i.e. this is a no-no ff_module-salad-spinner__leaves__leaf.
  • Elements don't inherit, i.e. they should be self-contained and never rely on parent styles or the addition of other classes.
  • When you do have a natural parent-child element situation, use names that suggest the link, for example:
<ul class="ff_module-salad-spinner__leaves">
	<li class="ff_module-salad-spinner__leaf">Sarah Student</li>
	<li class="ff_module-salad-spinner__leaf">Peter Pupil</li>
</ul>

Modifiers

Don't tell me you fell at the last hurdle and you thought "M" stood for "Monkey"? Well, let me tell you, you're wrong, as it really stands for "Modifier". True fact. Modifiers are separated from the element with double dashes -- like this:

ff_module-salad-spinner__leaf--large

Some rules:

  • A DOM-element only ever has one modifier, for example:
<li class="ff_module-salad-spinner__leaf ff_module-salad-spinner__leaf--large">
  • A modifier (unlike an element) does inherit, but only every directly from it's parent element.

is-Modifiers

In Firefly-BEM we've added another type of modifier for styling of state, for example:

ff_module-salad-spinner__leaf--is-active

Some rules:

  • a DOM-element can have any number of is-modifiers, and these can sit along side a singular modifier, for example:
<li class="ff_module-salad-spinner__leaf ff_module-salad-spinner__leaf--large ff_module-salad-spinner__leaf--is-active ff_module-salad-spinner__leaf--is-selected">
  • is-modifiers are the only classes that can be added or removed via Javascript. This in itself should give you a sizeable clue when to use is-modifiers and not a modifier.

Mixins

With very little cascade, this could lead to code-bloat, i.e. repeating of many styles. We get around this problem by use of mixins. For example, in this .less file:

#ff_module-salad-spinner() {
	.circle() {
		border-radius: 50%;
		overflow: hidden;
	}
}

.ff_module-salad-spinner {
	
	&__leaves {
		#ff_module-salad-spinner > .circle();
		border: 1px solid @varible_for_border_colour;
	}
	
	&__branches {
		#ff_module-salad-spinner > .circle();
		border: 1px solid darken(@varible_for_border_colour,10%);
	}

}

Of course, there are also global mixins for use cross blocks, defined in the following places:

  • For general styling, in /_shared/mixins.less
  • For text styling, in /ff_util/ff_util-prose/ff_util-prose.less

If you spot a mixin defined in another block that you think would look good in your code, have a lovely chat with its author and see if you can't both agree on a global you can both use to further reduce the code-base.