Skip to content

Instantly share code, notes, and snippets.

@JofArnold
Last active December 31, 2016 11:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JofArnold/9dd68e1381c0654b5556f31e841351c6 to your computer and use it in GitHub Desktop.
Save JofArnold/9dd68e1381c0654b5556f31e841351c6 to your computer and use it in GitHub Desktop.
How BEM encourages inflation of code whereas CSS modules compares reduction of code
/*
You have a component called MyComponent.jsx and a decidated "locally scoped"
scss file called MyComponent.scss.
For one of the HTML nodes you wish to add a clearfix using something like:
*/
...:after {
clear: both;
content: ".";
display: block;
height: 0;
overflow: hidden;
visibility: hidden;
}
/*
If you take BEM very literally and you want everything locally scoped you don't
really want to use utility functions. So what you might be tempted to do is
create a mixins file such as mixins/utilities that contains:
*/
@mixin clearFix {
&:after {
clear: both;
content: ".";
display: block;
height: 0;
overflow: hidden;
visibility: hidden;
}
}
/*
So for your top level node you'll be doing:
*/
.MyComponent {
@include clearFix;
}
/*
Which outputs the CSS
*/
.MyComponent:after {
clear: both;
content: ".";
display: block;
height: 0;
overflow: hidden;
visibility: hidden;
}
/*
But with modules you'd have a generic layout file like this:
*/
.clearFix:after {
clear: both;
content: ".";
display: block;
height: 0;
overflow: hidden;
visibility: hidden;
}
/*
Which you'd include by using composes like this
*/
.MyComponent {
composes: clearFix from utils.scss;
}
/*
That doesn't actually output the above, however, but adds the class `clearFix`
to your component instead of the class `MyComponent`.
So what happens when you have MyComponent2 and you want to add clearfix to it?
Well now with BEM again you want locally-scoped styles so you'll probably use
that mixin again and now your code is
*/
.MyComponent {
@include clearFix;
}
.MyComponent2 {
@include clearFix;
}
/*
Which compiles to:
*/
.MyComponent:after {
clear: both;
content: ".";
display: block;
height: 0;
overflow: hidden;
visibility: hidden;
}
.MyComponent2:after {
clear: both;
content: ".";
display: block;
height: 0;
overflow: hidden;
visibility: hidden;
}
/*
I.e. twice as long!
Now you could make the case "well, this is repetion so gzip will solve it. But
the problem is you also have double the selectors which is a performance
overhead for the browser.
Contrast with CSS modules: MyComponent2 simply, again, receives the className
"clearfix". You can imagine how effectively this scales.
There are solutions to this (e.g. using utility files so you don't have
to keep using mixins for BEM-type approaches) but my point is BEM encourages
CSS ballooning and at least some attempts to solve that add global scopes.
And take it from me; when your project is as large as my last company's and
you're dealing with a 15,000 LOC style file and 7,000+ selectors the last thing
you need is global selectors!
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment