Uh oh, spaghettios!
Making the grade - Preview Image
chevron

Become a CSS Architect

Make your CSS a more organized mess...

CSS is taking up a larger piece of the pie these days. This is thanks to all of incredible things CSS can now achieve our code is even larger and more complex than it already was. To combat these growing complexities, building modular CSS is has becoming the new buzz topic. For the past few years I have had the chance to develop modular code and styleguides for complex sites and applications at West Virginia University. In that time I have learned some important things about how to develop CSS that can scale quickly and make the development process for one person or a team of people much easier. Let's dig in shall we?

Re-usable code is king

As we all know, CSS is completely driven on cascading elements. The problem with this is many of us write code that encounters too many cascading conflicts. Part of this is attributted to using too many raw HTML elements in our CSS, and simply not sectioning off the items that make up our code. We write code that makes numerous references to the same instance and nest things far too often. The key is to write more intelligent CSS that uses the best practices to minimize code that can be easily navigated and allows for more obvious implementation in our html. This means better understanding the elements your project will need and the variations of each of those components. If you can better plan for the elements you need, you can remove a large sum of code from your base that would otherwise feature bloated code that has too many button, header, and formatting elements that are not written to be re-used.

Normalizing for browsers

Before you begin writing any core CSS for your project you need to set a base for which all elements behave similarly across each browser. Referencing or completely implementing Normalize.css from Nicolas Gallagher is a good starting point. This gives you a solid base to write the rest of your CSS on. No more wondering how each browser is going to handle your buttons, line-heights, inputs, etc.

Understand frameworks, but don't use them

While I applaud frameworks for introducing many people to better re-usable concepts. I hate incorporating any of them into my code. Frameworks are for those people who don't write CSS for a living. If you do, then study frameworks, understand them and establish your own based on the needs of your project. This way you avoid bloating your base code with unnecessary elements. The whole objective here is to develop a modular base for your project, not to adopt something that you will likely only use bits and pieces of throughout your project. This post more so re-affirms my love/hate relationship with frameworks - Living in a CSS world - Architects & Citizens.

Make your CSS object oriented and think about pre-processors

Object oriented CSS, often referred to as Dry CSS should be the corner stone of how you construct CSS. It is the base for writing re-usable and more lightweight CSS. A good article from Louis Lazaris that dives into OOCSS in detail can be found at Smashing Magazine - An Introduction to OOCSS. Mixing OOCSS with pre-processors only increases the effectiveness of it.

Pre-processed CSS presents routes to accelerate and extend your code. Eventually it is something that will be adopted into CSS itself. For now though, CSS.LESS and SASS are the two directions you can go. Having set variables for things like colors and fonts provide you with quick and efficient methods to manipulate those highly used values in your CSS. How many times have you been 75% through a project and wanted to slightly, or drastically adjust a color or font? Time for a search replace party! Pre-processors make those days a thing of the past with variables, mixins, and operations. Additionally you can create pretty complex scenarios to extend headers, buttons, and column or grid based layouts. I could dive into those, but it is best to run through .LESS and SASS to really gain a better understanding of how those all work. For the sake of this article let's stick to SASS. Below is an example of how I would define some re-usable color variables.

            $blue: #0032a0;
            $green: #27ae60;
            $grey: #eee;
            $red: #e74c3c;
            $yellow: #eeb111;
        

Organize your CSS files

In the past it was pretty common to have all of your CSS slammed into one epic file. It was painful to navigate, and often was filled with tons of duplicated elements which were coupled with far too much nesting. Lately more and more folks have started breaking things down into smaller more managable files. For the most part most of us still don't sort our CSS into logical areas though. If a certain section of our code becomes large it might get its own file, but that still doesn't make for a code base that is easy to sort through. In the past few years, through plenty of trial and error I have developed a process that has made my CSS base much more managable. Below is an outline for how I approach this.

Foundation/Base level

This is where all my code for variables and mixins go from a pre-processor. I also focus on defining extendable code (also a pre-processor method), and then move onto normalizing, and setting the base properties for my CSS. This mostly consists of root level html, body, and generic styling for forms and tables

Framework level

This is the level where I break out various commonly used rule sets into their own CSS files. Most of the time this consists of button definitions and the development of the grid I plan to use to shape the site. Depending on the size and type of project there could also be stylesheets for forms, tables, and headers. Each of these are rule sets which I could end up referrencing tens or hundred of times in my code. This can lead to major cascading issues down the road. It is best to summarize what you need from each of these by developing base re-usable blocks. Further down I will go into a bit more detail about this.

Cosmetic level

At this point your site/application should have a well defined CSS core to build on. This is where page specific cosmetic pieces are developed. Most of your time will be spent tweaking these styles as you develop your product. The Foundation and Framework bits may need tweaked along the way, but keeping them out of the cosmetics makes for much cleaner and easier to manage code. Cosmetics define how the content is laid out within each content block. Things like how images and content come together, and how buttons and headings should be positioned are addressed here. I also define element positioning concerning how each content block works responsively. You may need to define flexbox ordering and layouts for these. Getting the most out of pre-processors will allow you to have re-usable flexbox references that can be extended from foundation CSS that you can easily plug right into any cosmetic area. The more you work with the concept of constructing levels of CSS, the faster you will be at developing complex scenarios for your interface. Here is a small example in SASS of how that may come together.

