The Problem With Raw CSS

Writing raw CSS is not a pleasure nowadays. Pure CSS has a very simple and, as a side effect, very inflexible syntax that doesn’t always suited our needs in building high quality products. The overall complexity of systems are increasing day by day and modern web developers need more and that’s why CSS preprocessors exist.

The Overall Structure

In order to explain what a CSS preprocessor is and why we should use this kind of tools I’ll build a little demo with raw CSS. After that I’ll take this further by translating it in sass, the preprocessor of our choice for this article. This demo will be big enough to see the difference between each tool. I’ll try also to explain along the way some new concepts about preprocessors pretty quickly, so that you can start using those right now.

For the rest of this article I’ll use this HTML structure:

<section id=“main”>
    <figure>
        <article>
            <img src="..." alt="">
        </article>
        <figcaption>
            ...
        </figcaption>
    </figure>
</section>

I’ll skip the repetition from the code, just to be clear. You can taste full code listing and the demo in this codepen. Later we’ll discuss about implementing this demo using sass, the preprocessor we used to talk about in this article.

See the Pen yyvBVZ by Andrei Glingeanu (@andreiglingeanu) on CodePen.0

Sass: Syntactically Awesome Style Sheets

Installation

We have 2 options: to use command line or a GUI application.

If you have ruby installed on your system, be it windows, osx or linux, you can type into command line this line to install sass:

gem install sass

Now you should have sass binary on your computer. You can compile a file named input.sass into corresponding output.css using command below. We have --watch switch to indicate that we want to recompile automatically as we change the input.sass file.

sass --watch input.sass:output.css

Another option will be to use a tool like Prepros to compille sass files for you. Many other options at Official Installation Page.

Nesting rules

The most used feature that preprocessor gives us is rules nesting, just like we nest elements in each other in HTML. For example, when we write a rule like this:

#main-content {
    h1 {
        em {
            text-transform: uppercase;
        }
    }
}

it will generate the following CSS:

#main-content h1 em {
    text-transform: uppercase;
}

Using variables

We can treat variables as a named container, where we can put several things. For example we can store a color in a variable and use this color in multiple places. Storing a size in a variable, be it in pixels, percents or ems, is also a good idea. Let’s see a demo using variables next.


$itemBackground: #867e7e;
$itemPadding: 5px;

ul.menu {
list-style: none;
padding: 0;

li {
display: inline-block;

background: $itemBackground;
transition: background .5s ease-in;

// we can use several functions to modify our colors
// here we lighten $itemBackground by 50% in order to ensure
// that we are able to read the text
color: lighten($itemBackground, 50%);

padding: $itemPadding;
// we can use arithmetic operations, if variable is a number
margin-right: $itemPadding * 2;

cursor: pointer;
font-size: 2em;
}

}

See the Pen MYQwXM by Andrei Glingeanu (@andreiglingeanu) on CodePen.
0

See how I defined variable $itemBackground in order to store background color for our menu? This is a very common pattern to define our palette of colors at the top and then use this colors throughout the file by explicit name. In this way we can change all colors very easily. In this demo we also have used rules nesting.

Another trick about storing colors in variables is that we can modify them using several predefined functions like:

  • lighten
  • darken
  • saturate
  • alternate

You can see full list of them and their usage on this great resource.

Parent reference

Sometimes, when using rules nesting we need a way to reference the element inside we nest rules. Let’s say we need a way to target paragraphs inside an article, but only those who have the class special. We can express it this way:

article {
    p {
        color: #333;

        &.special {
            color: #f00;
        }
    }
}

The key idea here is to use & in order to reference the current element. Sass will give us back the following css:

article p {
    color: #333;
}

article p.special {
    color: #f00;
}

We can use this trick in order to target all the pseudo elements and pseudo classes of current element together. In this demo you’ll see how I target :last-child in order to give it margin-right: 0; and also how to style :hover pseudo class for lis using &.


$itemBackground: #867e7e;
$itemPadding: 5px;

ul.menu {
list-style: none;
padding: 0;

li {
display: inline-block;

background: $itemBackground;
transition: background .5s ease-in;

// we can use several functions to modify our colors
// here we lighten $itemBackground by 50% in order to ensure
// that we are able to read the text
color: lighten($itemBackground, 50%);

padding: $itemPadding;
// we can use arithmetic operations, if variable is a number
margin-right: $itemPadding * 2;

cursor: pointer;
font-size: 2em;

&:hover {
// another function which modifies color
background: darken($itemBackground, 10%);
}

&:last-child {
margin-right: 0;
}
}

}

