DoCSSa 2.0 {dok~sa}

Sass based CSS architecture and methodology


About

What is DoCSSa ?

DoCSSa is a CSS architecture and methodology to help structure rapid and maintainable stylesheets development.
It is intended for use in large, long lived sites, on which many frontend developers may be working over time.
The name stands for Deferred Object CSS Architecture.

What are the key features of DoCSSa ?

  • Clear and proven folder structure
  • Separation of concerns between HTML and CSS
  • Scalable and maintainable stylesheets
  • Easy to setup and flexible

Why does DoCSSa exist ?

As frontend web developers, we are living in a world of evergrowing complexity. What once was a relatively easy thing to do (putting aside browsers inconsistencies) has grown into a very complex, dynamic, everchanging reality.

So, we need flexible structures in order to be more efficient and less under pressure when the rough times come. The more work we can avoid by having defined the right tools and the right architecture ahead of time, the better.

DoCSSa is our attempt at an organization that aims toward a fast workflow that will keep the flexibility required for the long run.

How does DoCSSa bring its benefits ?

DoCSSa is based on Sass, and leverages some of its key features to achieve its goal. Most notably, DoCSSa takes advantage of imports and mixins. It also suggests a file system organisation and a BEM based naming convention, and integrates the core ideas found in OOCSS and SmaCSS.


File Structure

Basics

In DoCSSa, the file system is divided in four main directories in the sass folder :

Each base folder has a specific role, and CSS rules for a particular set of elements will end up in one of these directories, according to their nature.
The structure has a single point of entry, which we'll call custom.scss. This file is located at the root of the sass folder.

In most cases, it will be the only file with no underscore(_) prefix: as you may know, the .scss to .css convertion process in Sass only converts files that don't have an underscore in front of them. Most of the files in our structure being imported by other files, they don't need to be rendered directly.
Only components may be rendered separately, in order to be able to dynamically load them if needed, but we'll get back to it.

The main .scss file will look something like this :

  • // custom.scss
@charset "UTF-8";
/*!
========== INIT
*/
// styles reset (normalize) and third party scss entry point
@import 'vendor/__vendor';
/*!
========== BASE
*/
// variables, fonts, mixins, helpers... common styles used across the entire site
@import 'base/__base';
/*!
========== COMPONENTS
*/
// reusable components
@import 'components/__components';
/*!
========== SPECIFICS
*/
// declarations specific to the project, organized according to the items/sections represented
@import 'specifics/__specifics';

As you can see, it mostly acts as an aggregator for other files, which themselves import some other scss files, and so on. With a well thought organization, this simple construct can prove very powerful!

On a sidenote, remember that Sass is only a CSS precompiler, so you'll end up with only one .css file with all the goodies, not a bunch of HTTP requests.

Here is an overview of what a basic file system might look like :

// file system
sass
¦   custom.scss
¦
+---base
¦   ¦   __base.scss
¦   ¦   _config.scss
¦   ¦
¦   +---project
¦   ¦       __project.scss
¦   ¦       _fonts.scss
¦   ¦       _globals.scss
¦   ¦       _mixins.scss
¦   ¦       _variables.scss
¦   ¦
¦   +---utils
¦           __utils.scss
¦           _mixins.scss
¦           _system.scss
¦
+---components
¦   ¦   __components.scss
¦   ¦
¦   +---button
¦   ¦       _button.scss
¦   ¦
¦   +---tabs
¦           _tabs.scss
¦
¦
+---specifics
¦   ¦   __specifics.scss
¦   ¦   _main.scss
|   |   _inbox.scss
¦   ¦
¦   +---popins
¦           __popins.scss
¦           _popin-congratulations.scss
¦           _popin-loginForm.scss
¦
+---vendor
    __vendor.scss

Base folder

The "base" folder contains rules that are global to the site. It is divided in two parts :

Note that the base/_config.scss file is located directly in the base folder. It contains variables that are required by both the utils and the project. So far only the $baseFontSize fell in that category, but we still dedicated a file to it in order to be consistent.

