Coding Etiquette

Golden rule: Every line of code should appear to be written by a single person, no matter the number of contributors.

TOC

  1. General
    1. Editor Preferences
    2. Commenting Your Code
    3. Keep It Modular
  2. HTML
    1. Syntax
    2. Attribute Order
    3. Javascript Generated HTML
  3. CSS
    1. Syntax
    2. Single Declarations
    3. Nesting in Sass

General

Editor Preferences

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

  • Use soft-tabs set to four spaces.
  • Trim trailing white space on save.
  • Set encoding to UTF-8.
  • Add new line at end of files.

Consider documenting and applying these preferences to your project’s .editorconfig file.

The example to the right is our Preferences.sublime-settings defaults (minus the theme being used – thats up to you).

We recommend using sublime, installing the package manager and the Seti_UI theme.

{
    "bold_folder_labels": true,
    "draw_white_space": "all",
    "folder_exclude_patterns":
    [
        ".svn",
        ".git",
        ".hg",
        "CVS",
        ".sass-cache",
        "node_modules"
    ],
    "highlight_modified_tabs": true,
    "ignored_packages": ["Vintage"],
    "scroll_past_end": true,
    "trim_trailing_white_space_on_save": true,
    "tab_size": 4
}

 

Commenting Your Code

Commenting your code is very important for the future of your project.

Make a habit out of commenting each block, function or “workaround” in your code to save the sanity of you or any future colleagues when revisiting a project.

If you use sublime text, install “DocBlockr” for easy documentation of functions, classes etc in various languages.

Even if you don’t use sublime, check out the DocBlockr page to see how to format your comments in other editors.

/**
 * Calculate the average and maximum profit per acre/hectare
 * @param  int seed_qty         quantity of seeds to be planted
 * @param  int est_return       estimated gross monetary return per acre
 * @param  int price_per_1000   decimal cost of seeds per 1000 units
 * @param  int percent_avg      percentage value of average improvement to species
 * @param  int percent_max      percentage value of maximum improvement to species
 * @return array                 average and maximum profit based on variables
 */
calculator.getImprovementPerArea = function (seed_qty, est_return, price_per_1000, percent_avg, percent_max) {
    var avg = est_return * (percent_avg / 100) - price_per_1000 * (seed_qty / 1000);
    var max = est_return * (percent_max / 100) - price_per_1000 * (seed_qty / 1000);
    return [avg, max];
};

 

Keep It Modular

Modular code is easier to read, maintain and document!

Each “function” or “task” (php, js etc) in your code should do one thing, and do it well.

If you have the need to perform multiple tasks in one go, separate each of those tasks out into their own functions, and call them from a wrapper function.

The same applies for styling a site:
panels.scss can contain a default panel style, as well as any hover states, variations of background and border colour and animations which may occur.

If you find your file length is getting a little verbose, then perhaps you need to split your file into more manageable, smaller files.
For example, the functions file can easily grow large in a WordPress project, why not separate out things like “theme setup functions”, or “media related functions” into their own files and include() them?

// helper object
let helper = {};

// viewport
helper.viewport = {
    width  : function(){ return Math.max(document.documentElement.clientWidth, window.innerWidth || 0); },
    height : function(){ return Math.max(document.documentElement.clientHeight, window.innerHeight || 0); },
};

// breakpoints
helper.breakpoint            = {};
helper.breakpoint.isPortable = function(){return (helper.viewport.width() <= 1024) ? true : false; };
helper.breakpoint.isPalm     = function(){return (helper.viewport.width() <= 667) ? true : false; };
helper.breakpoint.isLap      = function(){return (helper.viewport.width() >= 668 && helper.viewport.width() <= 1024) ? true : false; };
helper.breakpoint.isLapAndUp = function(){return (helper.viewport.width() >= 569) ? true : false; };
helper.breakpoint.isDesk     = function(){return (helper.viewport.width() >= 1025) ? true : false; };
helper.breakpoint.isDeskWide = function(){return (helper.viewport.width() >= 1200) ? true : false; };

HTML

