Skip to content

Instantly share code, notes, and snippets.

@mwurzberger
Last active August 29, 2015 14:15
Show Gist options
  • Save mwurzberger/ecafa1319a4065d8f02f to your computer and use it in GitHub Desktop.
Save mwurzberger/ecafa1319a4065d8f02f to your computer and use it in GitHub Desktop.

Styles and Formatting - HTML


Preface

The goal of this document is not to give rules that result in perfect code. It is so that with minimal effort the code will:

  • Do what it is supposed to do
  • Reduce the lead time required to understand an implementation
  • Make it easier to establish what code can be reused
  • Clarify how updates to an implementation should be styled or structured

Styles

Naming

  • pageName.xsl file in the xsl/PATH/pages folder
  • pageName.js file in the js/PATH/pages folder
  • pageName.less file in the css/PATH/pages folder

Formatting

  • Indent all lines using two spaces
  • Do not use <br/>, place blocking elements like <div> as appropriate
  • Do not use <div> tags for spacing-only, modify the margin of the surrounding <div> tags
  • Tag attributes should use double-quotes, not sinqle-quotes
  • Use the <button> element instead of <input type="button">
  • Only use <table> elements when displayng tabular data
  • The id attribute should be in camelCase so that is matches the JavaScript conventions <div id="myPage">Contents</div>
  • If tags contain more than a small amount of content then the opening and closing tags should be placed on separate lines
<!-- Good -->
<div>
  <a href="#">Link Here</a>
  This is a test
</div>

<!-- Bad -->
<div><a href="#">Link Here</a>This is a test</div>

Page Layout

  • The <body> tag should have the attribute class="pageName-ns" set
  • Inline JavaScript - This should be avoided when possible. Use a binding event in the external pageName.js file.
  • Inline CSS - This should be avoided when possible. When needed add a new class to the element and define the changes in the external PAGE_NAME.less file.
<html>
  <header>
    <title>My Page</title>
    <link rel="stylesheet" type="text/css" href="bootstrap3.css" />
    <link rel="stylesheet" type="text/css" href="pageName.css" />
  </header>
  <body class="pageName-ns">
  </body>
  <footer>
  </footer>
  <script type="text/javascript" src="jquery-1.10.2.js">&#160;</script>
  <script type="text/javascript" src="pageName.js">&#160;</script>  
</html>

Styles and Formatting - JavaScript


Preface

The goal of this document is not to give rules that result in perfect code. It is so that with minimal effort the code will:

  • Do what it is supposed to do
  • Reduce the lead time required to understand an implementation
  • Make it easier to establish what code can be reused
  • Clarify how updates to an implementation should be styled or structured

Styles

Namespacing

  • All JavaScript should be wrapped in an object to prevent function name overlap and keep the code neat
if (! com) { var com = {}; }
if (! com.pageName) { com.pageName= {}; }

// Wrapping new functions and variables within an object as properties
com.pageName = {
  variableName: 'variableValue',
  functionName: function( param1 ) {
    // statements
  }
}

// Wrapping functions and variables within a function
// An API is returned from the function as a JS object, the properties are the publicly accessable functions and variables
// See example module-pattern-jquery.html
com.pageName = function() {
  var publicFunction = function() {
    privateFunction();
  }

  var privateFunction = function() {
    // statements
  }

  var oPublic = {
    publicFunction: publicFunction
  };

  return oPublic;
}
  • Calls can be made directly by using the entire path
com.pageName.functionName(param1);

Naming Conventions

  • Naming functions, objects, instances, etc
camelCase; // function and var declarations
functionNamesLikeThis;
variableNamesLikeThis;
methodNamesLikeThis;
  • Naming constructors, prototypes, etc
PascalCase; // constructor function
ConstructorNamesLikeThis;
EnumNamesLikeThis;
  • Naming Symbolic Constants using ALL_CAP_UNDERSCORED
SYMBOLIC_CONSTANTS_LIKE_THIS
  • No Abbreviations, use longer descriptive names
// Good
var deliveryNote = 1; 

// Bad
var delNote = 1; 
  • Collection names should match their contents or be explicit
'dog' is a string
'dogs' is an array 
'dogArray' is an array
  • Prefixes for metadata. Certain prefixes let the reader know details about the variable or function