Utils contains only things that don't need to change from a project to another. As of today, it consists of _system and _mixins.

  • _system is a special file that contains tools used by DoCSSa.
    Most notably, it contains a mixin that helps requiring content from several places without generating duplicate content, and one that helps the provided components to make use of Modernizr classes.

  • _mixins contains a collection of commonly used helpers. They are particularily useful for handling vendor prefixes and fallbacks. For example, DoCSSa comes with a linear-gradient mixin that compiles to all required vendor prefixes (and only those required!) and generates a fallback color from the input values for browsers that don't support linear-gradient at all. DoCSSa recommends using Modernizr for feature detection and progressive enhancement, and the provided mixins implementing CSS3 features rely on it by default for their output (even though it can be disabled at include time).

    Mixins can accumulate and enrich your library with no cost, as they are only compiled when used.
    Mixins are a great way to avoid repetition when coding. They end up in code repetition in the css output, and for that reason the previous version of DoCSSa was based on placeholders instead, but it has now been proven that this repetition is not an issue once gzip comes into play (more info)

Project is where every global setup of a project is stored. Whereas utils is intended to be kept and grow from a project to the next, project only stands true for a given project (although you may want to use it as a boilerplate from project to project). As of today, it consists of _variables, _fonts, _mixins and _globals.

  • _variables is were all site wide variables reside. Default values, color theme, configuration variables, etc. go into this file.

    Here's what the _variables.scss file might look like :

    // _variables.scss
    /* _____ VARIABLES _____ */
    // Generic
    // ==========================================================================
    $default-borderRadius: 4;
    $containerWidth: 760;
    // Colors
    // ==========================================================================
    $color-default-light:   #fff;
    $color-default-dark:    #333;
    $color-default-darker:  #000;
    $color-main:            #ff7f50;
    $color-main-light:      #ff9e7e;
    $color-main-lighter:    #ffdec7;
    $color-secondary:       #5cbcaa;
    $color-alt:             #f1ede4;
    $color-alt-dark:        #c2c0bc;
    $color-alt-light:       #f8f5ec;
    $color-alt2:            #637c84;
    
  • The _fonts file is used —you guessed it— for the font-families declaration.
    In our implementation, we use a font mixin that is in charge of generating a bulletproof syntax according to the passed configuration for each needed font, according to a file naming convention.

    But where do we have to place the font files themselves, you may be wondering? Well, as this Sass structure is intended to be compiled to CSS in a different directory, the fonts will be in that directory. Typically, you'll have the custom.scss file in a "sass" folder" compiled to a custom.css in a "css" or "styles" folder. The font files will have to be there (preferably in a "fonts" subfolder in order to stay nice and tidy).
    Same goes for all the image files you may be referring to in your stylesheets.

  • _mixins is a place for you to store simple helper that you may want to reutilize throughout the site, but are not generic enough to endup in the utils/_mixins file.

  • _globals contains rules that are global to the site. Things like box-sizing type, html font size, body background color, headings and link defaults, etc. are defined here. It is also be a good place to store your layout definition if it is used for all pages on the site.

Components folder

The "components" folder is where your ui-components are located. It is the place dedicated to store your reusable UI appearance.
Components are an important part of DoCSSa, and we dedicated a whole section to explain all there is to know about them, so we won't say much more about them here.

Specifics folder

The "specifics" folder is your common playground. It is where you'll place the rules that don't belong in the "base" or "components" folders. Until you become fluent with DoCSSa's organization system, what will eventually end up in a component will probably exist in here first.

Specifics is the closest thing to your usual CSS file, except that everything in there is split and dispatched in files and folders according to what they apply to. This fragmentation is key to keeping things maintainable!

By convention, we're using two underscores(__) as a prefix for files that act as an import summary, and only one underscore(_) for files which are content only. This usually evolves with the project: you begin with an underscore prefixed file, you add another one, and at some point you stop calling them directly from the main .scss file and you reorganize them in a folder with its own summary file.

DoCSSa encourages you to keep your definitions tidy and reorganize in subfolders as soon as it makes sense.
No file should ever be big enough that you can't scroll through it in a few mousewheel movements max!

