CSS Specificity
Or: How I learned to stop worrying and love the BEM
-- Phil Karlton
"There are only two hard things in Computer Science: cache invalidation and naming things."
Why is naming hard in CSS?
-
Collaboration
-
CSS Specificity
CSS Specificity
h1 {
color: blue;
}
h1 {
color: black;
}
<h1>Title</h1>
In general, later CSS rules override earlier ones.
CSS Specificity
.title {
color: red;
}
h1 {
color: black;
}
<h1 class="title">Title</h1>
Order is overruled by "specificity," which is determined by the selector you use (element, class, id, etc.)
h1.title {
color: blue;
}
Combining multiple selectors adds their specificity "score" together.
CSS Specificity
#foo {
color: blue
}
.bar {
color: red;
}
h1 {
color: black;
}
h1 {
color: #BADA55 !important;
}
Inline Styles
<h1 style="color: green;">Title</h1>
IDs
Elements
Classes
!important trumps everything else
CSS Specificity
#foo {
color: blue
}
.bar {
color: red;
}
h1 {
color: black;
}
section.article .title {
color: purple;
}
1000
<h1 style="color: green;">Title</h1>
0100
0001
0010
Specificity can be calculated using a "point" system.
0021
CSS Specificity
BEM
BEM is a naming convention which helps you keep your CSS specificity "flat"
Advantages
- It's descriptive
- Class names hint at the markup structure
- Separation of concerns
- Everything you select in your CSS has its own class
- Modifiers represent tweaks
- One CSS selector won't overwrite another
- Nearly all rules have 0010 specificity
BEM
BEM is a naming convention which helps you keep your CSS specificity "flat"
Disadvantages
- It's ugly
- It could be more descriptive
- Namespacing enhances this
BEM
BEM stands for Block Element Modifier
Block: An abstract component
Element: A descendant or relative of the block, which helps form the block
Modifier: A different state or version of a block or element
.person {} // Block
.person__hand {} // Element
.person--female {} //Modified block
BEM
.person {} // Block
.person__hand {} // Element
.person--female {} //Modified block
.person__hand--left {} // Modified Element
.person--female__hand {} // Element of a modified (type of) block
.modal {} // A modal popup
.modal--open {} // Styles the modal when open
.modal__header {} // The header of a modal
.button {} // Basic button styles (can include defaults)
.button--alert {} // Styles to make the button red
.button--small {} // Styles to make the button small
In practice...
Or...
BEM
.modal {
display: none; // Hide by default
width: 500px; // Base styles, etc.
}
.modal--open {
display: block; // Show the modal.
}
.modal__header {
text-transform: uppercase; // Modal headers are uppercase
}
CSS
<div class="modal modal--open">
<h1 class="modal__header">Signup Successful!</h1>
<p>You are now a member.</p>
</div>
HTML
BEM
.button {
padding: 10px; // Padding around text
background-color: grey; // Default background color
color: black; // Default text color
}
.button--success {
background-color: green;
color: white;
}
.modal__button {
float: right; // Modal buttons are on the right side
}
CSS
<div class="modal modal--open">
<h1 class="modal__header">Signup Successful!</h1>
<p>You are now a member.</p>
<button class="modal__button button button--success">DONE</button>
</div>
HTML
Separation of concerns!
BEM
<div class="modal modal--open">
<h1 class="modal__header">Signup Successful!</h1>
<p>You are now a member.</p>
<button class="modal__button button button--success">DONE</button>
</div>
HTML
This represents both a feature and a limitation of BEM.
A BEM class cannot have more than one element or one modifier, so at some point you must name a new block.
<div class="modal modal--open">
<h1 class="modal__header">Signup Successful!</h1>
<div class="modal__body">
<p class="modal__body__paragraph">This is not BEM!</p>
<p class="modal__paragraph">This is BEM.</p>
</div>
</div>
When not to BEM
<div class="header">
<img class="site-logo" src="logo.png">
</div>
<div class="header">
<img class="header__logo" src="logo.png">
</div>
Is the site-logo styled a certain way because it's in the header? Probably not, but if so...
Ask yourself:
BEM is just a way of writing classes which imply structure (with elements) and variation (with modifiers).
Not every class name needs __ or --.
Let it help you, not hinder you!
BEM & Sass
.modal {
// Base modal styles
&--open {
// .modal--open styles
}
&__header {
// .modal__header styles
}
&__button {
// .modal__button styles
}
}
Sass's ampersand (&) feature makes BEM super easy to write and read.
<div class="modal modal--open">
<h1 class="modal__header">Signup Successful!</h1>
<p>You are now a member.</p>
<button class="modal__button button button--success">DONE</button>
</div>
.button {
// Base button Styles
&--success {}
&--warning {}
&--small {}
&--large {}
}
The End
- https://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/
- http://getbem.com/introduction/
- https://css-tricks.com/bem-101/
- https://csswizardry.com/2015/08/bemit-taking-the-bem-naming-convention-a-step-further/
CSS Specificity and BEM
By James TW
CSS Specificity and BEM
- 2,727