// jQuery objects should be prefixed with $
var $curTarget = $(event.currentTarget);

// Regular Expressions prefixed with r
var rEmailer = //;

// Private methods are prefixed with _
com.pageName = function() {
  var publicFunction = function() {
    _privateFunction();
  }

  var _privateFunction = function () {
    // statements
  }

  var oPublic = {
    publicFunction: publicFunction
  };

  return oPublic;
}

Whitespace

  • Use 4 space indentation
  • Never mix spaces and tabs
  • No trailing whitespace on any line
  • No more than one blank line separating any other command
  • There should be no spaces between the function name and the first (
  • There should be a space after open parens and before close parens function( param1, param2 )
  • One space should be added following commas and colons {param1: "Hello", param2: "World"}

Beautiful Syntax

  • Parens, Braces, Linebreaks
// Open braces on same line as the previous statement
// Close braces on the same indent as the original function call
function func() {
  return {
    "name": "Batman"
  }; 
}

// Readability Examples
while( condition ) {
  // statements
}

if( true ) {
  // statements
} else {
  // statements
}

// Ternery if/else statments allowed
if( value > 100 ) ? alert('Expensive') : alert('Cheap');
  • Assignments, Declarations, Functions ( Named, Expression, Constructor )
// Using only one `var` per scope (function) promotes readability
// and keeps your declaration list free of clutter 
var foo = "",
    bar = "",
    quux;

// Literal notations:
var array = new Array(),
    object = new Object();

// var statements should always be in the beginning of their respective scope (function)
function foo() {
  var bar = "",
      qux;
  // statements
}
  • Callbacks can be passed in one of two ways
// Inline
$( "#target" ).click( function() {
  // statements
});

// By Reference
$( "#target" ).click( functionName );

// Constructor Declaration
function FooBar( options ) 
  this.options = options;
}

// Usage
var fooBar = new FooBar({ a: "alpha" });
fooBar.options;
  • Use single quotes for all strings. For complex jQuery selectors the single and double quotes can be reversed from the examples on the jQuery website.
// Good
$('.testId[href^="www.any.com"]').show(); 

// Bad
var word = "word";

Type Checking (Courtesy jQuery Core Style Guidelines)

  • Actual Types String: typeof variable === "string"
    Number: typeof variable === "number"
    Boolean: typeof variable === "boolean"
    Object: typeof variable === "object"
    Array: Array.isArray( arrayLikeObject )
    Node: elem.nodeType === 1
    null: variable === null
    null or undefined: variable == null

    undefined:

    Global Variables: typeof variable === "undefined"
    Local Variables: variable === undefined
    Properties:

    >    object.prop === undefined  
    >    object.hasOwnProperty( prop )  
    >    "prop" in object  
  • Coerced Types

    Consider the implications of the following...

    Given this HTML: html <input type="text" id="foo-input" value="1">

    // `foo` has been declared with the value `0` and its type is `number`
    var foo = 0;
    
    // typeof foo;
    // "number"
    
    // Somewhere later in your code, you need to update `foo`
    // with a new value derived from an input element
    
    foo = document.getElementById("foo-input").value;
    
    // If you were to test `typeof foo` now, the result would be `string`
    // This means that if you had logic that tested `foo` like:
    
    if ( foo === 1 ) {
      importantTask();
    }
    
    // `importantTask()` would never be evaluated, even though `foo` has a value of "1"
    
    // You can preempt issues by using smart coercion with unary + or - operators:
    
    foo = +document.getElementById("foo-input").value;
    //    ^ unary + operator will convert its right side operand to a number
    
    // typeof foo;
    // "number"
    
    if ( foo === 1 ) {
      importantTask();
    }
    
    // `importantTask()` will be called

    Here are some common cases along with coercions:

    var number = 1,
      string = "1",
      bool = false;
    
    number;
    // 1
    
    number + "";
    // "1"
    
    string;
    // "1"
    
    +string;
    // 1
    
    +string++;
    // 1
    
    string;
    // 2
    
    bool;
    // false
    
    +bool;
    // 0
    
    bool + "";
    // "false"
    
    string === number;
    // false
    
    string === number + "";
    // true
    
    +string === number;
    // true
    
    bool === number;
    // false
    
    +bool === number;
    // true
    
    bool === string;
    // false
    
    bool === !!string;
    // true