Before everyone in your team is familiar with DoCSSa, it can be helpful for occasional contributors wondering where to place their code to have a dedicated file. In such case, we recommend using a _inbox.scss file in the "specifics" folder and ask them to commit their work in there.
It shall be emptied regularly by a more experienced DoCSSa user, who would move the CSS rules defined in there to the correct place in the architecture.

Vendor folder

The vendor folder is where we import SCSS files that come from third parties and can be updated at any time. It can import from a bower folder, or have its assets directly in the folder. As the .scss syntax is CSS compatible, all we have to do is to rename the .css files to .scss, in order for them to be integrated to the .css compilation instead of referenced by the CSS file as a classic @import.

_normalize.scss is an excellent candidate for this section, along with more project specific third party CSS. We currently rely on bower for fetching it for us.


Components

Introduction

Components are an important part of DoCSSa. They have been redesigned since version 1 of DoCSSa to become simpler and easier to use. They are the "Deferred Object" part of DoCCSa.

We say the Object is Deferred because its core resides in an abstraction (the mixin) instead of being tied to a classname. DoCSSa's components are class agnostic. They are made of mixins. A component mixin is in charge of binding the reusable styling to one or several HTML class(es). Thanks to the BEM naming convention, the class passed to the component mixin can be a prefix for other classes onto which to bind functionalities.

This allows for components to be instantiated on any class, and to be composable if needed.

As the component is not tied to a particular class, you can use it on whatever class you want, whenever you want, from the stylesheet side. That means that you can (and should) keep a semantic meaning to your HTML classes, and change their look and feel without having to modify the markup.
When your markup comes from a RTE, this is a huge gain. You can change the styling without asking the contributors to change their habits, and you can affect everything already written without having to make search&replace throughout a database or without having a "red" class helper mean the color is going to be purple!

For example, instead of having a link with the "button red" classes, you can give it a "navTrigger" class and bind a button component with a red skin to it. You could also use the same component on a "submitTrigger" class so that both look the same. When time comes to have a different look for your submits, all you have to do is bind the submitTrigger to another component and you're done, without affecting the navTriggers and without touching the markup.
Note that for advanced components, the HTML may be expected to conform to a particular structure to be a valid target.

If you need a component with a slightly different behaviour than the original one, you can pass a parameter to the mixin to change the binding (or rules). If the exceptions become too numerous, it's probably time to consider creating another component or a set of small components.

Here is what a component definition looks like :

// component example
// map the placeholders content to some selectors through a mixin
@mixin example($selector, $defaultSkin: true) {
  #{$selector} {
    padding: 10px;
  }
  #{$selector}_inner {
    padding: 20px;
  }
  #{$selector}:hover {
    padding: 30px;
  }
  @if $defaultSkin != false {
    @include example-skin-default($selector, $hover);
  }
}

In order to fulfill their role, components need to respect those two guidelines :

  • A component should be self contained.

    This means that what is outside of the visual boundaries of the component doesn't belong in the component definition. Typically, things like margins or positioning should reside in the "specifics" folder, not in the component. This is required for your component to live in any possible context.

  • Structure(layout) should be dissociated from skin(paint).

    For example, background color, images, text colors, etc. may go into the skin section of the component, not in its core definition. That way, you can create additional styles for them without altering their expected behaviour as a component, and choose what visual style you want when binding the component to a classname.

Of course, it's up to you to compose with those precepts and adapt them to your constraints, but respecting them results in a clean separation of concerns and genuinely reusable components, which is much likely to make your dev faster further down the road.

When beginning with DoCSSa, it's easy to think as everything as components, as they are so powerful. You must be careful about that, and think about what needs to be a component and what doesn't.
If you component-ize every set of rules, you risk spending more time building the same thing as you would have in the "specifics" folder without enough additional value for it to be worth it. Try to begin with small components to get the hang of it, and adjust your use little by little.
You can begin everything the way you are used to in the "specifics" folder, organize it in imported files and subfolders the DoCSSa way, and only extract a functionality to a component when you feel that it would help you.
DoCSSa only gives you tools to play with, what you implement and how you do things with it is up to you. That's what we believe a "framework" should be anyway.

Description

When looking at a component folder, you will see one file, and possibly some subfolders. Let's take a Tabs component as an example, as probably everyone has already seen a tabbed navigation in a page. The file in the Tabs folder would be: _tabs.scss.
It is the component definition. Let's look at it in details.