Syntax

  • Use soft tabs with four spaces — they’re the only way to guarantee code renders the same in any environment.
  • Nested elements should be indented once (four spaces).
  • Always use double quotes, never single quotes, on attributes.
  • Don’t include a trailing slash in self-closing elements—the HTML5 spec says they’re optional.
  • Don’t omit optional closing tags (e.g. </li> or </body>).

<!DOCTYPE html>
<html>
    <head>
        <title>Page title</title>
    </head>
    <body>
        <h1 class="hello-world">Hello, world!</h1>
    </body>
</html>

 

Attribute Order

HTML attributes should come in this particular order for easier reading of code.

  • class
  • id, name
  • data-*
  • src, for, type, href, value
  • title, alt
  • role, aria-*

Classes make for great reusable components, so they come first. Ids are more specific and should be used sparingly (e.g., for in-page bookmarks), so they come second.

<a class="…" id="…" data-toggle="modal" href="#">
  Example link
</a>

<input class="form-control" type="text">

<img src="..." alt="...">

 

JavaScript Generated HTML

If it can’t be avoded, then make sure it’s clear where the markup is coming from with a data-origin attribute.
$('<div class="…" data-origin="slider.js">')
    .appendTo('body');

CSS

Syntax

  • Use soft tabs with four spaces—they’re the only way to guarantee code renders the same in any environment.
  • When grouping selectors, keep individual selectors to a single line.
  • Include one space before the opening brace of declaration blocks for legibility.
  • Place closing braces of declaration blocks on a new line.
  • Include one space after : for each declaration.
  • Each declaration should appear on its own line for more accurate error reporting.
  • Declarations should be in alphabetical order.
  • End all declarations with a semi-colon. The last declaration’s is optional, but your code is more error prone without it.
  • Comma-separated property values should include a space after each comma (e.g., box-shadow).
  • Don’t include spaces after commas within rgb(), rgba(), hsl(), hsla(), or rect() values. This helps differentiate multiple values (comma, no space) from multiple property values (comma with space).
  • Don’t prefix property values or color parameters with a leading zero (e.g., .5 instead of 0.5 and -.5px instead of -0.5px).
  • Lowercase all hex values, e.g., #fff. Lowercase letters are much easier to discern when scanning a document as they tend to more unique shapes.
  • Use shorthand hex values where available, e.g., #fff instead of #ffffff.
  • Quote attribute values in selectors, e.g., input[type=”text”]. They’re only optional in some cases, and it’s a good practice consistency.
  • Avoid specifying units for zero values, e.g., margin: 0; instead of margin: 0px;.
/* Bad CSS */
.selector, .selector-secondary, .selector[type=text] {
    background-color:rgba(0, 0, 0, 0.5);
    box-shadow:0px 1px 2px #CCC,inset 0 1px 0 #FFFFFF
    margin:0px 0px 15px;
    padding:15px;
}

/* Good CSS */
.selector,
.selector-secondary,
.selector[type="text"] {
    background-color: rgba(0,0,0,.5);
    box-shadow: 0 1px 2px #ccc, inset 0 1px 0 #fff;
    margin-bottom: 15px;
    padding: 15px;
}

 

Single declarations

In instances where a rule set includes only one declaration, consider removing line breaks for readability and faster editing. Any rule set with multiple declarations should be split to separate lines.The key factor here is error detection — e.g., a CSS validator stating you have a syntax error on Line 183. With a single declaration, there’s no missing it. With multiple declarations, separate lines is a must for your sanity.

/* Single declarations on one line */
.span1 { width: 60px; }
.span2 { width: 140px; }
.span3 { width: 220px; }

/* Multiple declarations, one per line */
.sprite {
    background-image: url(../img/sprite.png);
    display: inline-block;
    height: 15px;
    width: 16px;
}
.icon           { background-position: 0 0; }
.icon-home      { background-position: 0 -20px; }
.icon-account   { background-position: 0 -40px; }

 

Nesting in Sass

Nesting should only occur in the following situations:

  • If scoping is needed (parent > child)
  • If multiple elements need nesting

Don’t nest more than 3 levels deep! Consider replacing nested elements with class names.

Additional reading: Nesting in Sass and Less

// Without nesting
.table > thead > tr > th { … }
.table > thead > tr > td { … }

// With nesting
.table > thead > tr {
    > th { … }
    > td { … }
}