For the last couple of months I’ve been thinking a lot about giving our css best practices a refresh
and along the way have looked at approaches such as OOCSS, SMACSS, and
DRY CSS. They all have some common underlying principles, one of which
is the separation of structure and presentation.
We’ve all had this goal for years, but our practices haven’t really achieved it. Instead of decoupling our html and css we’ve been locking them ever tighter and making them more and more dependent on each other. I apologize if you’re getting tired of hearing me talk about coupling, but I think it’s a very important concept to understand if you want to develop scalable and maintainable websites.
I want to touch on a few of the points and then give a quick walk through of yet another method (BEM) with similar goals to the ones we’ve been talking about.
All agree we should move away from location based selectors as tying css selectors to a specific html structure leads to greater difficulty in changing either html or css. Inevitably we’re left managing specificity.
Jonathan Snook refers to this as the depth of applicability or in his words, “the depth at which a particular rule set impacts the elements around it.”
For example consider the following code for a relatively simple navigation bar with a single drop down.
If we were to write some css targeting the link in the drop down (
#nav li a ), the depth of applicability is 5. Even though we didn’t
specifically mention every element along the way we’ve moved through
ul#nav to li to ul to li to a, or 5 levels of html structure.
That’s too much and it also affects both the top level links and secondary links in the drop down. Jonathan offers two ways to reduce the depth of applicability
The key is in seeing that many of the selectors we’ve been using over the years are coupling our html and css ever tighter. The debate is still ongoing as to the best way to decouple things, though hopefully you agree there’s a need for decoupling.
At the highest level of a design, your blocks might be your header block, footer block, main content block, and sidebar block. Your header would likely include several blocks inside such as one for your logo and tagline, another for a navigation bar, and maybe another making up a search field and button.
Elements are parts of blocks. They perform certain functions within the block and they’re context dependent. Take an element outside its block and it no longer makes sense. For example a search block might be made up of 2 elements.
Together blocks and elements are arranged in your design to form your page layout. Elements are arranged inside blocks and blocks are arranged inside other blocks working up to the outermost container blocks that shape the page as a whole.
Blocks and elements should have keywords (names) associated with them. The only way the same name or keyword is reused is when the same block or element is being reused. Blocks must be independent of each other to allow for arbitrary placement within the design. We want to be able to take our search block and easily move it from the top right in the header to the middle of the sidebar for example.
This leads to 3 guidelines for writing css:
You’d then added class=”current” to the currently selected menu item.
The class modifies one element inside your navigation block.
BEM goes a lot further than what I’ve described above. In fact it’s for more than just html and css. It covers behaviors with Javascript, though the same basic principles and approach apply. I’ll let you read the original source if you’d like more details. I mainly wanted to show you the basic approach.
The idea of seeing a web page as elements within blocks within blocks is an easy one to grasp and probably how many of us already view the pages we develop. I certainly have, as you can see in a couple of posts I wrote for Onextrapixel a couple years back.
Most of these methods are similar in their underlying goals and principles, which is the main thing to be paying attention to. You’ll likely pick and choose techniques across some of these approaches depending upon the specific problem in front of you as opposed to following any one entirely.
It’s the underlying principles like decoupling html and css that are more important. It’s the idea of reducing location based selectors, mostly likely through a greater use of classes that you should be thinking about. See how each approach attempts to solve this and decide which makes the most sense for you.
If you’re getting tired of these posts please let me know. I realize I’ve been offering a lot about this same basic concept for awhile and perhaps the message has long since gotten across. If you are enjoying these posts and some of the methods I’ve been pointing to, let me know as well. There are more approaches out there with similar goals in mind that I could cover.
We’ve all had this goal for years, but our practices haven’t really achieved it. Instead of decoupling our html and css we’ve been locking them ever tighter and making them more and more dependent on each other. I apologize if you’re getting tired of hearing me talk about coupling, but I think it’s a very important concept to understand if you want to develop scalable and maintainable websites.
I want to touch on a few of the points and then give a quick walk through of yet another method (BEM) with similar goals to the ones we’ve been talking about.
Decoupling HTML and CSS
Ideally we’d like to be able to completely rewrite our html or css without touching the other. That’s unlikely to happen all the time. There will often be a need to changes one after changing the other. However the less dependent our html and css are on each other, the better. Using OOCSS we reduce coupling by dropping descendent selectors in favor of classes. With a DRY CSS approach we’re also using classes, but here the magic is based more on how we organize our css around stylistic groups. SMACSS falls somewhere in between these approaches.All agree we should move away from location based selectors as tying css selectors to a specific html structure leads to greater difficulty in changing either html or css. Inevitably we’re left managing specificity.
Jonathan Snook refers to this as the depth of applicability or in his words, “the depth at which a particular rule set impacts the elements around it.”
For example consider the following code for a relatively simple navigation bar with a single drop down.
1 2 3 4 5 6 7 8 9 10 |
<ul id="nav">
<li><a href="">Item 1</a></li>
<li><a href="">Item 2</a>
<ul>
<li><a href="">Sub Item 1</a></li>
<li><a href="">Sub Item 2</a></li>
</ul>
</li>
<li><a href="">Item 3</a></li>
</ul>
|
That’s too much and it also affects both the top level links and secondary links in the drop down. Jonathan offers two ways to reduce the depth of applicability
- Child selectors — using #nav > li > a limits the scope to the top level links
- Class selectors — is ultimately the better approach as it’s not dependent on html structure at all
The key is in seeing that many of the selectors we’ve been using over the years are coupling our html and css ever tighter. The debate is still ongoing as to the best way to decouple things, though hopefully you agree there’s a need for decoupling.
BEM — Block, Element, Modifier
The BEM approach to developing websites comes from the developers at Yandex. It has similar goals to the approaches we’ve seen before.- Quick development
- Team efficiency
- Scalability
- Code reuse
Blocks and Elements
Under BEM a block is it’s own independent entity. Blocks can be simple or complex and they can contain other blocks. There’s something familiar in this as every html element is displayed as a box or block of some kind.At the highest level of a design, your blocks might be your header block, footer block, main content block, and sidebar block. Your header would likely include several blocks inside such as one for your logo and tagline, another for a navigation bar, and maybe another making up a search field and button.
Elements are parts of blocks. They perform certain functions within the block and they’re context dependent. Take an element outside its block and it no longer makes sense. For example a search block might be made up of 2 elements.
- Input field
- Button
Together blocks and elements are arranged in your design to form your page layout. Elements are arranged inside blocks and blocks are arranged inside other blocks working up to the outermost container blocks that shape the page as a whole.
Blocks and elements should have keywords (names) associated with them. The only way the same name or keyword is reused is when the same block or element is being reused. Blocks must be independent of each other to allow for arbitrary placement within the design. We want to be able to take our search block and easily move it from the top right in the header to the middle of the sidebar for example.
This leads to 3 guidelines for writing css:
- Blocks should have unique names, which become classes
- HTML elements should not be used in css selectors since they aren’t context-free
- Cascading selectors for several blocks should be avoided
Modifiers
What happens when you have a block like a search input and button and you want to add another to the page that looks similar, though not exactly like the first? This is where modifiers come in. Modifiers help us create similar though different blocks from already existing blocks.A modifier is a property of a block or an element that alters its look or behavior. A modifier has a name and a value. Several modifiers can be used at once.Typically a modifier will be an additional css class you would add to an element. An example I’m sure you’ve come across is highlighting the currently selected menu item so it stands out from the rest of the menu items. To achieve this you probably created css similar to the following.
1 2 3 |
.current {
background: #f00;
}
|
BEM goes a lot further than what I’ve described above. In fact it’s for more than just html and css. It covers behaviors with Javascript, though the same basic principles and approach apply. I’ll let you read the original source if you’d like more details. I mainly wanted to show you the basic approach.
The idea of seeing a web page as elements within blocks within blocks is an easy one to grasp and probably how many of us already view the pages we develop. I certainly have, as you can see in a couple of posts I wrote for Onextrapixel a couple years back.
- Part 1: How to Turn a Design Image Into a Working Web Page
- Part 2: How to Turn a Design Image Into a Working Web Page
Summary
Again I hope I’m not repeating myself too much in all these posts, but these concepts are important ones to understand. Ultimately I think we should be rethinking some of our css practices as they haven’t been as great as we’d like to believe. Many have been thinking the same thing and over the last few years we’ve seen quite a few new methods and approaches for writing html, css, and javascript.Most of these methods are similar in their underlying goals and principles, which is the main thing to be paying attention to. You’ll likely pick and choose techniques across some of these approaches depending upon the specific problem in front of you as opposed to following any one entirely.
It’s the underlying principles like decoupling html and css that are more important. It’s the idea of reducing location based selectors, mostly likely through a greater use of classes that you should be thinking about. See how each approach attempts to solve this and decide which makes the most sense for you.
If you’re getting tired of these posts please let me know. I realize I’ve been offering a lot about this same basic concept for awhile and perhaps the message has long since gotten across. If you are enjoying these posts and some of the methods I’ve been pointing to, let me know as well. There are more approaches out there with similar goals in mind that I could cover.
No comments:
Post a Comment