Component's definition

The component definition file contains two mixins. One for the component structure, one for the component's skin.

Here's the structure part of our "tabs" component :

  • // components/tabs/_tabs.scss
// _____ STRUCTURE _____ //
// define the component structure
@mixin tabs($selector, $defaultSkin: true) {
  #{$selector} {
   display: inline-block;
    margin: 0;
    padding: 0;
    font-size: 0;
  }
  #{$selector}_item {
    @include remIt(font-size, 18);
    display: inline-block;
    vertical-align: bottom;
    line-height: 2.5;
  }
  #{$selector}_link {
    padding: 0 10px;
  }
  @if $defaultSkin != false {
    @include tabs-skin-default($selector);
  }
}

A mixin named after the component is all it takes. Its role is to actually bind the component's styling rules to the provided classname, its "elements", and its state.

We recommend that the "structure" part of the component doesn't make use of any project variable in order to stay as generic and reusable as possible.

By default, the component binding will also implement the default skin. If we have defined another skin, all we need to do is pass "$defaultSkin: false" when instantiating the component, and call another skin binding mixin to handle the component's skin.

We said earlier that a component folder may have subfolders. One of those is a "_skins" folder that would host different skins that we could import as needed. The "_skins" folder is prefixed by an underscore only so that it always show on top of the list in case you need some other folders in there.

Now let's look at the skin part of our "tabs" component :

// A component's skin part
// _____ SKIN _____ //
// provide a default skin for the component
// only visual changes that don't affect the component layout should be in here
@mixin tabs-skin-default($selector) {
  #{$selector} {
    list-style: none;
  }
  #{$selector}_item {
    border-bottom: 1px solid $color-main-lighter;
    &._is_current {
      border-bottom: 3px solid $color-main-light;
    }
  }
  #{$selector}_item--highlighted {
    background: $color-alt-light;
  }
  #{$selector}_link {
    @include basicClickable(true);
    border-left: 1px solid $color-main;
    color: $color-default-dark;
    font-family: 'titillium', Arial, 'sans-serif';
    #{$selector}_item:first-child & {
      border-left: 0;
    }
    #{$selector}_item._is_current & {
      color: $color-main-light;
    }
    &:hover {
      background: $color-alt;
    }
  }
}

As you can see, it is very close to the structure part. Actually it is placed inside the component's folder for simplicity, but it could very well reside in a _skins folder right away.

As stated before, a component's "structure" should only contain it's layout, it's skeleton. The "skin" part, unlike the structure, should only contain rules that don't affect the structure. These rules can be background-colors, background-images, border-radius, shadows, opacity... Anything you want as long as it doesn't fiddle with the component's external boundaries.
It is not always easy, but the more you practice it the more it feels natural, and the easier it is to find out the right place when you come back to adjust something about your component.

Implementation

Now that we know how a component is structured, it's time to implement it. This is done by calling the component mixin and passing it a class selector.

Here's what an implementation may look like :

// in specifics/_main.scss
    @include tabs('.mainMenu');
    

That's right, now that you have defined your component, using it is as easy as that!

And here is what the output css will look like :

// in css/custom.css
.mainMenu {
    display: inline-block;
    margin: 0;
    padding: 0;
    font-size: 0;
}
.mainMenu_item {
    font-size: 18px;
    display: inline-block;
    vertical-align: bottom;
    line-height: 2.5;
}
.cssremunit .mainMenu_item {
    font-size: 1.125rem;
}
.mainMenu_link {
    padding: 0 10px;
}
.mainMenu {
    list-style: none;
}
.mainMenu_item {
    border-bottom: 1px solid #ffdec7;
}
.mainMenu_item._is_current {
    border-bottom: 3px solid #ff9e7e;
}
.mainMenu_item--highlighted {
    background: #f8f5ec;
}
.mainMenu_link {
    background: none;
    border: 0;
    cursor: pointer;
    text-decoration: none;
    border-left: 1px solid #ff7f50;
    color: #333;
    font-family: 'titillium', Arial, 'sans-serif';
}
.mainMenu_item:first-child .mainMenu_link {
    border-left: 0;
}
.mainMenu_item._is_current .mainMenu_link {
    color: #ff9e7e;
}
.mainMenu_link:hover {
    background: #f1ede4;
}

