Components for Implementing a Modular CSS Philosophy - Part 2

0 min read
Leah Wagner
Moving right along from my first post, you will remember covering four of the five categories of code that are used to implement a Scalable and Modular Architecture for CSS or SMACSS. In this post, we will uncover the fifth and final category -- components.
We are dedicating this entire post to this one category, because there is much more to dive into. So, lets go! Firstly, what is a component? A component is a page element that is generic enough to remain reusable, while specific enough to not conflict with other styles. For instance, when you have a teaser block displaying a recent blog post. This may have an image, title, and a bit of text. In this case, the image floats to the left and the text sits to the right. You would then style the text to be a certain colour and font size. This element could be considered a component. This means it could be reused in the same arrangement for another piece of content, like an event.
Components should be able to move around the page without breaking. This means, your styles should not link to a particular page region, or contain layout related attributes (read more about applying layout styles in my previous post). That’s it -- the 30 second introduction! Lets continue reviewing with a few examples. I always find this exercise to be helpful!
Lets take a look at a typical listing that the Views module would create for us.
<div id="block-view-1" class="view"> <h1>My views listing title</h1> <ul> <li> <h3><a href="/node/1">Lorem Ipsum Dolor</a></h3> <p>Lorem ipsum dolor sit amet, consectetur adipiscing.</p> </li> <li> <h3><a href="/node/2">Lorem Ipsum Dolor</a></h3> <p>Lorem ipsum dolor sit amet, consectetur adipiscing.</p> </li> <li> <h3><a href="/node/3">Lorem Ipsum Dolor</a></h3> <p>Lorem ipsum dolor sit amet, consectetur adipiscing.</p> </li> </ul> </div>
In this case, we have a block with an id of #block-view-1. Our first task for this block would be to apply some basic styling.
#block-view-1 li { border-bottom: 1px solid #CCC; padding: 20px 0; } #block-view-1 h3 a { color: #333; } #block-view-1 p { font-style: italic; }
As our site begins to grow, we now need another block, #block-view-2 which, requires the same styling.
#block-view-1 li, #block-view-2 li { border-bottom: 1px solid #CCC; padding: 20px 0; } #block-view-1 h3 a, #block-view-2 h3 a { color: #333; } #block-view-1 p, #block-view-2 p { font-style: italic; }
This is NOT an example of SMACSS. Here, we are duplicating code. Having said that, this code would be easy to maintain -- it’s just not ideal. The worse case scenario would be that #block-view-2 gets put in a separate area of the stylesheet. Then, #block-view-1 would potentially get updated and those changes wouldn’t be reflected in #block-view-2.
The improved modular approach is to define a reusable class. In addition, the class needs to describe the content being displayed clearly and specifically. A class of .view-list is not specific enough, because different content can exist in a list. Also, .blog-teaser-list is too specific because a title/body list could be used on other content types. Here, I would probably use .list-title-body.
.list-title-body li { border-bottom: 1px solid #CCC; padding: 20px 0; } .list-title-body h3 a { color: #333; } .list-title-body p { font-style: italic; }
Now, when we have a need for the third block that requires the same styling, we simply have to apply this reusable class. At that point, there will be no edits to the CSS file required.
Consequently, this one class now styles all three of the list blocks.
<div id="block-view-1" class="list-title-body"> <h1>My views listing title</h1> <ul> <li> <h3><a href="/node/1">Lorem Ipsum Dolor</a></h3> <p>Lorem ipsum dolor sit amet, consectetur adipiscing.</p> </li> <li> <h3><a href="/node/2">Lorem Ipsum Dolor</a></h3> <p>Lorem ipsum dolor sit amet, consectetur adipiscing.</p> </li> <li> <h3><a href="/node/3">Lorem Ipsum Dolor</a></h3> <p>Lorem ipsum dolor sit amet, consectetur adipiscing.</p> </li> </ul> </div>
There is the possibility that every listing on your site is NOT going to look the exact same. Actually, that’s probably guaranteed. Continuing with this example, let’s say that #block-view-2 needs an alternative style. In this case, we need to apply a grey background to every other list item. How would we approach this?
Let’s start by reviewing what we DO NOT want to do:
1. Revert back to using #block-view-2. This will give us a style that is not reusable. This isn’t useful because we may have need for this style somewhere down the line.
// DO NOT #block-view-2 li:nth-child(2n) { background: #DDD; }
2. We are not going to apply a class to the ul list to add this style. When implementing SMACSS, you want all of your styling applied at the first level. In this case, that would be the .list-title-body. This reduces the need for deep nesting which, can cause CSS conflicts.
// DO NOT .list-title-body ul.striped li:nth-child(2n) { background: #DDD; }
Instead, we create a subcomponent. A subcomponent extends the styles of the original class, but then makes the necessary modifications. Your subcomponent will extend the same naming convention as your original component. I like using “--” to separate my subcomponent identifiers. This is also defined in the BEM philosophy. In this case, I have chosen --stripped to define the override that we are implementing.
.list-title-body--striped li:nth-child(2n) { background: #DDD; }
Now, we add the newly created subcomponent class to our listing, while still keeping our original component class style.
<div id="block-view-2" class="list-title-body list-title-body--striped"> <h1>My views listing title</h1> <ul> <li> <h3><a href="/node/1">Lorem Ipsum Dolor</a></h3> <p>Lorem ipsum dolor sit amet, consectetur adipiscing.</p> </li> <li> <h3><a href="/node/2">Lorem Ipsum Dolor</a></h3> <p>Lorem ipsum dolor sit amet, consectetur adipiscing.</p> </li> <li> <h3><a href="/node/3">Lorem Ipsum Dolor</a></h3> <p>Lorem ipsum dolor sit amet, consectetur adipiscing.</p> </li> </ul> </div>
When implementing the subcomponent, I try to stick to a single subcomponent. Say, I was styling a button. This is when I could take the approach of multiple subcomponents. For instance, I could add .button, .button--green, .button--inline, .button--rounded. This starts to feel like I am implementing inline CSS. Instead, I would define .button--green-inline-rounded.
However, this does have drawbacks. In the first example, if I no longer wanted rounded corners, I would simply remove .button--rounded. In my second example, I would define a new style -- .button--green-inline. You’ll have to individually weigh the pros and cons to see what works best for your projects.
There are other tools that can help us combat these dilemmas -- like using SASS. We’ll get there! I wanted to first introduce you to this concept, without adding a SASS dependency. It is not a requirement. Even without taking that next step, you’ve still been able to implement a stable, reusable, modular CSS infrastructure.
Up Next...
We are going to introduce SASS. We will review how SASS can help you streamline your components, compile your files, and more. We will also touch on naming conventions and file organization.