As websites grow and become more complicated, you don't want to end up in a state of disarray.
Continuing from my first blog post (Episerver 10 Alloy MVC), lets configure the Alloy MVC project to use ITCSS and BEM for structuring your front-end needs. I believe it is very important to have a solid approach when structuring your Episerver website styling needs. As websites grow and become more complicated, you don't want to end up in a state of disarray or the dreaded !important hell 😬.
During my most recent endeavor, I worked on an Episerver project that was very challenging, and pushed me to create some really cool features on an aggressive timeline. One of the many good takeaways I learned from this experience, was how ITCSS and BEM can make your front-end life a lot easier. Yes, learning and implementing something new took a little more time to create, but the time saved in the long run especially in regards to “technical debt” was time well spent.
If you are not familiar with ITCSS, it is a methodology that stands for “Inverted Triangle Cascading Style Sheet”. ITCSS helps you structure and understand how to break apart your CSS into manageable layers. Below is a picture of the inverted triangle and descriptions for each of the layers.
Let's go over each of those layers and explain the purpose
Settings - used for preprocessors to setup global settings like font size, font colors, definitions, etc. No CSS
Tools - used for preprocessors to setup global mixins and functions. No CSS
Generic - houses high level styles that handle things like box-sizing and normalizing browsers. This is where I put normalize.css (https://github.com/necolas/normalize.css).
Elements - styling for HTML elements without class assignments (like a h1, p, body. etc.). This is usually very simple styling. Example: set HR element's margin and padding to 0.
Objects - HTML elements with class assignments for non-cosmetic styles. Mostly used for containers, layout systems, etc.. Example: all classes with “container” will center align children using margin left and margin right of auto.
Components - This is where most of the work is done to style pages, blocks and views. I usually create sub directories for each purpose (blocks, pages, partials, etc..).
Trumps - this is where you add any overrides for anything. This is where !important would be used. I usually don't have much if anything is this directory.
As you just read, coupling ITCSS with a preprocessor like Sass (SCSS) can make life a lot easier. Being able to setup Sass variables and mixins allows you to be DRY (don’t repeat yourself) and encourage reusability. For the sake of simplicity and understanding how to use ITCSS, I will take the approach of using vanilla CSS. This means some folders will be empty since functionality like variables and mixins are not available.
Let's continue; basically the idea is to cut down or eliminate any overrides until it is absolutely necessary. When you organize, and layer your CSS in a specific manor - you start to structure and tackle your front-end styling differently. This especially bodes well for large multiple site instances within a single Episerver web property. ITCSS gives you the flexibility to separate your layers that might have brand specific constraints, plus allows you to use shared styles across brands.
Implementing BEM naming is fairly straight forward and like everything, you get better at it over time. This is especially true on larger projects. BEM stands for Block Element Modifier and helps you label your element's CSS class names based on the element’s purpose. I strongly recommend you learn more about BEM from getbem.com and watch the following YouTube video called “Introduction to BEM - A front-end methodology”.
My interpretation/experience has been that the BEM naming methodology makes you take a hard look at your intentions and refactor your code into concise blocks. This pattern fits really well when you are building Episerver websites that are block and contentarea heavy. BEM and Episerver blocks feel a lot like the Web Components isolation movement, but from a server-side approach. The ability to sandbox your block's style and functionality is very powerful and allows for the creation of a dynamic web property managed within a web content management system.
Now that you have a high level understanding of what ITCSS and BEM can do, let's look at some code examples.
The following is the HTML rendered for a Teaser Block in the Alloy MVC starter project. This is a good example of a BEM block. The wrapping div element has the “teaserblock” class identifier and the descendant elements (h2, p, div, img) have the “teaserblock__” prefix to indicate that they are within this block.
Now let’s look at the project directory structure for ITCSS. The screenshot blow shows how I created separate folders for each of the layers needed. I prefixed a number to each of the folders to help remember the layering order. For the TeaserBlock, you can see it has its own Component and Trump CSS files. As a side note - the Trump was needed since I needed to override Twitter’s Bootstrap framework that was packaged along with the Alloy MVC project.
The following screenshots are the CSS code for the TeaserBlock’s Component and Trump files (respectively).
The example I discussed above is available out on my Github account (Episerver-AlloyMVC-ITCSS-BEM). I basically fired up a new Alloy MVC project, upgraded it to 10.10, and started to replace the traditional CSS files (style.css and media.css) with ITCSS and BEM. I only updated a few things for the blog post (Teaser Block, Jumbtron Block, etc..) and I encourage you to pull the code down and complete the rest of conversion. I think this is a great way to wrap your head around what was discussed and put that knowledge to work in a stable environment.