-
Notifications
You must be signed in to change notification settings - Fork 2
6. Styling
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.
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
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
notcolor
) - We use full words (think
navigation
notnav
)
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>
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.
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.
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.