If later on you need to bind the tabs component to another class, all you have to do is to call the mixin with that class and the parameters you want, and you're done!

For example :

// in specifics/_main.scss
@include tabs('.articleTabs', $defaultSkin: false);
@include tabs-skin-alternate('.articleTabs');

Naming conventions

HTML classes

In DoCSSa, we decided to follow BEM class naming convention.
HTML class names for Blocks are lowerCamelCase, and the Elements nested within are separated by an underscore(_). Modifiers are separated by a double dash(--), and they are used for elements variants. An element's state is written separately with a pattern that begins with "_is_".

Variants are dissociated from states because they play a different role, and it appeared that with our components architecture, having a simple "_is_current" class for our items' "current" state was way more effective than a "mainMenu_item--current" when it came to modifying the state through javascript.
BEM modifiers are now exclusively used for visual variants that don't change over time. They have a meaning at the content(HTML) level. For example, if a tab needs to be highlighted so that it stands out, it is applied a variant by using a modifier.
By opposition, a "state" is something that is supposed to be handled by javascript and change over time.

Here is an example of what that convention may look like in our tab example :

// naming example
<nav class="mainNav">
    <ul class="mainMenu">
        <li class="mainMenu_item">
            <a class="mainMenu_link" href="#">Home</a>
        </li>
        <li class="mainMenu_item">
            <a class="mainMenu_link" href="#about">About</a>
        </li>
        <li class="mainMenu_item">
            <a class="mainMenu_link" href="#fileStructure">File Structure</a>
        </li>
        <li class="mainMenu_item">
            <a class="mainMenu_link" href="#components">Components</a>
        </li>
        <li class="mainMenu_item _is_current">
            <a class="mainMenu_link" href="#namingConventions">Naming conventions</a>
        </li>
        <li class="mainMenu_item">
            <a class="mainMenu_link" href="#responsive">Responsive</a>
        </li>
        <li class="mainMenu_item">
            <a class="mainMenu_link" href="#gettingStarted">Getting started</a>
        </li>
        <li class="mainMenu_item mainMenu_item--highlighted">
            <a class="mainMenu_link" href="#contributing">Contributing</a>
        </li>
    </ul>
    <button class="mainNav_opener"></button>
</nav>
Note that this example is taken from the menu you're looking at just now in the present page.

At first, the BEM notation style can seem quite verbose and put off some developers, but it is very powerful and allows us to go way behind old school naming conventions.
It has to be tamed, though, and a classic beginner's mistake is to reflect the position of each element in the component's DOM in its class name. To avoid that, we recommend that you look at your low level elements first (those deeper in the DOM tree) and wonder if they could exist elsewhere in the page or in the component. Going up the tree, you can identify your most basic reusable components and set the names accordingly.

For example, in our example above, the "mainMenu_link" class doesn't need to reflect the fact that it is contained in a "mainMenu_item", this doesn't really matter to the link, so there is no reason to specify it in its name.
Also, if the element can live outside the block you're looking at, it's probably not a good idea to tie it to it, and it probably should exist on its own.

Sass files

We talked about some of the aspects of the Sass file naming convention in the "File Structure" section.

Each file is lowerCamelCase named and prefixed by an underscore(_) so that it is considered by the Sass compiler as a partial and not rendered to a standalone CSS file.

Each folder has a single entry point in charge of importing other partial Sass files. This file is named after the folder's name, and is prefixed with two underscores(__) so that it always appears on top in the files list. It imports only the files in its own folder, except for other summary indexes located in a direct subfolder. This way, you always can handle your imports very easily and stop the imports of nested files at any level.
Components definition files should have the same name as the component's folder name, and have a single underscore prefix, as they are content and not imports list.

SASS variables

Sass variable names should be composed of dash(-) separated parts, with each part sorted from the most generic to the most specific variable characteristic. This is quite useful in most IDE as you can take advantage of autocompletion.

For example :