See the Pen jEZwKb by Andrei Glingeanu (@andreiglingeanu) on CodePen.
0

Mixins and extending rules

In a nutshell, mixins are a way to encapsulate many useful properties into one block, and then using @include insert this properties into our rule. This is somewhat a similar concept to functions in JavaScript and PHP. The main idea is that you can pass different parameters to the mixin, and it will return you the right properties, depending on the parameters you passed. Let’s see an example where we define a mixin in order to write vendor prefixes for transform property.


@mixin transform($transformation) {
-webkit-transform: $transformation;
transform: $transformation;
}

div {
width: 100px;
height: 100px;
background: red;

@include transform(translate(40px));
}

See the Pen yyvEgQ by Andrei Glingeanu (@andreiglingeanu) on CodePen.
0

Let’s see, here we have transform mixin, and we include it into div, using @include. As a named parameter $transformation we receive translate(40px). The generated css for this mixin will look like this:

-webkit-transform: translate(40px);
transform: translate(40px);

Another way of reusing existing styles is to @include already existing rules. This one is not so common as mixins, because it does not have the ability to pass parameters to it, therefore it is not so flexible. You’ll have an example on using this technique in the final demo for sass.

Hence, we have many ways to not repeat ourselves by defining mixins and including already existing rules. There is available online many collections of predefined mixins for sass, which provide many neat things. Most popular ones are bourbon and susy. You can read about them by clicking on the links I provided for you. Among the others, susy is a great alternative to bootstrap grids and it will prevent your html being polluted with unsemantic classes like col-md-4. You definitely should check them out.

Reimplementing demo

Now let me give you a full reimplementation of our kitties using sass, you can skim through code on codepen, it is very simple. Try to reveal all the new concepts we’ve covered here in the code for this demo.

See the Pen JopZRj by Andrei Glingeanu (@andreiglingeanu) on CodePen.0

Conclusion

As a conclusion, all the preprocessors and sass specifically gives us a more flexible way to structure our styles, in comparison to pure css. Now all the nesting from HTML is expressed very naturally in our stylesheets. We also do’nt repeat ourselves by writing colors and scalar values, which is highly error prone and is very easily to commit a mistake by using sass variables. The abillity to group multiple rules under one named mixin is also a beautiful and readable way of structuring css.

These little explanations should really get you started on using sass. If you really want more you can go ahead and read official guide for this preprocessor. You may find useful documentation, which gives many more ideas and insights on using and integrating sass on different platforms and development stacks.

Written by

I’m a self-taught frontend developer with passion to cutting edge web technologies. My primary occupation is Ruby on Rails freelancing and most of my spare time I spend learning new things about my workflow and about what I’m interested in.

Hot Deals & Offers!

Find enormous discounts and hot offers for many useful services and products
(designmodo, creative-tim, themify and more)

Check Out Now
Sponsors
4 Comments, leave yours
  1. Ralph Feb 24, 2015, 9:08 pm

    Raw CSS is not a problem… the problem is if you select elements like this:

    #main figure figcaption span

    If your CSS output is like that after preprocessing as well, then you’re creating problems in your CSS, not CSS itself.

    There are also postprocessors by the way which can save you al lot of time as well, but you just write CSS as it was meant to be and you can use CSS variables and calc() too.

    Reply
    • Andrei Glingeanu Mar 18, 2015, 6:26 pm

      Thank you Ralph, good point.

      But the main idea of this feature is not to nest our rules as deeply as possible, in order to generate selectors with dozens of lines in length.
      Selectors nesting was created in order to simplify styles for complex widgets, and also to reflect html structure in css.

      The problem with writing selectors in a way or another is tackled by various CSS methodologies, about which you can read about on the WEB.

      At the end of the day, that’s just a description of a tool that should help you. You should master and use it wisely in a way that suits your personal needs.

      By the way, I’ve recently found out a way to separate completely layout issues from visual styles: http://gridstylesheets.org/. That’s also a great way to improve the way we write our projects, but it introduces one more layer of complexity over our already so complex workflow.

      Reply
  2. Andrea Ballerino Mar 18, 2015, 3:25 am

    Hey Andrei, very nice article, thanks :)

    Reply
    • Andrei Glingeanu Mar 18, 2015, 6:27 pm

      You’re welcome, Andrea!

      Reply
Leave a Reply to RalphCancel Reply