Code Guide by @solislab

SCSS

Syntax

Tab Indent

/*
  Add 1 space between class and { tag
  Bad is .hero__headline{
*/

.hero__headline {
  /*
    Add 1 space after :
    Bad is display:block;
   */
  display: block;
  /*
    Add ; to the end of row
    Bad is margin-bottom: 1em
   */
  margin-bottom: 1em;
  padding: 15px;
  background-color: rgba(0,0,0,.5);
  /*
  The close } tag should be in a single row
   */
}

Define global values before using

You should look into _variable.scss to find any global variable like color, font, breakpoints, etc...

The file _typography.scss always include pre-defined typography for Heading, text

The file _button.scss should have pre-defined button styling.

/*
Read /src/scss/ folder
Looking for existing .h1 class from _typography.scss
Looking for existing color $c-blue from _variables.scss
Looking for existing mixin transition from _utils.scss
 */

.hero__headline {
  @extend. h1;
  @include transition;
  color: $c-blue;
}

Declaration order

Related property declarations should be grouped together following the order:

  1. Extends and mixin
  2. Positioning
  3. Box model
  4. Typographic
  5. Visual

Extends and mixins should be add first cause it keep us understand what they override.

Positioning comes second because it can remove an element from the normal flow of the document and override box model related styles. The box model comes next as it dictates a component's dimensions and placement.

Everything else takes place inside the component or without impacting the previous two sections, and thus they come last.

For a complete list of properties and their order, please see Recess.

. {
  /* Keep extends and mixins in the top */
  @extend .section;
  @include transition;
  /* Then declarations */

  /* Positioning */
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 100;

  /* Box-model */
  display: flex;
  width: 100px;
  height: 100px;

  /* Typography */
  font: normal 13px "Helvetica Neue", sans-serif;
  line-height: 1.5;
  color: #333;
  text-align: center;

  /* Visual */
  background-color: #f5f5f5;
  border: 1px solid #e5e5e5;
  border-radius: 3px;

  /* Misc */
  opacity: 1;
}

Media query

Place media queries inside each class. Keep mobile-first: define in mobile, then in large screens.

.hero__item {
  @extend .headline;
  width: 100%;
  /*
    Keep to use @media inside class in SCSS
    Keep mobile first: mobile, then other large screen
   */
  @media (min-width: 25em) {
    width: 50%;
  }
  @media (min-width: 30em) {
    width: 25%;
  }
}

Prefixed properties

You don't need to insert prefix for other web browsers. Our workflow always include the way to add prefix after compiling.

.hero {
    display: flex;
    /*
    Not need add display: -webkit-flex;
     */
}

Single declarations

If it extends only one declaration, keep it shorten in same row with class name.

If it extends multiple declarations, add each of them in single row.

/* Multiple declarations, one per line */
.button {
  display: inline-block;
  padding: 15px 20px;
  background-color: black;
}
/*
  These below buttons use same class .button, extend only single declaration
*/
.button--red { background-color: red; }
.button--blue { background-color: blue; }

/* But keep multiple lines if it extends more than one declaration */

.button-outline {
  @extend .button;
  background-color: none;
  color: black;
}

Shorthand notation

Strive to limit use of shorthand declarations to instances where you must explicitly set all the available values. Common overused shorthand properties include:

Don't define only 1 value (like 10px) for margin and padding. Using at least two values (like margin: 0 10px;)

Override

In mobile, you define margin: 0 auto, so in large screen, you need to override margin-top only. Don't use `margin. Use margin-top is better way.

The Mozilla Developer Network has a great article on shorthand properties for those unfamiliar with notation and behavior.

/* Good example */
.element {
  /*
  Using at least two values for margin and padding
  BAD is margin: 10px; (while not need 10px for left and right)
 */
  margin: 0 auto;
  /*
  If not need set padding for left, right and top, don't use padding
  BAD is padding: 0 0 10px 0;
   */
  padding-bottom: 10px;
  /*
  Using background-image than background
  BAD is background: url('image.jpg');
   */
  background-image: url('image.jpg');
  /*
  If border-radius has 4 values while you define two only, avoid using border-radius
   */
  border-top-left-radius: 3px;
  border-top-right-radius: 3px;
}

Nesting in Less and Sass

Avoid unnecessary nesting. Just because you can nest, doesn't mean you always should. Consider nesting only if you must scope styles to a parent and if there are multiple elements to be nested.

Additional reading:

/*
Keep the code clean with BEM
Avoid nesting if needed until it must be
The BAD example is below
*/

.header__menu {
  .menu-item {
    a {
      color: $c-blue;
      &:hover {
        color: $c-black;
      }
    }
  }
}

/* Optimization for BETTER code */

.header__menu {}
.header__menu-item {}
.header__menu-link {
  color: $c-blue;
  &:hover {
    color: $c-black;
  }
}

Operators in Less and Sass

For improved readability, wrap all math operations in parentheses with a single space between values, variables, and operators.

// Bad example
.element {
  margin: 10px 0 $gutter*2 10px;
}

// Good example
.element {
  margin: 10px 0 ($gutter * 2) 10px;
}

Comments

Code is written and maintained by people. Ensure your code is descriptive, well commented, and approachable by others. Great code comments convey context or purpose. Do not simply reiterate a component or class name.

Be sure to write in complete sentences for larger comments and succinct phrases for general notes.

/* Bad example */
/* Modal header */
.modal-header {
  ...
}

/* Good example */
/* Wrapping element for .modal-title and .modal-close */
.modal-header {
  ...
}

Class names

It's also useful to apply many of these same rules when creating Sass and Less variable names.

/* Bad example */
.t { ... }
.red { ... }
.header { ... }

/* Good example */
.tweet { ... }
.important { ... }
.tweet-header { ... }

Selectors

/* Bad example */
span { ... }
.menu-item a {}
.page-container #stream .stream-item .tweet .tweet-header .username { ... }
.avatar { ... }

/* Good example
Using BEM class
*/
.hero__headline {}
.hero__button {}
.hero__link {}

/* Extends parent class if need override */
.hero__headline {
    @extend .h2;
    /* If body class contains home */
    .home & {
        @extend .h2-home;
    }
}

Organization

/* Add from top parent to child */
.hero {
    /* Keep other component (like social-links) below if they are under this hero with other style */
    .social-links {}
    /* BAD is below. Don't nesting because .hero--home can override .hero without adding it inside */
    &.hero--home {}
}

/* Keep extend class below, don't add it inside .hero class */
.hero--home {
    /* Then add any child element needs override */
    .hero__headline {}
    .hero__button {}
}

.hero__container {}
.hero__headline {}
.hero__list {}
.hero__button {}

Editor preferences

Set your editor to the following settings to avoid common code inconsistencies and dirty diffs:

Consider documenting and applying these preferences to your project's .editorconfig file. For an example, see the one in WordPress. Learn more about EditorConfig.