// variables example
/* _____ VARIABLES _____ */
// Generic
// ==========================================================================
$default-borderRadius: 4;
$containerWidth: 760;
// Colors
// ==========================================================================
$color-default-light:   #fff;
$color-default-dark:    #333;
$color-default-darker:  #000;
$color-main:            #ff7f50;
$color-main-light:      #ff9e7e;
$color-main-lighter:    #ffdec7;
$color-secondary:       #5cbcaa;
$color-alt:             #f1ede4;
$color-alt-dark:        #c2c0bc;
$color-alt-light:       #f8f5ec;
$color-alt2:            #637c84;

Responsive

Introduction

Now that you're all familiar with the core concepts and basic implementation of DoCSSa, it's time to take it to the next level and see how we can handle Responsive Web Design (RWD).
As you may have noticed, the main menu on the page you are currently looking at changes depending on the width of the viewport. We'll use it as an example to show you how to handle RWD.

As always, there isn't a one size fit all solution, and your mileage may vary, but we thought it would be nice to provide at least one implementation of a responsive widget.

Dispatching the roles

In order to have responsive tabs on this page, we had to decide what was going to be part of a component, and what would be outside. We chose to create a responsive component that would display horizontally from 900px and up, and vertically below that breakpoint.
As a component should be as reusable as possible, we made that value a parameter of the component mixin.
We also wanted the vertical menu to be hidden by default, and only revealed when clicking on a burger icon. This is a specific implementation : all responsive tabs don't need to hide the menu when they are in vertical state. As such, we handled the hiding and revealing of the menu in the "specifics" part and kept the component unaware of those specifics.

Responsive component

Here is what our sample component looks like :

  • // components/responsiveTabs/_responsiveTabs.scss
// _____ STRUCTURE _____ //
// define the component structure
@mixin responsiveTabs($selector, $breakpoint: 900, $defaultSkin: true) {
  // handle tabs vertically until breakpoint
  @media (max-width: #{($breakpoint - 1)}px) {
    #{$selector} {
      padding: 0;
    }
    #{$selector}_link {
      display: block;
      padding: 20px;
    }
  }
  // handle tabs horizontally until breakpoint
  @media (min-width: #{$breakpoint}px) {
    #{$selector} {
      display: inline-block;
      margin: 0;
      padding: 0;
      font-size: 0;
    }
    #{$selector}_item {
      @include remIt(font-size, 18);
      display: inline-block;
      vertical-align: bottom;
      line-height: 2.5;
    }
    #{$selector}_link {
      padding: 0 10px;
    }
  }
  @if $defaultSkin != false {
    @include responsiveTabs-skin-default($selector, $breakpoint);
  }
}
// _____ SKIN _____ //
// provide a default skin for the component
// only visual changes that don't affect the component layout should be in here
@mixin responsiveTabs-skin-default($selector, $breakpoint) {
  #{$selector} {
    list-style: none;
  }
  #{$selector}_item {
    border-bottom: 1px solid $color-main-lighter;
  }
  #{$selector}_item--highlighted {
    background: $color-alt-light;
  }
  #{$selector}_link {
    @include basicClickable(true);
    color: $color-default-dark;
    font-family: 'titillium', Arial, 'sans-serif';
    #{$selector}_item._is_current & {
      color: $color-main-light;
    }
    &:hover {
      background: $color-alt;
    }
  }
  // set specific visual adjustments for horizontal display
  @media (min-width: #{$breakpoint}px) {
    #{$selector}_item {
      &._is_current {
        border-bottom: 3px solid $color-main-light;
      }
    }
    #{$selector}_link {
      border-left: 1px solid $color-main;
      #{$selector}_item:first-child & {
        border-left: 0;
      }
    }
  }
}

As usual, the component is split in two parts: the structure and the skin. Its implementation is located in specifics/_nav.scss:

@include responsiveTabs('.mainMenu', $breakpoint: 900);

As an experiment, you can add a "$defaultSkin: false" parameter to the call to see how the component looks like with no skin applied. You'll see that it behaves the same, but doesn't look as good.

On the structure part, things are quite simple: we declare a totally different set of rules for below or above the breakpoint. It is not mandatory, but can help avoiding regression in the long run.

