Crafted CSS

This is a personal compilation of CSS practices I follow.

Inspiration was drawn from Nicholas Gallagher’s Idomatic CSS, Jonathan Snook’s SMACSS, Harry Robert’s HTML/CSS Coding Style, Nicole Sullivan’s OOCSS, Yandex’s BEM, Github’s CSS Style Guide, Google’s HTML/CSS Style Guide and my own experience with CSS over the years.

All code in any code-base should look like a single person typed it, no matter how many people contributed. – Nicholas Gallagher

Contents

General

Formatting

Whitespace

Example showing the proper use of whitespace:

.btn {
    background-image: linear-gradient(to bottom, #0cf, rgba(255, 255, 255, 0.5));
}

Numbers

URLs

Protocol-relative url example:

.example {
    background-image: url(//chrisnager.com/images/image.png);
}

Colors

Vendor prefixes

.btn {
    -webkit-transition: background-color 0.4s ease-in-out;
    -moz-transition: background-color 0.4s ease-in-out;
    -o-transition: background-color 0.4s ease-in-out;
    transition: background-color 0.4s ease-in-out;
}

Font-size / line-height

html {
    font: 16px/1.6 sans-serif;
}

h1 {
    font-size: 40px; /* Fallback */
    font-size: 2.5rem; /* This makes your h1 40px/64px. */
}

Comments

Commenting formats:

/* ==========================================================================
   Comment level 1
   ========================================================================== */

.selector {
    property: value;
}






/* ==========================================================================
   Here's another level 1 comment
   ========================================================================== */

/* Have you seen level 2 comments?
   -------------------------------------------------------------------------- */
.selector {
    property: value;
}



/* And...comment level 3
   ------------------------------------------------------ */
   
.selector {
    property: value;
}
.selector {
    property: value;
}



/* But wait! There's more. Comment level 4 */
.selector {
    property: value;
}

.selector {
    property: value;
}



/* Level 2 comment
   -------------------------------------------------------------------------- */
.selector {
    property: value;
}






/* ==========================================================================
   Another level 1 comment
   ========================================================================== */

.selector {
    property: value; /* A wild inline comment appeared! */
}

Order

You should follow this five-group model for crafting your CSS.

  1. Base - includes your elements without classes html {}, a {}, a:hover {}

  2. Layout - includes elements that make up the structure of the page .l-module {}, .l-content {}

  3. Module - includes typical elements that contain the content .nav {}

  4. State - define your JS state classes here .is-active {}

  5. Theme - includes variations of module elements .btn--dark {}

General declaration order:

.btn {
    /* Box model */
    content: " »";
    box-sizing: border-box;
    
    width: auto;
    min-width: 0;
    max-width: none;
    height: auto;
    min-height: 0;
    max-height: none;

    margin: 0 auto;
    margin-top: 0;
    margin-right: auto;
    margin-bottom: 0;
    margin-left: auto;
    border: 0;
    border-top: 0;
    border-top-width: 0;
    border-right: 0;
    border-right-width: 0;
    border-bottom: 0;
    border-bottom-width: 0;
    border-left: 0;
    border-left-width: 0;
    border-radius: 0.15em;
    padding: 0.5em 1em 0.55em;
    padding-top: 0.5em;
    padding-right: 1em;
    padding-bottom: 0.55em;
    padding-left: 1em;

    /* List your positioning properties in TRBL (top, right, bottom, left) order. */
    position: relative;
    top: 0;
    right: auto;
    bottom: auto;
    left: 0;

    /* Display properties */
    display: inline-block;
    float: none;
    clear: none;
    z-index: 1;

    list-style: katakana inside;
    list-style-type: katakana;
    list-style-image: url(list-disc.png);
    list-style-position: inside;

    opacity: 0.9;
    cursor: pointer;

    /* Tables */
    table-layout: auto;
    border-collapse: collapse;
    border-spacing: 0.5em;
    caption-side: top;
    empty-cells: show;
    speak-header: always;

    /* Typographic styles */
    font: 1.5rem sans-serif;
    font-family: sans-serif;
    font-variant: small-caps;
    font-size: 1.5rem;
    font-size-adjust: none;
    font-weight: bold;
    font-style: italic;
    font-stretch: normal;

    line-height: 1.5;
    letter-spacing: -0.1em;

    white-space: nowrap;
    word-spacing: normal;

    text-indent: 1em;
    text-align: center;
    text-transform: uppercase;
    text-decoration: underline;
    text-shadow: 0.1em -0.1em rgba(0, 0, 0, 0.8);

    /* Colors and backgrounds */
    color: white;

    background: none;
    background-color: red;
    background-image: url(btn-bg.png);
    background-position: right center;
    background-repeat: no-repeat;
    background-size: contain;
    
    /* Other presentational properties */
    box-shadow: 0 0.1em 0.5em black;
    transform: rotate(3deg);
    transition: color 1s ease-out;
    animation: flip 3s all;
}

Exceptions

Take for example a large sprited image of national flags:

.icon--flag {
    width: 15px;
    height: 10px;
    border: 1px solid gold;
    display: inline-block;
    background-image: url(//path.to/sprite.png);
}

.icon--flag-1 { background-position: 0 -10px; }
.icon--flag-2 { background-position: 0 -20px; }
.icon--flag-3 { background-position: 0 -30px; }
.icon--flag-4 { background-position: 0 -40px; }
.icon--flag-5 { background-position: 0 -50px; }
.icon--flag-6 { background-position: 0 -60px; }

Responsive Design

OOCSS and BEM

OOCSS example:

.btn {}
.btn--primary {}
.btn--secondary {}

How BEM should be written:

.block__element--modifier {}

Block
.menu {}

Block + Modifier
.menu--vertical {}

Block + Element
.menu__menu-items {}

Block + Element + Modifier
.menu__menu-items--rev {}

Real world example of OOCSS in action using a BEM-style class structure:

<a href="/" class="btn  btn--large  btn--positive">Submit</a>
.btn {
    border-radius: 0.1em;
    padding: 0 0.75em;
    display: inline-block;
    line-height: 1.75em;
    white-space: nowrap;
    color: white;
    background-color: gray;
}



.btn--small {
    padding-right: 0.5em;
    padding-left: 0.5em;
    line-height: 1.5em;
}

.btn--large {
    padding-right: 1em;
    padding-left: 1em;
    line-height: 2em;
}



.btn--positive {
    background-color: limegreen;
}

.btn--negative {
    background-color: orangered;
}

JavaScript

Preprocessors

I encourage splitting your SCSS/Less/Stylus files into a maintainable folder structure with chunks of related styles.

Like this:

project-name.scss vars.scss

More on this to come…