Starting to Write CSS
Don't you feel that CSS is not the same anymore? Last few years became a hot topic and many smart people talked about it. CSS is not that little thing which front-end developer should do to make the page looks pretty. It's far more then that. We care about performance and we want to produce better web sites. In this article I want to share what I learned last few months and what exactly is my vision about CSS coding. As a programmer I'm really interested in the architectural part of the things. I feel that the writing of CSS should be changed and I dig a lot. I search for the good processes, the best principles and new workflows. This post is like conclusion of journey in the world of CSS. Many people say that writing CSS is not exactly programming. I'll disagree and will say that it's equally interesting and challenging.
CSS Preprocessors
Ok, let's face it. Writing pure CSS is not the funnies thing in the world. The preprocessors take something which looks like CSS, make some magic and produce valid CSS code. This adds one more layer between you and the final styles which are send to the browser. That's not so bad as it sounds like, because the preprocessors provide some really helpful features.
Concatenation
I think that one of the most valuable thing which came is the concatenation of your files. I'm sure, you know that when you use @import in your .css file you actually tell to the browser please, get that file too. And it does. It makes a new request which is kinda bad, because you may have a lot of files. Making additional requests decrease the performance of you application. If you use CSS preprocessors this problem is gone. They simply compile all your styles to one single .css file.
Extending
There are two main CSS preprocessors - LESS and SASS. They both support extending. Yes, it works a little bit different, but the idea is the same. You make a basic class (usually called mixin) with bunch of properties and later import these properties inside another selector. For example
// less .bordered(@color: #000) { border: dotted 2px @color; } .header { .bordered; } .footer { .bordered(#BADA55); } // compiles to .header { border: dotted 2px #000000; } .footer { border: dotted 2px #bada55; }
The problem here is that if you define a mixin without parameters i.e. if you have just
.bordered { border: dotted 2px #000; }
this goes to the final compiled CSS file, no matter if it is used or not. It's like that, because it is a valid selector. In SASS we have a little bit more flexibility. There are mixins, extends and placeholders (if you want to see the exact difference between them I strongly recommend checking this article). Let's get the following SASS and its compilation:
// sass @mixin bordered($color: #000) { border: dotted 2px $color; } .header { @include bordered; } .footer { @include bordered(#BADA55); } // compiles to .header { border: dotted 2px black; } .footer { border: dotted 2px #bada55; }
It looks almost the same. But if we go to the second use case and define a place holder:
// sass %bordered { border: dotted 2px #000; } .header { @extend %bordered; } .footer { @extend %bordered; } // compiles to .header, .footer { border: dotted 2px #000; }
There are two good things happening. First, there is no .bordered class compiled. Second, SASS combines the selectors and it makes our CSS a little bit shorter.
Configuration
Both LESS and SASS support definition of variables. You can later access those variables and use them as values for your properties.
// sass $brand-color: #009f0A; ... h1 { color: $brand-color; }
That's a good feature, because you may store some important things like company colors or grid widths in one place. If you need to change something you don't need to go through all your code.
Another handy usage of the variables is interpolation. The following example demonstrates the idea:
// sass @mixin border($side) { border-#{$side}: solid 1px #000; } .header { @include border("left"); } // compiles to .header { border-left: solid 1px #000; }
Against the preprocessors
- The preprocessor is a tool, i.e. it's one more thing which you have to add to your environment. You may want to integrate it into your application. This of course requires additional coding.
- If you don't want to mess your code with such a thing, then you will probably need a watcher. Another instrument which monitors your files and once something is updated fire compilation. If that's the case then you have to run the watcher every time when you start working on the project. Maybe you will optimize the process over the time, but it's still something that you should care about.
- Very often the developers look only their .less or .sass files. However the output is what it matters. You may have elegant and optimized SASS code, but this doesn't mean that you will end up with the same beautiful CSS code. You may have some really interesting specificity problems. So, check the compiled version regularly.
BEM
Ok, I found a new tool to play with. The preprocessors probably save a lot of time, but they can't write a good architecture alone. The first thing which I started thinking of is a naming convention. Let's get the following HTML markup:
<header class="site-header"> <div class="logo"></div> <div class="navigation"></div> </header>
A possible styling may look similar to
.site-header { ... } .logo { ... } .navigation { ... }
This will work of course, but it has a problem - reading the CSS you can't understand that, for example, the logo belongs to the header. You may have another little logo image used in the footer. The next logical step is to write a descendant selector.
.site-header .logo { ... }
However using such selectors is not very good idea, because it tights styles to specific tags hierarchy. What if I want to move the logo outside the header tag? I'll lose the styling. The other thing which you could do is to add site-header in the name of the logo's class:
.site-header-logo { ... }
That's good, self explanatory, but it doesn't work in all the cases. Later, during December I may want to use a Christmas version of the logo. So, I can't write
.site-header-logo-xmas { ... }
because my logic is to write the selector like that so it matches the nesting of the tags in the html.
BEM could be the answer of the situation. It means Block, Element, Modifier and creates some rules, which you could follow. Using BEM, our little example will be transformed to:
.site-header { ... } /* block */ .site-header__logo { ... } /* element */ .site-header__logo--xmas { ... } /* modifier */ .site-header__navigation { ... } /* element */
I.e. site-header is our block. The logo and the navigation are elements of that block and the xmas version of the logo is modifier. Maybe it looks simple, but it's really powerful. Once you start using it will find that it makes your architecture better. The arguments against BEM are mainly because of the syntax. Yes, maybe it looks a little bit ugly, but I'm ready to make a sacrifice in the name of the good system.
OOCSS
Once I found BEM I was able to name my classes correctly and I started thinking about composition. Maybe the first thing which I read was an article about Object oriented CSS. Object oriented programming sometimes is about adding abstractions and CSS language supports that. Using preprocessors or not, OOCSS is something that you should know about. As a coder I found this concept really close to my usual programming, in JavaScript for example. There are two main principles:
Separate structure and skin
Let's use the following example:
.header { background: #BADA55; color: #000; width: 960px; margin: 0 auto; } .footer { background: #BADA55; text-align: center; color: #000; padding-top: 20px; }
There are few styles which are duplicated. We may extract them in another class like that:
.colors-skin { background: #BADA55; color: #000; } .header { width: 960px; margin: 0 auto; } .footer { text-align: center; padding-top: 20px; }
So, we have an object colors-skin which we could extend. The html markup may look like that:
<div class="header colors-skin"> ... </div> <div class="colors-skin"> ... </div> <div class="footer colors-skin"> ... </div>
There are several benefits of that change:
- We have a class, which may be used several times.
- If we need a change we need to make it in only one place
- We removed duplication in our CSS file, which makes its file size lower
Separate container and content
The idea here is that every element should have the same styles applied no matter where it is put in. So, you should avoid the usage of selectors similar to the following
.header .social-widget { width: 250px; }
It's because if you move .social-widget outside the .header container the width will be different. In general, that's not a good practice. Especially for components which are used all over the page. This principle encourage modular CSS and I strongly recommend to take enough time trying it. Personally, for me, following the principle means producing better CSS.
The framework
If you open the OOCSS repository on GitHub you will see a framework. Yes, the framework uses object oriented CSS concept and yes, it has a bunch of cool ready-to-use components. From some time I don't like frameworks. If you think a bit you will see that the word framework has two parts frame and work. And indeed you work in a frame. You actually make a deal with that thing and you have to play by its rule. I prefer to use micro-frameworks or something which gives me only the base. Of course I don't mean to reinvent the wheel, but I'm always trying to find the balance. Very often, the ready-to-use solutions lead to messy and complex systems. My advice is to build things with only one an specific purpose. If you try to cover as many cases as possible you will end up with ... you know - a framework.
However, I strongly recommend checking the OOCSS framework. It's an unique piece of knowledge and maybe it will fit in your needs. The repository is hosted by Nicole Sullivan. She is a pioneer in OOCSS and if you have some free time I'll suggest to check here presentations/talks.
SMACSS
Another popular concept is SMACSS. SMACSS stands for scalable and modular architecture for CSS. Jonathan Snook introduces something like style guide for the CSS developers. The idea is to separate your application into the following categories:
- Base - basic default styles usually used for a simple selectors. Like clearfix for example.
- Layout - grids definition
- Module - a group of elements which combined form a module. Like for example header or sidebar.
- State - contains different states of elements. Definition of rules if particular object is hidden, pressed, expanded etc ...
- Theme - oriented more to the visual parts of the things. Similar like the state category.
I don't have experience using SMACSS, but it is quite popular and indeed promotes good ideas. The very good thing is that it is more like a concept then a framework. So, you are not tight to any strict rules, classes or components.
Atomic design
Knowing about OOCSS and SMACSS I searched for an appropriate metaphor and very soon I landed on this page. It's a presentation of the great concept Atomic Design. Its author is Brad Frost, which is a well known web developer working mainly in the responsive and mobile world.
The idea is really interesting. Following some chemistry terminology, we could say that the basic unit of the matter is the atom. Brad moves this to CSS saying that our pages are build by atoms. An atom could be
<label>Search the site</label>
or
<input type="text" placeholder="enter keyword" />
I.e. atoms contain some basic styling of DOM elements. Like color palette, font sizes or transitions. Later those parts could be combined into molecules. For example:
<form> <label>Search the site</label> <input type="text" placeholder="enter keyword" /> <input type="submit" value="search" /> </form>
So the form element contains several atoms. Abstracting the things like that brings flexibility, because we may use the same atoms to build another molecule. Together with that, we could reuse the same form in different contexts.
Brad didn't stop there. The organisms are something which is build of molecules. Following the same approach we may write the following and call it an organism:
<header> <div class="logo"> <nav> <ul> <li><a href="#">Home</a></li> <li><a href="#">About</a></li> <li><a href="#">Contacts</a></li> </ul> </nav> <form> <label>Search the site</label> <input type="text" placeholder="enter keyword" /> <input type="submit" value="search" /> </form> </header>
The next thing in the concept are the templates. They are not related to the chemistry directly, but are put into web context. Once we start combining different organisms we are building template. Later those templates form our final pages.
You are probably already using similar approach to build your applications. However, naming the things in a reasonable manner brings good architecture. You and all your team mates will have something to catch on, during the development. Separation of the things to atoms and molecules is kinda important part, because it improves both, the working process and the maintenance of your web application.
OrganicCSS
Before a couple of months I wrote an article about Organic. It's a great small framework for JavaScript applications. It's more like a design pattern, and I personally like it a lot. I even used Organic in several projects and everything works pretty well. If you are interested in it, I strongly recommend reading the blog post here.
When I read the Brad Frost's article I was already familiar with similar concept, because I knew about Organic. Brad's work is amazing, but I decided to go deeper and try to write my own micro framework based on atomic design concept. I chose SASS as a preprocessor and create a repository in Github - https://github.com/krasimir/organic-css.
Atoms
Let's start with the smallest part of the framework - the atom. Its definition in wikipedia is The atom is a basic unit of matter. In the context of CSS, I think that it is a property and its value. For example:
margin-top: 24px;
Adding atoms just by writing styles directly inside the classes is not what I wanted. Because if I type something like that
body { margin-top: 24px; } header { margin-top: 24px; }
the preprocessor will leave that as it is. The result which I want to get at the end is:
body, header { margin-top: 24px; }
In SASS this effect is achievable by using place holders. I.e.
%margin-top-24 { margin-top: 24px; } body { @extend %margin-top-24; } header { @extend %margin-top-24; }
So, I had to use placeholders. This also means that I had to have a lot of predefined placeholders, which I can use. At that moment, I decided that the framework will contain only atoms. And maybe few molecules with generic functions like the usual reset.css, grid definition and so on. I wanted to write something which acts as a base for the CSS development. Maybe project after project I'll see some patterns, which could be put in the core, but as a start I wanted to keep the repo clean and simple.
To make the things a little bit more consistently, I created a mixin for atom definition. So, here is an example:
@include define-atom("block") { display: block; } @include define-atom("font-family") { font-family: Georgia; }
Using this approach I created a bunch of atoms, which I could easily apply in every project. You can check them here. I used some good practices from other frameworks so, not all the credits go to me. There is also a mixin for combining atoms in a molecule:
@mixin header { // <- molecule called 'header' @include atoms(( block, clearfix, font-family )); }
Molecules
Molecule is a DOM element which needs styling, but doesn't have children. Or if it has children they are not directly connected to it. For example <img src="logo.jpg" /> could be a molecule. If you find difficult to recognize the molecules in your page, just think of what is build by atoms. If some element is build by other molecules it is probably an organel. Just a few lines above I showed how to define a molecule:
@mixin login-box { @include atoms(( block, font-size-20, margin-top-23, bold )); }
There is something interesting, which I faced with. Let's get the body tag. What it is? Is it a molecule or something else? Sure, it needs some styling via atoms, but in general contains other molecules. It should be something else. I made the conclusion that the CSS should be the leading part. I.e. if the body needs few atoms for its styling then it is a molecule, which means that, in theory, I should not attach any other molecules to it. This may seem a little bit impractical, but in most of the cases will keep you from using descent selectors, which is a good sign.
Organelles
Once you recognize which DOM elements are molecules you will see what organelles are. For example, the typical form element is a great example of organelle. It contains molecules like label, input or textarea.
.login-form { @include label; @include input; @include textarea; }
The organelles are maybe the first part of the framework, which is tightly connected to the current application. The atoms and molecules could be transferred between the different projects while the organelles may not.
More abstractions
Very often you may want to combine several organelles in something else. If that's the case then add another abstractions.
Atom → Molecule → Organelle → Cell → Tissue → Organ → Sys → Organism
It's a matter of choice how you will continue constructing your CSS. I used OrganicCSS only in one project so far, but I could say that it brings clarity. I put the different elements in their own directories and named the classes like that so I can easily find out what exactly I'm working with. For example if there is an organelle called header I simply change it to o-header. Later, when I read the HTML markup I could see that the CSS styles for this element are in organelles folder.
Conclusion
It was an interesting journey. I don't know if I'm going to use OrganicCSS in the future but that's not the most important part. The things which I've learned are what it matters. I knew that I had to change my CSS development process and I did it. I believe that we should talk more about architecture in CSS. As you can see we have a lot of good resources out there. We just have to find them, learn what they do and how they work. Only then we could decide what to use or not. Even better, when you see the whole picture you are able to create something which fits better in your needs.
About Krasimir Tsonev
Krasimir Tsonev is a coder with over ten years of experience in web development. With a strong focus on quality and usability, he is interested in delivering cutting edge applications. Currently, with the rise of the mobile development, Krasimir is enthusiastic to work on responsive applications targeted to various devices. Living and working in Bulgaria, he graduated at the Technical University of Varna with a bachelor and master degree in computer science. If you'd like to stay up to date on his activities, refer to his blog or follow him on Twitter.
I assume there will be 5 people who have already pointed this out, but in case not: LESS won’t compile mixins into CSS classes if they take parameters. And if your mixin doesn’t take params but you don’t want it to compile to CSS, you can define it with empty parens:
Eek. Not sure what happened with the styles there, but hopefully the point is still clear.
Yep, if you add () your mixin/class is not going to the compiled css. However, I found that a lot of people forgot about that and their styles are full with mixins :)
>styles are full with mixins
Then they will happy to use CSSO http://bem.info/tools/csso/
CSSO is a nice tool, but I’m not sure that will solve the problem. In the actual CSS the mixin is added as a normal class. CSSO will not remove it, because it has no idea if it is used in the HTML or not.
An article which is useful for who starting CSS & currently pursuing UI/UX
Your Sass, isn’t Sass. It’s Scss
Your BEM example is confusing. How is
.site-header__logo { }
any different from
.site-header-logo { }
or
.site-header .logo { }
With any of these syntaxes, you still end up with the problem (that you originally mentioned) – what if you wanted to use the logo outside of .site-header?
Seems to me that using BEM, or any similar type of naming convention, ignores the C in “CSS”
For the record, I think the best solution is to use a class of logo on your logo and then use the following:
.logo { /* global logo rules, regardless of where it is */ }
.site-header .logo { /* rules applied only to logo elements within .site-header elements */ }
@Adam: .site-header__logo perfectly shows that logo is an element of the header. If I use .site-header-logo that’s not really clear, because I may have .site-header-blue. And the word “blue” means modification, but not an element. So, there is no consistency. I’d like to think about BEM more as a naming convention. It helps in a lot of cases, but it is not necessary to use it everywhere in your stylesheet. Maybe the example used in my article is not the best one, but I still believe that it fits in the BEM idea. By my opinion your suggestion is not so bad, but I prefer to avoid such selectors. That’s because later if I want to copy the exact same style of “.site-header .logo” I can’t. And I can’t because that’s descendant selector. You better use .logo and .logo-header and apply them both when you need.
In general: what to use and what not depends on your project as well. We can’t really say that BEM or OOCSS or Atomic design should be used always.
I’m sorry, but your example and reasoning is one of those things where I think you put too much thought into it.
The whole point of css is to enable you to style and name the classes and ids to whatever you. Of course, you do want to take into consideration to use semantic names for ease of understanding.
If you worried about .site-header .logo not being re-useable when you move logo out of the header, then you shouldn’t use less or sass in the first place. Maybe you shouldn’t write your css with any inheritance since the majority of those are not re-useable.
Great article for CSS beginners. Thanks!
And what about use this struture?
.core { position: relative; }
.core.inline { width: 100%; float: left; display: inline; }
#header { }
#header .logo { width: 50px; height: 50px; }
#header .footer { width: 10px; height: 10px; }
@Pablo: you should see if you will use the targeted classes (I mean .inline, .logo and .footer) somewhere else outside of there parents. For example the .inline class seems like something general and could be used outside the .core wrapper. This means that you will lose its styles. It’s the same with the .logo and .footer. If that are generic type of elements it makes sense to avoid descendant selectors.
thanks for the tutorial css above, this is very useful for me
Your organic css atoms remind me a bit of Jeremy Clarkes talk about dry css (http://vimeo.com/38063798). It’s a nice concept to get a great felxible styling base. I just did my last project with Brad Frosts PatternLab and at some point you can style a whole page just by adding classes in the html.
@Mikael Boutin
Yes it is Sass, using the SCSS syntax. But it’s Sass.
thanks for the tutorial, this is very useful for me
one of the best posts in quite some while on the topic of meta css work. Really enjoyed reading it, although I knew most of the concepts already – however getting them in one comparable perspective does the difference in understanding where I should be moving with my own css.
Keep them coming! :)
subscribed :D
wow! I found the great blog :))
Thank you David for your shares ;)
Great article, nice explanations. 100% goes to my bookmarks.
Check out http://jslegers.github.io/atomic-navigation/ for several navigation elements implementing an atomic CSS design pattern.
You can also check out http://www.cascade-framework.com/ for an entire CSS framework based on Atomic CSS design patterns.
Great article, I have really enjoyed it. Do you guys think that a front-end team should always use the same(or most of the times) CSS development technique or having the ability to adapt based on the project requirements (SMACSS, OOCSS or else)?
I would avoid organic for the simple fact you can not create submodules due to how it @extends.
For example, this will not work if the pa-s atom (padding-all small) is before pa-m (padding-all medium)
Personally, I would go with SMACSS.
The editor mucked up my code with the hypens. Sorry everyone.
CSSO is a nice tool, but I’m not sure that will solve the problem. In the actual CSS the mixin is added as a normal class. CSSO will not remove it, because it has no idea if it is used in the HTML or not.
Hello, try OrnaJS, Orna4Node or Atomizer as tools for Atomic CSS.
http://ornaorg.github.io
http://ornaorg.github.io/Orna4Node.html
https://github.com/acss-io/atomizer