On the skin part, we tried to keep most rules generic. We wanted both layout to have the same look&feel. Still, some visual enhancements only made sense in the horizontal display, so we made sure they got scoped to the correct media query.

Responsive implementation

Once we have a responsive component, all we have to do is give it some boundaries.
In the "specifics" section we call the component and pass it a breakpoint. We also set some rules to the "mainNav" wrapper according to this breakpoint: the position of the tabs in the page, and the visual enhancement that go with it. For example, we set a bottom drop shadow for the horizontal state of the menu, and a right drop shadow for its vertical state. We also make sure the burger menu toggler is hidden when we don't need it, and the vertical menu respects a specific width.

  • // specifics/_nav.scss
$nav-breakpoint: 900;
$left-nav-width: 200;
// bind the responsive tabs mixin to the .mainMenu class
@include responsiveTabs('.mainMenu', $breakpoint: 900);
// handle menu position and visibility
@media (max-width: #{($nav-breakpoint - 1)}px) {
  .mainNav {
    @include transition('left .2s linear');
    @include box-shadow(0 3px 3px 3px rgba(0, 0, 0, .3));
    position: absolute;
    top: 0;
    bottom: 0;
    left: -#{$left-nav-width}px;
    z-index: 999;
    background: $color-default-light;
    width: #{$left-nav-width}px;
    &._is_open {
      left: 0;
    }
  }
  .mainNav_opener {
    display: block;
    position: absolute;
    top: 20px;
    left: #{$left-nav-width + 20}px;
    z-index: 998;
    border: 1px solid $color-default-light;
    background: $color-main;
    padding: 0;
    width: 30px;
    height: 30px;
    overflow: hidden;
    text-indent: -999px;
    color: $color-default-light;
    &:before {
      display: block;
      width: 28px;
      height: 30px;
      text-align: center;
      text-indent: 0;
      line-height: 1.8;
      content: '\2630';
    }
    .mainNav._is_open &:before {
      content: '\2613';
    }
  }
}
@media (min-width: #{$nav-breakpoint}px) {
  .mainNav {
    @include box-shadow('0 3px 5px rgba(0,0,0,.3)');
    @include box-opacity(.95);
    position: fixed;
    top: 0;
    right: 0;
    bottom: auto;
    left: 0;
    background: $color-default-light;
    text-align: right;
  }
  .mainNav_opener {
    display: none;
  }
}

All there is left to do is use a bit of javascript to drive the state of the mainNav wrapper, and voila, a responsive menu we have!


Getting started

Download the kit

Download this page and its implementation of DoCSSa and play with it.
Source code can be found on DoCSSa's github page.

Learn about the basics

  • Handling Deferred Objects in DoCSSa [article]
  • Why DoCSSa ? [article]
  • Getting started with SASS [article]
  • Four ways to create CSS that's modular and scalable [article]
  • BEM methodology [official website]
  • Shubhie Panicker - CSS module system in Google+ (CSSconf.eu 2013) [video]

How to start ?

  1. First, you can simply write CSS code in separated files into the "specifics" folder, using DoCSSa's logic.
  2. Then, try manipulating the provided "_mixins" from the base/utils folder to give your project more reusable code.
  3. After that, you may write your own "_mixins", tailored for your own specific needs.
  4. For more reusability within or across your project(s), you may then try to convert some of your "specifics" rules into "components".
    If see you are repeating the same rules on different sets of classes, you have a good candidate.
  5. Been there, done that ? It's time to preach the choir ;)

I'm the team lead of a non expert koala army, how can I make use of DoCSSa's powers ?

  1. While your koalas are learning Sass, they can keep writing the same old CSS in 'specifics' folder
  2. Once one of them feels ready to, let her write a component and let the whole team know they can use it.
  3. It won't be long before some other koalas would like to write a useful component too.
  4. With knowledge adding up, it will become easier to detect components candidates.
  5. Don't forget to offer your koalas a lot of eucalyptus regularly.

Contributing

Contact us

DoCSSa is evolving!
We are very interested in your feedback to improve it or learn about how you implemented it.
Please contact us, fork the project, make Pull Requests or talk about DoCSSa at will.