Foundation level CSS Extender

            // SASS EXTENDER -- FLEXBOX PARENT -- INCLUDES TABLE (OLD SPEC)
            .flexbox-parent {
                // OLD CSS SPEC
                display: table;
                // NEW CSS SPEC
                display: -webkit-box;
                display: -moz-box;
                display: -ms-flexbox;
                display: -webkit-flexbox; // Safari fallback
                display: flex;
            }
            // SASS EXTENDER -- FLEXBOX CHILD -- INCLUDES TABLE-CELL (OLD SPEC)
            .flexbox-child {
                // OLD CSS SPEC
                display: table-cell;
                // NEW CSS SPEC
                display: -webkit-box;
                display: -moz-box;
                display: -ms-flexbox;
                display: -webkit-flexbox; // Safari fallback
                display: flex;
            }
        

Cosmetic level implementation of Foundation extender

            // CSS THAT INCLUDES SASS FLEXBOX EXTENDER
            .feature-block {
                @extend .flexbox-parent;
                background: #fff;
                width: 100%;
                height: 20em;
            }
            .feature-child {
                @extend .flexbox-child;
                background: $grey;
                width: 10em;
                height: 10em;
            }
        

The two CSS snippets above show you how you can create pretty detailed extenders in SASS and easily add them to any rule set in CSS. In the CSS output, you will still have as much code as you would writing those out in each rule set, but the speed you save extending rules into other rule sets is a huge time saver.

Everything gets a class

Targeting HTML elements is not a practice you should make use of. It leads to cascading conflicts, or overly complex nesting. Giving everything you can a class name gives you greater control over your elements, and leads to much cleaner and less nested CSS. As a rule of thumb I try to never go deeper than 3 levels and most of the time I try and draw the line at 2. If you have gone farther than this, you need to break those elements out. Using practical class names will make this all much easier. A good practice I tend to stick to is substring naming. An example of this in use would be with buttons. Typically, you have 3 to 4 types of buttons on any website. Submit, cancel, view, and in some cases caution. For each of these I start by creating a complex button mixin in SASS. Let's have a look.

Framework level button mixin code

            @mixin button-layout($button-background-color, $button-font-color, $button-height) {
                display: inline-block;
                vertical-align: top;
                margin: 0;
                padding: 0 1em;
                background: $button-background-color;
                border: none;
                border-radius: $button-height / 2;
                height: $button-height;
                font-family: $site-text;
                font-size: 1em;
                line-height: $button-height;
                text-decoration: none;                
                color: $button-font-color;
                cursor: pointer;
                &:hover {
                    background: darken($button-background-color, 10%);
                }
                &.active {
                    background: lighten($button-background-color, 10%);
                    &:hover {
                        background: darken($button-background-color, 10%);
                    }
                }
            }
        

Here I have a mixin that defines the parameters for what I would like my button to look like, and a general set of rules for how it should interact with its surrounding elements. I gave the mixin some general color properties as well, but our substring classes will overrule these. Additionally I have defined the hover and active states with pre-defined hover color adjustments. With this mixin I can now focus on button colors and sizes when I prepare my button classes. Take a look at how I use the mixin within a rule set to complete my buttons.

Framework level implementation of the Framework mixin for my buttons

            [class^="button"] {
                @include button-layout($grey, #000, 2.5em);
                &[class*="submit"] {
                    @include button-layout($green, #fff, 2.5em);
                }
                &[class*="cancel"],&[class*="close"] {
                    @include button-layout($red, #fff, 2.5em);
                }
                &[class*="view"] {
                    @include button-layout($blue, #fff, 2.5em);
                }
                &[class*="view"] {
                    @include button-layout($yellow, #fff, 2.5em);
                }
            }
        

As you can see, to have 4 set types of buttons I needed only 12 lines of code. Moving forward if I decide I want to adjust the looks of the buttons on the site I simply adjust the mixin and if need be, adjust the colors and sizes for each button class. Also notice that I am only looking for elements that start with the class name button. If the element starts with any other text these styles will not be used. In addition to the class needing to start with button I then connect substrings to the word button. Now if I want a submit button all I need to do it write out the following.

            
        

Substringing class names is a productive concept when an element could have numerous styles attached to it but be cautious not to over do it. An example would be if I also want this button to animate when it is hovered. I wouldn't add -animated to button-submit. I would add a separate class to the element called animated. In addition I would do the same for display properties, or position properties. The button itself has its own framework level properties that include some base cosmetic properites. Decisions over whether it should animate, where it should be in relation to sibling elements, and its higherarchy on the page aren't core button dependencies as much as they are interface layout decisions that need to happen in the cosmetic level of my CSS. Having a class of button-submit-top-animated would lead to cosmetics level interface decisions filling up your button rule set. These cosmetic level decisions need their own rule sets as they will likely be used again in other buttons and potentially other elements. Simplifying the naming to button-submit top animated handles the task much better from an OOCSS standpoint.

            
        

Depending on what your project is, you may or may not need to also develop a styleguide page or pages. If you are putting together a small website, this is not necessary. However, if you are working within a team and the project is on a much larger scale, you definitely need to have extensive examples of how everything works together. These pages need to showcase simple buttons, complex animating buttons, forms, tables, and any of the other essential pieces of your project. Ultimately, the goal of writing CSS in a more structured way is not only to make your job easier, but to make the code, and how it is worked with from all ends an easier process. Moving forward, you will save yourself a lot of grief with a well structured set of CSS Stylguides.

Writing cleaner code, sorting out your files, and providing extensive documentation is a great deal of work. CSS has become so expansive that these kinds of details are now necessary in order to have modular code that can be dealth with on a personal and team level. Hopefully this can all provide greater inight for how to manage any project you might be working on. If you have any thoughts or questions I would be happy to hear them!