Introduction
Object Oriented Programming (OOP) is a widely used programming paradigm, typically seen in back-end development languages such as Java, C++, C#, Python, and PHP. It essentially preaches the encouragement of code reuse and, ultimately, a faster and more efficient codebase that is easier to expand, maintain and understand. This is something that is becoming more and more relevant in modern front end environments, especially with the introduction of SASS which encourages the use of a directory structure, I’ll explain this in more detail later.
This post will go over the basics that I consider and implement whenever starting a new front-end development project, and discuss the methodologies behind utilising BEM, SASS and OOCSS to supercharge it. I will also provide a link to the repo I use and maintain for the majority of my static front end projects.
The Principles
BEM Syntax
BEM, or Block, Element, Modifier is a front-end naming methodology which essentially offers a structured way of naming CSS classes to give them more meaning and encourage reusable code that is transparent for other developers. Harry at CSSWizardry wrote a great article explaining this in much more detail, for now I’ll cover the very basics.
The BEM website explains that “The BEM approach ensures that everyone who participates in the development of a website works with a single codebase and speaks the same language. Using proper naming will prepare you for the changes in design of the website.”
The naming conventions mentioned follow the pattern below:
.block {}
Encapsulates a standalone entity that is meaningful on its own. While blocks can be nested and interact with each other, semantically they remain equal; there is no precedence or hierarchy, for example .header {}
.block__element {}
Parts of a block and have no standalone meaning. Any element is semantically tied to its block, for example .header__logo
.block--modifier {}
Flags on blocks or elements. Use them to change appearance, behavior or state, for example .button–success {}
SASS
The SASS website gloats that it is “the most mature, stable, and powerful professional grade CSS extension language in the world” and it definitely lives up to it’s claims. Most front-end developers will be more than clued up on this preprocessor, so I’ll just cover the very basics, for a more detailed overview on why you should consider using SASS, there’s a great article by Dan Cederholm at A List Apart.
SASS essentially brings a plethora of new features to vanilla CSS that make larger, more complex codebases much easier to maintain, for example nesting, variables, mixins and much more.
The main feature of SASS I’ll be talking about in this article is the ability to separate your stylesheets into separate files. This allows you to use the @import directive to include the source of your individual files into one master stylesheet, essentially allowing the setup up an object oriented directory structure.
OOCSS
OOCSS or Object Oriented CSS is an approach for writing CSS that’s fast, maintainable, and standards-based, pioneered by Nicola Sullivan, she explains that “It adds much needed predictability to CSS so that even beginners can participate in writing beautiful websites”. It is based on two main principles which are explained in more detail here.
- Separate structure and skin
- Separate container and content
The overall idea is to create a repeating visual pattern, that can be abstracted into an independent snippet of HTML, CSS, and possibly JavaScript. That object can then be reused throughout a site.
Getting Started
As previously mentioned, the introduction of SASS allows for the ability to separate your stylesheets and create a directory, this is the first thing I consider when starting a new project, the boilerplate I’ve created (github repo towards the bottom of this article) has a generic ‘starter point’ with a few preset files, it is structured in an object oriented way as follows:
scss/ | |-- modules/ # Modules | |--_config.scss # project configuration | |--_mixins.scss # include Mixins | |--_maps.scss # include SASS Maps | |-- partials/ # Partials | |--_reset.sass # css reset | |--_grid.scss # grids | |--_buttons.sass # buttons | |--_typography.scss # typography | |--_spacing.scss # padding/margin modifiers | |--_displays.scss # display modifiers | -- main.scss # primary Sass file
To break this down further, I use the main.scss file in the root to pull in all my modules and partials, this means I have one global place to keep track of my imports, as you can see in the below example, the file is incredibly easy to understand and acts as a great place to build my main stylesheet.
// Config files @import "modules/config"; // Partials files @import "partials/reset"; @import "partials/grid"; @import "partials/colors"; @import "partials/buttons"; @import "partials/typography"; @import "partials/padding"; @import "partials/displays";
I use the modules directory for things such as variables, mixins declarations and other things that don’t actually output any CSS. The _config.scss file works as a base and includes global project variables, such as project specific colours, font stacks, responsive breakpoints etc, by default the _mixins.scss stylesheet is also imported here (rather than the main.scss) to keep it nice and tidy. You could break this up to be more granular, for example you may want your project specific colours in another stylesheet, this would sit within the modules folder then be imported through _config.scss.
I use the partials directory to construct the majority of my CSS, using the OOCSS methodology to break the partials up, I create a granular file structure which breaks up structural elements and modifier elements, for example, the _buttons.scss file will build the base button styling for the project, as well as modifiers for each, and nothing more.
The structure of this directory changes slightly for each project, there is also room for expansion, for example you may want a vendor folder, where you can keep files that belong specifically to external libraries, for example, the SCSS for jQuery UI or Bootstrap.
Creating Objects
Now the SASS directory is setup, we can start making some objects, we’ll want to be considering the fact that we’re approaching this project in a modular, object oriented way.
Ideally we’d want a style guide to best approach this, but it isn’t completely necessary – some great examples of style guides, and why they can be so helpful can be found here – they don’t need to be this elaborate, it may be as simple as considering the different font sizes and weights in a methodical way before developing the project. Although this adds a bit of preparation time, it can save time in the long run and serve as an all encompassing guide for expanding the project in the future.
I’ll use font sizing as an example, and show how i’d approach it for this environment.
Font Sizing: Preperation
Instead of applying font sizing to individual elements (for example, .header p.title), we’ll be building some global font sizing selectors. The initial process will be to know the sizes and elements you will be using throughout your site, for example you may have something like the following (very simple) example:
- Heading text – 2.125rem
- Intro Text – 1.125rem
- Paragraphs – 1rem
- Small Paragraphs – 0.875rem
Font Sizing: Converting to Variables
This may not always be relevant, however, font sizing is a good example of a good time to create variables. As we’ve prepared the required global sizes for the project, we can set these up as variables in our _config.scss file (or split into _font-sizes.scss as mentioned earlier) and refer to that throughout the project, this means if anything changes in the future, say you want to increase the heading text to 38px, you’ll only have to change one value.
The following example shows the previously prepared font sizes as SASS variables:
// Global Font Sizes $heading-text: 2.125rem; $intro-text: 1.125rem; $paragraph-text: 1rem; $small-paragraph-text: 0.875rem;
We can then reference these variables throughout the project, for example:
.h1 { font-size: $heading-text; }
However we want to do this in an object oriented way and create a global, reusable class. This can be achieved by utilising the BEM methodology and creating a global modifier class, for example, we could do something like the example below.
Font Sizing: Global Objects
As stated, we don’t want to be attributing these on a per element basis, so instead we’ll be creating a global modifier class within the _typography.scss file for each font size, which will usable throughout the site. Using BEM naming conventions, it would look something like:
// Global Font Sizes Modifiers .p--heading-text { font-size: $heading-text; } .p--intro-text { font-size: $intro-text; } .p--paragraph-text { font-size: $paragraph-text; } .p--small-paragraph-text { font-size: $small-paragraph-text; }
Using this method, we create a class selector that can be applied to any element across the site, for example, we may have a h2 in the sidebar that actually wants to be quite small, there may be default h2 styling already set in your stylesheets that make the aside’s h2 24px, so usually you’d have to target this uniquely, something like .aside h2 { font-size: 16px; } – using the above method, we can simply modify the h2 by adding a global class selector:
<aside> <h2 class=”p--small-paragraph-text”>Sidebar</h2> </aside>
This method can be applied to almost anything, another great example being font colouring.
Going Even Further
As previously mentioned, SASS has a bunch of great features which we can take advantage of for this kind of setup. Take the font-sizing setup previously explained, we can use SASS maps to advance this setup even further.
Font Sizing: Mapping in SASS
SASS Maps bring dimensionality to SASS Lists. Maps are associations of values with a syntax that very closely resembles JSON. Utilising this feature, we can further advance our font-size stack to automatically output a list of class selectors based on one map.
Take the current font-size stack as an example:
// Global Font Sizes $heading-text: 2.125rem; $intro-text: 1.125rem; $paragraph-text: 1rem; $small-paragraph-text: 0.875rem; // Global Font Sizes Modifiers .p--heading-text { font-size: $heading-text; } .p--intro-text { font-size: $intro-text; } .p--paragraph-text { font-size: $paragraph-text; } .p--small-paragraph-text { font-size: $small-paragraph-text; }
This is pretty sweet, but utilising a map, we could minimise that amount of code needed. The first step is to add the variables to a map, as below:
$fontsizes: ( heading-text: $heading-text, intro-text: $intro-text, paragraph-text: $paragraph-text, small-paragraph-text: $small-paragraph-text, );
This is simply creating a comma-separated list of key/value pairs and giving it the variable of $fontsizes, this could be named anything. The next step is to loop through each of these.
@each $fontsize, $size in $fontsizes { .p--#{$fontsize} { font-size: $size; } }
This each loop is essentially going through each key/pair set in the $fontsizes variable, it will assign the key to $fontsize and the value to $size. The class selector (or ID) is generated within the loop, which eventually will output as .p–heading-text etc) and the $size attribute applied to each (in this case ‘34px’. This results in the following output:
.p--heading-text { font-size: 2.125rem; } .p--intro-text { font-size: 1.125rem; } .p--paragraph-text { font-size: 1rem; } .p--small-paragraph-text { font-size: 0.875rem; }
All you’ll need to do to create new selectors is add it to the original map, woohoo – Jason Garber wrote a great article here with a much more detailed explanation of maps. The idea is to use these globally throughout your project, rather than assigning a unique font size on a per-element basis. This could be expanded to a variety of other things, take a look at the boilerplate towards the bottom of the article, I have a couple set up by default including global font sizing, colouring, padding and display.
Real Life Example
I regularly update my front-end boilerplate and have recently been approaching it using the methodologies discussed in this article. For a real life example feel free to grab my starter point from here https://github.com/samuelgoddard/stripped which utilises many of the points discussed above.
The setup uses npm to install packages and grunt to watch / compile everything, essentially all you need to do is pull down the files, run npm install and then run grunt, the default task will watch and compile the CSS for you.
Who would use this and Why?
This methodology and approach to front-end code can be applied to pretty much any project, however it lends itself to a methodical approach, which is best suited for projects utilising a relatively strict setup (IE predefined colour pallets, font sizing etc). Saying that, this approach (IMO) works really well for anything that is going to be worked on by multiple developers or incur common updates in the future.
The main reason behind using these practises for me personally is to encourage a shared codebase that is fast, reliable and incredibly easy to expand. If you don’t want to commit to such an object oriented setup, I’d still highly recommend checking out some of the more advanced SASS features and BEM syntax, as they can be extremely powerful on their own. Happy coding!
If you have any questions or thoughts on this article, please feel free to comment below.