Conditional Evaluation

  • Use the === and !== operators. The == and != operators do type coercion. In particular, do not use == to compare against falsy values.
// When only evaluating that an array has length,
// instead of this:
if( array.length > 0 ) ...

// ...evaluate truthiness, like this:
if( array.length ) ...

// When only evaluating that an array is empty,
// instead of this:
if( array.length === 0 ) ...

// ...evaluate truthiness, like this:
if( !array.length ) ...

// When only evaluating that a string is not empty,
// instead of this:
if( string !== "" ) ...

// ...evaluate truthiness, like this:
if( string ) ...

// When only evaluating that a string _is_ empty,
// instead of this:
if( string === "" ) ...

// ...evaluate falsy-ness, like this:
if( !string ) ...

// When only evaluating that a reference is true,
// instead of this:
if( foo === true ) ...

// ...evaluate like you mean it, take advantage of built in capabilities:
if( foo ) ...

// When evaluating that a reference is false,
// instead of this:
if( foo === false ) ...

// ...use negation to coerce a true evaluation
if( !foo ) ...

// ...Be careful, this will also match: 0, "", null, undefined, NaN
// If you _MUST_ test for a boolean false, then use
if( foo === false ) ...


// When only evaluating a ref that might be null or undefined, but NOT false, "" or 0,
// instead of this:
if( foo === null || foo === undefined ) ...

// ...take advantage of == type coercion, like this:
if( foo == null ) ...

// Remember, using == will match a `null` to BOTH `null` and `undefined`
// but not `false`, "" or 0
null == undefined
  • ALWAYS evaluate for the best, most accurate result - the above is a guideline, not a dogma.
// Type coercion and evaluation notes

// Prefer `===` over `==` (unless the case requires loose type evaluation)

// === does not coerce type, which means that:

"1" === 1;
// false

// == does coerce type, which means that:

"1" == 1;
// true


// Booleans, Truthies & Falsies

// Booleans:
true, false

// Truthy:
"foo", 1

// Falsy:
"", 0, null, undefined, NaN, void 0

Comments

  • Comments are always preceded by a blank line. Comments start with a capital first letter, but don't require a period at the end, unless you're writing full sentences. There must be a single space between the comment token and the comment text; for multi-line comments a new line may be used in place of a space.
// We need an explicit "bar", because later in the code foo is checked.
var foo = "bar";

/*
Four score and seven-pause-minutes ago...
*/

function foo( types, selector, data, fn, /* INTERNAL */ one ) {
  // statements
}
/**
 * Reverse a string
 *
 * @param  {String} input_string String to reverse
 * @return {String} The reversed string
 */
function reverse(input_string) {
  // statements
  return output_string;
}

Based on a loosely on a work at github.com/rwldrn/idiomatic.js.

Styles and Formatting - LESS/CSS


Preface

The goal of this document is not to give rules that result in perfect code. It is so that with minimal effort the code will:

  • Do what it is supposed to do
  • Reduce the lead time required to understand an implementation
  • Make it easier to establish what code can be reused
  • Clarify how updates to an implementation should be styled or structured

Styles

Namespacing

  • All classes should be namespaced. In LESS this is relativly straight forward, wrap the entire document with a class that is the same as the pagename.

    • LESS
    #pageName-ns {
      .class1 {
        // styles
      }
      .class2 {
        // styles
      }
    }
    • CSS
    #pageName-ns .class1 {
      // styles
    }
    #pageName-ns .class2 {
      // styles
    }

<a name="formatting">Formatting</a>
- Do not create a class for only one element; use the element ID instead
- When specifying length values, do not specify units for a zero value, e.g., left: 0px; becomes left: 0;  
- Use single quotes instead of double quotes for all strings
- Where equivalent, use the opacity property instead of rgba(0, 0, 0, a)

<a name="selectors">Selectors</a>
- Use the dash-format to name classes
```css
.class-name-dashed {
  // styles
}
  • Use two colons when addressing a pseudo-element (i.e. ::after, ::before, ::-webkit-scrollbar) for readability
a::after {
  // styles
}
  • Only one selector should be on each line
// Good
.raw-button-one,
.raw-button-two,
.raw-button-three {
  // styles
}

// Bad    
.raw-button-one, .raw-button-two, .raw-button-three {
  // styles
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment