Introduction

This document is an overview of Front End development standards that we adhere to at Sapient. These best practices are collected from the experiences we've had with numerous, large-scale projects, as well as a variety of web resources. These standards will help reduce friction in your workflows by providing a common starting point and will serve as a useful intro for both new hires and contractors.

If you ever had to merge 103 files with somebody's tabs-to-spaces changes, you'll know what we mean.

We're happy to share this with the community and are excited to hear back form you - send us your comments and suggestions please create a fork and submit a pull request to start the conversation.

General Stuff

Here are a few basics to keep a common base in terms of documents and collaboration:

Source Control

All Sapient Projects use source control. While we generally have a self-hosted SVN repository setup, some projects use Git. All members of a team must have access to the repo (yes, including Designers) and are mandated (yes, especially Designers!) to use it.

UTF-8

Save your text-based files as UTF-8. For HTML files, don't forget to declare it with a meta-tag. Serve them as UTF-8 as well, by working with the backend team to set the right HTTP headers.

Document Settings

Use Unix line endings LF to make documents. Many DIFF clients choke on mismatched line endings (MS Windows defaults to CR+LF).

Whitespace / Indentation

Only one style should exist across the entire source of your project. Always be consistent in your use of whitespace. Use whitespace to improve the readability of any code.

Use indentation consistently to enhance the readability of the code. When elements carry over more than one line of code, indent the contents of elements between the start tag and the end tag. This will make it easy to see where the element begins and ends. Also, use indentation to align code at attribute names.

It is a good idea to use no more than two to four spaces for each level in indentation, so as not to use up all the available line length in indentation. If possible, set up the development tool to convert tabs to spaces so that the indentation will be the same when the source is viewed in different editors or as printed output.

Tip: configure your editor to "show invisibles". This will allow you to eliminate end of line whitespace, eliminate unintended blank line whitespace, and avoid polluting commits.

Example


    <div>
      <h3>NEXT MATCH</h3>
      <div class="contentd">
        <div class="info">
          <h4 class="fixture">CITY v<br>
            ARSENAL</h4>
          <p class="detail"> <strong>Home</strong><br>
            Barclays Premier League<br>
            Sat 19 Nov 11, 12:45<br>
          </p>
        </div>
        <div class="matchLinks borderTop">
          <ul>
            <li class="divider"><a href="#" class="livePlayer">Listen live on </a></li>
            <li ><a href="matchPreview.shtml" class="matchPreview">Match preview</a></li>
            <li class="divider"><a href="#" class="smsAlert">Mobile alerts</a></li>
            <li ><a href="#" class="buyTickets">Buy tickets</a></li>
          </ul>
        </div>
      </div>  
    </div>
    

Validation

A reasonable effort should be made to write code that passes validation services and linters. There are exceptions created by third party libraries or by certain back-end systems, but you, as a developer, are responsible for creating standards based, valid HMTL, CSS and JS code.

Code Comments

Comments are the lifeblood of a successful development environment. It's a vital communication channel for developers separated by both time and geography.

More information about commenting style can be found in the HTML, CSS and JavaScript sections.

Browser Matrix

The typical NA/EU Browser at Sapient matrix looks like this:

Windows 7/8

Internet Explorer 9 - 11
Firefox Latest stable
Chrome Latest stable
Safari no longer supported 

Mac OS 10.9 - 10.10

Firefox Latest stable
Chrome Latest stable
Safari7 - 8

Note that based on the client's analytics, sometimes legacy browsers such as Firefox 4.0 might need to be supported. A conversation around this should happen if current usage on the specific site is above 3% for a specific browser and not projected to drop below that until the go live date of the site or if specific business reasons demand support.

You might also consider a graded approach like described in Yahoo’s graded browser support.

HTML

When creating text/html, all you need is a Document Type Declaration or short doctype to trigger standards mode.


    <!DOCTYPE html>
    

HTML(5)

At Sapient, we write HTML5 code, unless there is a very specific need to use XHTML.

When you write any HTML, it has to be:

Note: HTML5 can written as valid XML, but unlike XHTML it is an option and not a requirement.

Character Encoding:

Use UTF-8 to encode your files, and declare it by placing


    <meta charset="utf-8">
    

right after your <head>-tag (Really - place it right behind it to avoid re-rendering in IE).

Unless you chose XHTML (see above - why did you choose it again?) - then you have to use


    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    

HTML Comments

HTML comments have the following syntax:


    
    
    

White space is not permitted between the markup declaration open delimiter("<!") and the comment open delimiter ("--"), but is permitted between the comment close delimiter ("--") and the markup declaration close delimiter (">"). A common error is to include a string of hyphens ("---") within a comment. Authors should avoid putting two or more adjacent hyphens inside comments. Information that appears between comments has no special meaning (e.g., character references are not interpreted as such). Note that comments are markup. Avoid multi-level html comments. (shown below)

Incorrect


    <html>
    <head>
      <!-- Multi-line comment begin
      <!-- This script does abcxyz -->
      <script>...</script>
      <script>...</script>
      Multi-line comment end -->
      <script>...</script>
    </head>
    <body>
      Hello world!
    </body>
    </html>
    

Correct


    <html>
      <head>
        <!-- Comment begin -->
        <!-- This script does abcxyz -->
        <script>...</script>
        <script>...</script>
        <!-- Comment end -->
        <script>...</script>
      </head>
      <body>
        Hello world!
      </body>
    </html>
    

W3 reference on comments

Conditional Comments

Conditional comments are the preferred means of differentiating Cascading Style Sheets (CSS) rules intended for specific versions of Internet Explorer.

The basic syntax of each type of comment is shown in the following table. The first comment shown is the basic HTML Comment, which is included for the purpose of comparison and to illustrate the different syntax used by each type of conditional comment.

Comment type Syntax or possible value
standard HTML comment <!-- Comment content -->
downlevel-hidden <!--[if expression]> HTML <![endif]-->
downlevel-revealed <![if expression]> HTML <![endif]>

Examples


    
    
    
    
    
     
      

Reference

<title>

Keep the text of your <title>-tag short and relevant. Make sure it's unique to the current page. It's what visitors from Search engines will see as the big blue link you want them to click on, so it better be sexy, too!

Meta tags

HTML meta tags are officially page data tags that we include between the open and closing head tags in the HTML code of a document.

The text in these tags is not displayed, but pars-able and tells the browsers (or other web services) specific information about the page. Simply, it “explains” the page so a browser can understand it.

Also using these a great way for web masters to provide search engines with information about their sites.

Most commonly used meta tags

    <meta name="description" content="goes here..."/>
    
This tag provides a short description of the page. The description is used as a part of the snippet shown in the search results, so it's definitely relevant - if it's teasing users to click your site in the search results it did the trick. Needs to be tailored to the specific page it's on and should typically be crafted by an editor.

    <meta name="keywords" content="keyword 1, keyword 2"/>
    
The keywords are used by some search engines to index your document in addition to words from the title and document body. Typically used for synonyms and alternates of title words. Not quite as relevant for SEO anymore these days as they were hit by a lot of keyword spamming, but if you have tags in say your CMS for a specific page, it's still worth feeding them in here. Should definitely be unique per page.

    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
    
(control zoom in mobile browsers) The <meta name="viewport"/> meta tag can be used to control how HTML content will appear in mobile browsers. This can have multiple properties with comma-separated. name=value, name=value, ... Please note that the "value"s are not enclosed in quotation marks.
Properties
width
width=device-width or width=nnn where nnn is the number of pixels between 200 and 10000 such as in width=980 (default)
height
height=device-height or height=nnn where nnn is the number of pixels between 223 and 10000
minimum-scale
minimum-scale=f.ff where f.ff is a floating point number between 0.0 and 10.0 such as in minimum-scale=0.25 (default)
maximum-scale
maximum-scale=f.ff where f.ff is a floating point number between 0.0 and 10.0 such as in maximum-scale=1.6 (defaut)
initial-scale
initial-scale=f.ff where f.ff is a floating point number between minimum-scale and maximum-scale
user-scalable
user-scalable=yes (default) to allow the user to zoom in or zoom out on the web page or user-scalable=no to prevent the user from zooming in or zooming out
Note that when a size is specified in pixels, it is not necessarily the number of actual pixels on the device, which can vary from one device to another. It is the number reference pixels, which is defined in CSS as the visual angle of one pixel on a device with a pixel density of 96dpi and a distance from the reader of an arm's length. This allows a web site to be displayed the same on devices with different screen sizes and pixel density. Example:

    <meta name="viewport" content="width=device-width; height=device-height; maximum-scale=1.4; initial-scale=1.0; user-scalable=yes"/>
    
Meta tags for search engine optimization (SEO)

    <meta name="robots"/>
    
It controls the behavior of search engine crawling and indexing. The robots meta tag applies to all search engines. It is still one of the most important meta tags. Believe it or not, it is still common for a site to be deindexed because someone accidentally added a noindex tag to the entire site. Understanding this tag is vitally important. The default values are "index, follow" (the same as "all") and do not need to be specified.

    <meta name="google"/>
    
When we recognize that the contents of a page are not in the language that the user is likely to want to read, we often provide a link to a translation in the search results. In general, this gives you the chance to provide your unique and compelling content to a much larger group of users. However, there may be situations where this is not desired.

    <link rel="canonical" href="http://www.example.com/original/&quot; />
    
Not strictly a meta-tag, but still very useful - this allows you to avoid the duplicate-content problem with search engines by telling it that it should list another URI instead of the current one for the content it's seeing on the current page.

    <meta name="googlebot"/>
    
The tag provides a list of search engine directives, consisting of special predefined terms separated by commas, that provide instructions for Google's search engine crawler. The below table represents the values to be used for both “robots” and “googlebot” meta tags. The robots meta tag applies to all search engines, while the "googlebot" meta tag is specific to Google.
noarchive The value noarchive indicates that a current snapshot of the page should not be permanently stored by Google. Otherwise a cached version of a web page, which shows how it looked when the page was last crawled, is available via a "Cache" link on Google's search engine results pages (SERPs).
nofollow The value nofollow tells Google's search engine robot that it should not access any web pages linked to by the current page.
noindex The value noindex tells Google to exclude the current page from their results.
noodp The value NOODP indicates that any site information in the Open Directory Project (dmoz.org) should not be used in Google's search engine results.
nosnippet The value nosnippet indicates that verbatim content from the web page should not be used by Google in the search engine results page (SERP).


    <meta name="verify"/>
    
You can use this tag on the top-level page of your site to verify ownership for Webmaster Tools. Please note that while the values of the "name" and "content" attributes must match exactly what is provided to you (including upper and lower case), it doesn't matter if you change the tag from XHTML to HTML or if the format of the tag matches the format of your page.

    <meta http-equiv="X-UA-Compatible"/>
    
X-UA-Compatible is used to indicate to an IE browser which version of the rendering engine should be used to display the page. This meta tag does not affect other browsers such as Firefox and Opera, which in general attempt to avoid bloating the size of the browser code by displaying web pages only one way according to established standards (Supporting multiple rendering engines presents some major challenges, especially when content rendered by one engine accesses embedded content rendered by a different engine). If at all possible it's more bulletproof to serve this directive and as HTTP Header. Here's an example taken from the HMTL5Boilerplate project showing how to do this on Apache

    <IfModule mod_headers.c>
      Header set X-UA-Compatible "IE=Edge,chrome=1"
      # mod_headers can't match by content-type, but we don't want to send this header on everything...
      <FilesMatch ".(js|css|gif|png|jpe?g|pdf|xml|oga|ogg|m4a|ogv|mp4|m4v|webm|svg|svgz|eot|ttf|otf|woff|ico|webp|appcache|manifest|htc|crx|oex|xpi|safariextz|vcf)$" >
      Header unset X-UA-Compatible
      </FilesMatch>
    </IfModule>
    
Meta tags for HTML pages on Mobile / handheld devices

    <link rel="apple-touch-icon" />
    
(for Web Clips) A Web Clip is a link to a web page or content from a web page that has been saved to a device along with an icon on the home screen that can be used to display it.

    <meta name="format-detection"/>
    
When running in a browser on a mobile phone, this tag determines whether or not telephone numbers in the HTML content will appear as hypertext links. The user can click a link with a telephone number to initiate a phone call to that phone number.

    <meta name="format-detection" content="telephone=yes"/>
    
(default on Safari in iOS) content="telephone=yes" indicates that telephone numbers in the HTML code should appear as hypertext links that can be clicked to make a phone call.

    <meta name="format-detection" content="telephone=no"/>
    
content="telephone=no" indicates that telephone numbers in the HTML code should not appear as hypertext links.

    <meta name="HandheldFriendly"/>
    
This tag indicates to the browser that the page has been laid out by the developer to be viewable on a small screen, and that the browser should not attempt any further layout enhancements. While somewhat effective, it does not offer any granular control over the layout width – it’s just a true/false flag.
Meta tags for apps on Mobile / handheld devices

    <meta name="apple-mobile-web-app-capable"/>
    
For a mobile app, the apple-mobile-web-app-capable meta tag determines whether the application runs in web mode, with an address bar and navigation bar, or in full screen mode without them. content=”yes” - the application will run in full screen mode, without the address bar at the top and the navigation bar at the bottom. The JavaScript boolean variable window.navigator.standalone will be set to true. content=”no” - the application will run in web mode, with an address bar at the top and a navigation area at the bottom. The JavaScript boolean variable window.navigator.standalone will be set to false.

    <meta name="apple-mobile-web-app-status-bar-style"/>
    
This meta tag specifies the style of the status bar for a mobile app. This is relevant only if the this tag with content="yes" is also included. content="default" - The status bar color is the normal gray gradient and it does not overlap the HTML content. content="black" - The status bar is black and does not overlap the HTML content. content="black-translucent" - The status bar is translucent black and overlays a small strip at the top of the HTML content.

    <link rel="apple-touch-startup-image"/>
    
This meta tag specifies a startup image, which is an image that is displayed while an offline web application is being launched on the mobile device. For the iPhone and iPod Touch, the image must be in portrait orientation 320 pixels wide by 460 pixels high.

Including CSS and JS

Before you can get started with CSS and JavaScript you need to get them onto the page. This section outlines the best practices surrounding this common and important task.

Including CSS

For including CSS use <link> and not @import as a standard. This is an important performance consideration.

Here is an example of the correct way to link a stylesheet:


    <link rel="stylesheet" type="text/css" href="yourStylesheetName.css" />
    

CSS files should always be included in the HEAD of the document. Again, this is important from a performance perspective. This is especially important when you consider the perceived performance of a page. With the CSS rules in place before the body element is reached the browser is able to go about the important task of rendering your markup as early as possible.

For more information on CSS please see our CSS Standards.

Including JS

For including Javascript use a <script> element.

Here is an example of the correct way to include js:


    <script src="yourJavascript.js"></script>

    <script type="text/javascript" src="yourJavascript.js"></script>

The type attribute that is required in required in HTML 4, is an optional attribute in HTML5.

JS files should always be included near the END of a document, unless there is specific reason for importing elsewhere in the document. This is to maximize page performance. Keep the number of JS files to a minimum and avoid inline-JS (unless you know why it might be ok, don't do it)

For more information on JS please see our Javascript Standards.

Favicon

Have a designer create a favicon for any site you're working on. It's just part of doing it right™. Your Favicon should have an .ico extension and include a 32x32px and 16x16px version. Read more over at html-kit or Mathias Bynens.

Your Favicon should sit in the root folder - that way you don't need a <link rel="icon shortcut" href=""/> in your html. If you have to put the favicon in a different folder, create a redirect rule for it.

Apple-touch icons

Have a designer create touch icons for your site. That way your bookmark will look pretty when mobile users place it on their home screens. You should use this snippet instead of placing the files in the document root:


    <!-- For non-Retina iPhone, iPod Touch, and Android 2.1+ devices: -->
    <link rel="apple-touch-icon-precomposed" href="apple-touch-icon-precomposed.png">
    <!-- For first- and second-generation iPad: -->
    <link rel="apple-touch-icon-precomposed" sizes="72x72" href="apple-touch-icon-72x72-precomposed.png">
    <!-- For iPhone with high-resolution Retina display: -->
    <link rel="apple-touch-icon-precomposed" sizes="114x114" href="apple-touch-icon-114x114-precomposed.png">
    <!-- For third-generation iPad with high-resolution Retina display: -->
    <link rel="apple-touch-icon-precomposed" sizes="144x144" href="apple-touch-icon-144x144-precomposed.png">
    

Note: if your filename and rel-attribute ends in -precomposed, iOS will not put its fancy gloss over your icon. Read more over at Mathias Bynens or straight from Apple.

And now - everybody together!


    <!DOCTYPE html>
    <html class="no-js" lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible"/>
        <meta name="description" content="goes here..."/>
        <meta name="keywords" content="keyword 1, keyword 2"/>
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
        <meta name="robots"/>
    
        <link rel="stylesheet" href="your-single-deployment-stylesheet.css">
        <link rel="apple-touch-icon-precomposed" href="apple-touch-icon-precomposed.png">
        <link rel="apple-touch-icon-precomposed" sizes="72x72" href="apple-touch-icon-72x72-precomposed.png">
        <link rel="apple-touch-icon-precomposed" sizes="114x114" href="apple-touch-icon-114x114-precomposed.png">
        <link rel="apple-touch-icon-precomposed" sizes="144x144" href="apple-touch-icon-144x144-precomposed.png">
        <!-- JS Links should sit on the bottom of the page! -->
    </head>
    <body>
    ... content
    <script src="yourJavascript.js"></script>
    </body>
    </html>
    

Avoid deprecated elements

In general, it's best to avoid deprecated elements. Our goal is to use the best solutions possible. Its going to be a rare case indeed when a dead element from the 1990s is the best available solution.

How do you handle Deprecated elements

With the ever evolving technology, there are HTML elements and attributes that have now been declared deprecated by W3C (World Wide Web Consortium is the main international standards organization for the World Wide Web). "Deprecated" means that the elements no longer serve a purpose and have been replaced by other methods, mostly involving cascading stylesheets (CSS). Although it is recommended that web browsers continue to support them, eventually they will become obsolete. This section talks about the most common ones which are deprecated along with the recommended replacements for them.

Recommended replacements for deprecated elements
The CENTER tag and ALIGN attribute

Center-align text in an HTML page. These elements have also been replaced by CSS. Deprecated examples include but not limited to be:

      
    <p align="center">Centered paragraph</p>
    
    <center><img src="pic.gif"></center>
      
    

To align content on a page, the CSS property is text-align. It takes four possibilities: left, right, center and justify.
.class-name { text-align: center; }

      
    <p class="class-name">Centered text</p>
      
    

This tag works for inline content such as text or images, but block level elements like tables and DIV do not follow the rules above. However, there is a simple yet relatively less-promoted trick to center block elements. The right solution is to set the margin to auto, as in the following code. Change 200px to the width you would like the table to be:

      
    <table cellpadding="0" cellspacing="0" style="margin: auto; width: 200px; border: 1px solid black;">
      <tr>
      <td>Test</td>
      </tr>
    </table>
      
    

This should work in all browsers except Internet Explorer prior to version 7. Note that the auto value actually only has an effect of the left and right margins; it does not center elements vertically.

The FONT and BASEFONT tags

FONT and BASEFONT have been deprecated in favor of CSS.
The BASEFONT tag specifies a default font-color, font-size, or font-family for all the text in a document, the tag is only supported by Internet Explorer and deprecated in HTML 4.01

face
The actual font to use, such as Times New Roman or Arial. This has been superseded by the CSS property font-family. You can also specify the type of font (serif, sans-serif, etc).
size
The size of the font, relative to the default on the page. This has been replaced by the CSS property font-size. You can use any length value (px, em, in, mm).
color
The color of the font. This has been replaced by the CSS property color.

Deprecated example

      
    <basefont face="Arial" size="+1" color="green">Some text</basefont>
      
    

To set the font for a page using CSS (as per BASEFONT), you should put the following in your style sheet (replace the rules with your chosen CSS rules):
body { font-family: Arial, sans-serif; font-size: 100%; color: green; }

The BACKGROUND and BGCOLOR attribute

This attribute is used primarily to set a background image or color for the document or an element. The BGCOLOR attribute applies to the TABLE, TR, TD, TH and BODY elements. Fascinatingly, the BACKGROUND attribute was only ever defined for the BODY element, but most browsers support it for the same elements as BGCOLOR.

Deprecated example

    
    <table bgcolor="yellow" background="gradient.gif">
    <tr>
    <th>Col 1</th>
    <th>Col 2</th>
    </tr>
    
    

Both of these attributes can be easily replaced with CSS. The following code sample sets the image gradient.gif as the background to the whole page. However, as per CSS rules, if the image cannot be found, the supplied color (gray) will be used instead.
body { background: gray url("gradient.gif"); }

Similar styles can be applied to the table attributes:
table.class-name { background-color: yellow; }

Or, for different heading and data cell colors:
table.class-name th { background-color: yellow; }
table.class-name td { background-color: yellow; }

    
    <table class="class-name">
    <tr>
    <th>Col 1</th>
    <th>Col 2</th>
    </tr>
    <tr>
    <td>Data 1.1</td>
    <td>Data 1.2</td>
    </tr>
    <tr>
    <td>Data 2.1</td>
    <td>Data 2.2</td>
    </tr>
    </table>
    
    
The BORDER attribute

Applies a border to an image or object.

Deprecated example

    
    <img src="image.gif" width="15" height="20" alt="image" border="1">
    
    

Border attributes can be easily replaced with CSS. The following code sets the border width and border color to the image or object.
.class-name { border: 1px solid black; }

    
    <img src="image.gif" width="15" height="20" alt="image" class="class-name">
    
    
The HSPACE and VSPACE attributes

These were used on the IMG and OBJECT tags to sets the horizontal and vertical space .The same effect can be achieved with margins in CSS.

    
    <img src="image.gif" width="15" height="20" alt="image" style="margin: 0 2px 2px 5px;">
    
    
The LANGUAGE attribute

This attribute is used on the SCRIPT tag to name the type of script being used.

    
    <script language="JavaScript">...</script>
    
    

The w3c now states the type attribute should be used instead. The values for every scripting language are likely to be 'text' followed by a forward slash, then the name of the language. JavaScript is really the only scripting language used these days (and the only one supported by every major browser).

    
    <script type="text/javascript">...</script>
    
    
The WIDTH and HEIGHT attributes

HEIGHT applies to TH and TD, WIDTH applies to the TH, TD, HR and PRE tags. These can all be replaced by the simple width and height CSS rules. Note that it is still recommended to use the HTML attributes for images.

The NOWRAP attribute

NOWRAP applies to both the TD and TH elements. This attribute unwrap text wrapping. The same effect can be achieved with CSS property white-space

    
    <td style="white-space: nowrap">Let's try long piece of content that could stretch the table cell by quite a bit.</td>
    
    

CSS

The following chapter outlines a reasonable style guide for CSS development. It is liberally based on Nicolas Gallagher idiomatic-css.

Organization

Code organization is an important part of any CSS code base, and crucial for large code bases.

Here's a typical set-up for your CSS-files:

/css/framework/framework.css (if applicable)
/css/core.client.css (contains your reset basic, coloring, layouts [e.g. framework overwrites or your own declarations] and general declarations that don't belong into the other files)
/css/modules/modulename.client.css (contains styles for a specific module, only dependent on core and if necessary the framework)
/css/modules/modulename2.client.css (etc...)
/css/forms/forms.client.css (if necessary - generic form declarations)
/css/forms/forms.contact-us.client.css (for declarations for a specific contact-us module)

On each CSS-file, add the standard CSS file header before the first declaration:


    /**
    * NAME OF THE STYLESHEET (e.g. core.client.css)
    * The styles in this file represent all basic styles for the <CLIENT> <PROJECTNAME> site.
    * It includes a reset, the basic grid and some default components.
    *<br>* Why we are using the equals sign in the section identifier:
    * stopdesign.com/archive/2005/05/03/css-tip-flags.html
    * 
    * @project   PROJECT NAME
    * @date      YYYY-MM-DD 
    * @author    YOUR NAME, SapientNitro <YOUREMAIL@sapient.com>
    * @licensor  CLIENTNAME
    * @site      PROJECTNAME
    *
    * @dependency framework.css
    * @dependency core.client.css
    *
    */
    

In core.client.css, also include a block that lists out the colors per styleguide.


    * USE THIS IN CORE.CLIENT.CSS
    * @colordef  #333; Quasi black (for most of the copy)
    * @colordef  #666; Grey (for some special copy)
    * @colordef  #999; Light grey (toolbar and text color)
    * ..... Replace and enhance with your specific project colors      
    

Comment your CSS code

Well commented code is extremely important. Take time to describe components, how they work, their limitations, and the way they are constructed. Don't leave others in the team guessing as to the purpose of uncommon or non-obvious code.

Comment style should be simple and consistent within a single code base.

Tip: configure your editor to provide you with shortcuts to output agreed-upon comment patterns.

CSS example:


    /* ==========================================================================
    =SECTIONNAME 
    ========================================================================== */
    
    /* =SUB-SECTION NAME comment block
    ========================================================================== */
    
    /*
    * Group comment block.
    * Ideal for multi-line explanations and documentation.
    
    
    /* Basic comment */
    

SCSS example:


    // ==========================================================================
    // Section comment block
    // ==========================================================================
    
    // Sub-section comment block
    // ==========================================================================
    
    //
    // Group comment block
    // Ideal for multi-line explanations and documentation.
    //
    
    // Basic comment
    

Format

The chosen code format must ensure that code:

To that end the following recommendations are made for CSS formatting:


    .selector-1,
    .selector-2,
    .selector-3 {
      -webkit-box-sizing: border-box;
      -moz-box-sizing: border-box;
      box-sizing: border-box;
      display: block;
      color: #333;
      background: #fff;
    }
    

Declaration order

Declarations should be ordered in accordance with a single principle, the team should initially agree to one of the suggested approaches. There are two basic approaches: alphabetical order and grouping by related properties.

Alphabetical order is a popular choice and is suggested as a baseline for those who have no strong preference in this matter. Alphabetical order has the benefit of always being in sync across project teams, where the importance or connectedness of properties can change depending on the developer or team making the associations.


    .selector {
      background: #000;
      border: 0;
      color: #fff
      display: block;
      height: 100px;
      margin: 10px;
      padding: 10px;
      position: relative;
      width: 50%;
    }
    

Alternatively, the approach is for related properties to be grouped together and for structurally important properties (e.g. positioning and box-model) to be declared prior to typographic, background, and color properties.


    .selector {
      position: relative;
      display: block;
      width: 50%;
      height: 100px;
      padding: 10px;
      border: 0;
      margin: 10px;
      color: #fff
      background: #000;
    }
    

Exceptions and slight deviations

Large blocks of single declarations can use a slightly different, single-line format. In this case, a space should be included after the opening brace and before the closing brace.


    .selector-1 { width: 10%; }
    .selector-2 { width: 20%; }
    .selector-3 { width: 30%; }
    

Long, comma separated property values - such as collections of gradients or shadows - can be arranged across multiple lines in an effort to improve readability and produce more useful diffs. There are various formats that could be used; one example is shown below.


    .selector {
    box-shadow:
      1px 1px 1px #000,
      2px 2px 1px 1px #ccc inset;
    background-image:
      linear-gradient(#fff, #ccc),
      linear-gradient(#f3c, #4ec);
    }
    

Miscellaneous Standards

Use lowercase hex values, e.g., #aaa.
Use single or double quotes consistently. Preference is for double quotes, e.g., content: "".
Always quote attribute values in selectors, e.g., input[type="checkout"].
Where allowed, avoid specifying units for zero-values, e.g., margin: 0.

Preprocessors: additional format considerations

Different CSS preprocessors have different features, functionality, and syntax. Your conventions should be extended to accommodate the particularities of any preprocessor in use. The following guidelines are in reference to Sass.


    .selector-1 {
      @extend .other-rule;
      @include clearfix();
      @include box-sizing(border-box);
      width: x-grid-unit(1);
      // other declarations
    }
    

Naming

We are not human code compiler/compressors, so don't try to be one. Use clear and thoughtful names for HTML classes. Pick an understandable and consistent naming pattern that makes sense both within HTML files and CSS files.


    /* Example of code with bad names */
    .s-scr {
      overflow: auto;
    }
    .cb {
      background: #000;
    }
    

    /* Example of code with better names */
    .is-scrollable {
      overflow: auto;
    }
    .column-body {
      background: #000;
    }
    

Use names that make sense even if design or usage changes.


    /* Example of code with bad names */
    .right-red {
      float: right;
      color: red;
    }
    

    /* Example of code with better names */
    .text-highlight {
      float: right;
      color: red;
    }
    

Practical example

The following example is designed to illustrate the various style conventions. It's not meant to be used as a solution to any specific problem. It's here merely to illustrate coding conventions and style.


    /* ==========================================================================
    Grid layout
    ========================================================================== */
    /*
    * Example HTML:
    *
    * <ul class="grid">
    *     <li class="cell cell-5"></li>
    *     <li class="cell cell-5"></li>
    * </ul>
    */
    .grid {
      font-size: 0;
      height: 100%;
      overflow: visible;
      /* Prevent inline-block cells wrapping */
      white-space: nowrap;
      /* Remove inter-cell whitespace */
    }
    .cell {
      border: 2px solid #333;
      box-sizing: border-box;
      /* Reset font-size */
      font-size: 16px;  height: 100%;
      overflow: hidden;
      /* Set the inter-cell spacing */
      padding: 0 10px;
      position: relative;
      vertical-align: top;
      width: 20%;
      /* Reset white-space */
      white-space: normal;
    
    }
    /* Cell states */
    .cell.is-animating {
      background-color: #fffdec;
    }
    /* Cell dimensions
    ========================================================================== */
    .cell-1 { width: 10%; }
    .cell-2 { width: 20%; }
    .cell-3 { width: 30%; }
    .cell-4 { width: 40%; }
    .cell-5 { width: 50%; }
    
    /* Cell modifiers
    ========================================================================== */
    .cell--detail,
    .cell--important {
      border-width: 4px;
    }
    

How to write good CSS (Selectors)

Writing Efficient CSS selectors is a good article to understand why writing efficient CSS selectors is important. Here's a summary:

In terms of performance, memorize Steve Souders' list (Quoted from Even Faster Websites by Steve Souders) of efficient CSS selectors - ordered from higher to lower efficiency:

  1. ID, e.g. #header
  2. Class, e.g. .promo
  3. Type, e.g. div
  4. Adjacent sibling, e.g. h2 + p
  5. Child, e.g. li > ul
  6. Descendant, e.g. ul a
  7. Universal, i.e. *
  8. Attribute, e.g. [type="text"]
  9. Pseudo-classes/-elements, e.g. a:hover

There is much to be said around how to architect the HTML and subsequently the CSS for a larger site. Here are a few good pointers to keep in mind:

  1. Find patterns in different modules and abstract them out.
    e.g. Two modules that have bulleted lists in them might inherit from a common class, and be adjusted separately with additional rules.
  2. When you create a module, let it be flexible so it can be used in a different context
    This goes hand in hand with "keep specificity low". When you write CSS for any module, don't tie it to a specific place (or parent) unless you really have to.

JavaScript

Styleguide

Naming Conventions

Always choose an understandable and consistent naming pattern, we recommend identifiers should start with a lowercase letter and use camelCase for multiple words.

For advanced coding there are alternate naming patterns you may use to give clearer hints as to the use of a variable.

Note: The following example only shows the style of identifier we recommend, it does not show how to create variables with those properties.

    //typical variable declaration (if unsure use this declaration)
    var myVar = 'foo';
    
    //private variable
    var _myPrivateVar = 'foo';
    
    //constant
    var MYCONST = 'foo';
    

Constructors should always start with an uppercase letter.

    // class constructor function
    function MyClass() {};
    
    MyClass.prototype = {
      //object with methods
    };
    
    new MyClass;
    

Block Structure

Place opening brackets on same line as preceding statement. This avoids errors in cases where automatic semi-colon insertion causes the return statement to return undefined instead of an object literal.

    function foo() {
      //function code;
    }
    
    return {
      "myMethod": myMethod
    }
    

Variable declaration

Declare all vars at the top of their scope when possible. As JavaScript has function level scoping, not block level as in some other languages, this helps clarify where those variables are accessible.

    function sample() {
      //the variable 'foo' is available from the start of function scope
      var foo;
    
      if ( condition ) {
        foo = 'bar';
      }
    
      return foo;
    }
    

Declare all vars with one var keyword when appropriate and use preceding commas. This is more performant than multiple statements.

    //avoid repeating var in variable declaration
    var foo;
    var bar;
    var lorem;
    var ipsum;
    
    //comma seperated variable declarations
    var foo,
      bar,
      lorem,
      ipsum;
    

Use whitespace for readability.

    function sample( arg, bar ) {   
      var tmp,
        foo = arg || false;
    
      if ( foo ) {
        tmp = foo;
      }
      return tmp;
    }
    

Use strict equality operators

Using the strict equality operator checks that the two operands are of the same type and value. This is a good coding style; It avoids type coercion (which has a performance cost), assures correct data-types and more clearly communicates intent.

For example, if a developer wrote if ( foo == null ) {...}, did he intend other falsey values (such as false, 0, '', or undefined) to pass this conditional?


    a === b  // strict equality 
    a !== b  // strict inequality 
    

Use object literal notation

Favor object literal notation for grouping object members to help keep code organized and allow editors to collapse blocks for readability.

    
    //avoid defining in multiple steps
    var foo = {};
      
    foo.prop = 'bar';
    
    foo.method = function() {};
    
    //defined in a single assignment
    var foo = {   
      prop: 'bar',    
      method: function() {}
    }
    
Linting your code

Mr. Douglas Crockford, the godfather of JavaScript has some ideas about how "good" JS code looks like and he has written a JSLint script to validate any code against it. Although there might be good reasons to not follow each and every rule, it's usually a very good starting point for getting your code clean, stable and increasing the compression rate for delivery. There are JSLint Bundles for most code-editors as well as this online validator tool. Alternatively one can use the JSHint tool, which is much more configurable.

Organization

During development use separate files to help break up code for distinct components, add a standard JS file header to each file explaining it's purpose and relevant dependencies.

Note: Here we include an exclamation mark after opening the comment, informing build code that this should remain in the production file.


    /*!
    * NAME OF THE FILE (e.g. filter.client.js)
    * This file contains the code for the Filter controls.
    * 
    * @project   PROJECT NAME
    * @date      YYYY-MM-DD 
    * @author    YOUR NAME, SapientNitro <YOUREMAIL@sapient.com>
    * @licensor  CLIENTNAME
    * @site      PROJECTNAME
    *
    */
    

Add comments liberally to your code. While variables and function names may seem to show intention, use your comments to add clarity and show limitations.

Code separation can make your code more robust in a production environment. The nature of the modern web is that many external scripts are added to a page yet they all work in the same context. You can limit the potential effects on your code from these third-party scripts by using the methods below.

Namespacing your code

The majority of your JavaScript code should be collected into a namespace. This namespace is the root for all calls into your code and gives you more control what functions are exposed in global scope.

A namespace in JS should be defined within a closure. Closures are a way of defining the scope of execution for a block of code. In JavaScript all functions are closures. Local variables defined in a function are not available outside of it, yet a function can access to variables outside of their lexical scope. It is this behavior that allows us to create private variables protected from other code.

Sample anonymous closure (1.0)

    (function( window, undefined ) {
      var foo = 1; //private variable
    
    })( window );
    

The closure in 1.0 is created using a self-executing function (complicated name: immediately invoked function expression). You can find this style all over the web, infact this is the first and last lines of the jQuery source code.

Here the value of foo is protected from any code outside of the closure. This example has a parameter named undefined. In JavaScript undefined can be set like any other variable. It is possible that third party code could do this. In this example it is NOT passed in when the function is executed, therefore we can always be sure that it is of type undefined.

Sample namespace (1.1)

    (function (window, $, undefined) {
      //example namespace, in this case an object literal
      var namespaceObject = {
        //object properties
      };
      
      //exposes the object to global scope.
      window.projectName = namespaceObject;
      
    }(window, jQuery)); 
    

In 1.1 we define our namespace as an object before exposing it to the global scope by adding it as a property of the window object. We could have set this as global by removing the var keyword, but this could easily be misunderstood as a mistake. In this case we have a basic object as our namespace, although it could be a more complex pattern.

This example also passes the jQuery object as a parameter, this ensures that the $ variable refers to the jQuery object inside the closure.

Sample module export (1.2)

    var projectName = (function (window, undefined) {
      //example namespace, but this could also be a module
      var namespaceObject = {
        //object properties
      };
      
      //return the object from the function expression.
      return namespaceObject;
      
    }(window, jQuery)); 
    

In 1.2 we again use a closure to protect our namespace, but we are returning the object itself from the function call allowing us to set to the projectName variable. This form is most useful when your code is already inside of a closure and have no need to expose the namespace to global scope.

Structuring your code

Putting thought into the structure and organization of your JavaScript enables you to write code that is easier to maintain, more reusable, easier to read, and less likely to cause collisions with other scripts. There are almost as many ways to effectively organize code as there are developers, but several tried and true patterns have emerged over the years

Sample object literal (2.1)

    //namespace object
    var namespaceObject = {
      //object properties set on creation
      property1 : 1
    };
    
    //adding additional properties to the object
    namespaceObject.property2 = 2;
    namespaceObject.initFunction = function () {
      //function code;
    };
    

This is a basic starting point for code organization, our properties and functions are grouped into a root object. A limitation of this approach is that the object properties are all public, and even when calling a property from inside the object you have to include it's full path or use the this keyword (discussed elsewhere).

Sample object literal created within a closure (2.2)

    //namespace object
    var namespaceObject = function () {
      //creating the new namespace object
      var _namespace = {
        //object properties can still be set on creation
        property1 : 1
      };
    
      //here property2 is a private variable, only accessible inside the closure.
      var property2 = 2;
    
      //adding additional properties to the object
      _namespace.initFunction = function () {
        //function code;
      };
    
      return _namespace;
    }();
    

This pattern will give you control over the visibility of your variables, just as we had in the namespace closure.

Sample class definition (2.3)

( cribbed from http://stackoverflow.com/questions/1635116/javascript-class-method-vs-class-prototype-method )


    // class constructor function
    function MyClass () {
      var property1 = 1; // private variable, only available within the constructor fn
    
      this.privilegedMethod = function () { // public method, can access property1
        //function code;
      };
    }
    
    MyClass.classMethod = function(){
      //function code;
    };
    
    MyClass.prototype.publicMethod = function () {
      // the 'this' keyword refers to the object instance
      // you can access only 'privileged' and 'public' members
    };
    
    var myObj = new MyClass(); // new object instance
    
    myObj.publicMethod();
    myObj.privilegedMethod();
    MyClass.classMethod();
    

Performance

When writing high-performance JavaScript, it can be hard not to micro-optimize. Saving a couple bytes here and there is usually not worth the cost incurred to the readability of the code, or the time spent agonizing over small details. That being said, there are many practices that, when ingrained into one's coding style, can help to ensure fast execution with little extra effort or impact to the maintainability of the code.

It should be noted that the impact of any single optimization is usually minor, but can be more easily seen in loops, or when otherwise dealing with instances where milliseconds matter (as with animation, where the time taken to draw each frame should ideally be less than 16ms).

This section sets a spotlight on different aspects of JavaScript, each with some basic context knowledge. So you can choose the most appropriate approach for your solutions and gaining some starting points for performance improvements.

Coding

Obviously the very core of using JavaScript is coding. As mentioned above, saving some bytes at the cost of readability is not reasonable. Modern JavaScript engines have a lot build-in optimizations for sub-optimal code. However, following a certain coding style will assure a good performance by default.

Read/Write values

The kind of storing and accessing values differs in terms of speed. This can have different impacts depending on having many read/write operations (real-time calculations) versus storing large amounts of data (state caching).
As a rule of thumb take this order:


    // literals
    [ ], '', { }    // ... are faster than ...
    // variables
    var x            //... are faster than ...
    // arrays | objects
    {property : "value"}
    

As a general note, try to use literals as often as possible. Especially when it comes to declaration of arrays/objects.


    // Don't...
    var array = new Array,
      object = new Object;
    
    // ... better to use
    var array = [ ],
      object = { };
    
Loops

In general the common "for" and "while" loops should be the preferred options. Apart from the loop-type it's way more important to cut down the amount of operations that happen in each iteration.
A usual scenario is looping over an array, which can be optimized like this (maybe moving the var statement to the top of your function for readability and happy lint'ing):


    // calculating the constant array-length in every iteration 
    // - makes our JS engine a dull boy :(
    for(var i = 0; i < arr.length; i++){ 
       do_sth();
    }
      
    // calculating the constant array-length once
    // - sounds like a pro way :)
    for(var i = 0, len = arr.length; i < len; i++){ 
       do_sth();
    }
      
    // if the process order doesn't matter
    // - you can go the rockstar way :P ...
    for(var i = arr.length ; i-- ; ){ 
       do_sth();
    }
    // ... this has only one operation per iteration
    // and the loop stops at 0 (false) automatically
    
Don't repeat yourself (DRY) when writing code

Try to chunk different operations & processes into separate functions, but don't overdo it. Always think about maintainability and readability.

Special advice: If you happen to repeat a lot of testing for the very same condition, maybe conditional advance loading is something for you.


    // doing the 'isModernBrowser' test with every function call
    // - makes our JS engine a dull boy :(
    function webGl() {
      if (isModernBrowser) {
        startSomeAssKicking3DGame();
      } else {
        openMinesweeper(); 
      }
    }
    function localStorage() {
      if (isModernBrowser) {
        saveSomeGameStats(); 
      } else {
        printCopy();
      }
    }
    
    
    // doing the 'isModernBrowser' test once on initial load
    // - sounds pro, bro' (sis') :)
    var webGl = (isModernBrowser)
                ? startSomeAssKicking3DGame
                : openMinesweeper;
    
    var localStorage = (isModernBrowser)
                       ? saveSomeGameStats
                       : printCopy;
    

DOM

A lot of nowadays script running times are rather spent on DOM operations / manipulations than on anything else. Due to the great achievements of JavaScript libraries and frameworks (jQuery, backbone, etc.) those impacts have been reduced. However, even while using those tools, you can improve the overall performance of your code by taking care for the DOM.

Reflow & Repaint

A lot of the following best-practices around the DOM topic refer to the mechanisms of reflow and repaint. It's essential to understand those effects when building modern (application-like) web-interfaces. A very(!) abbreviate description is:

A reflow is almost always bound to a repaint and quite expensive, thus it can hurt the user experience. Reducing reflows/repaints to a minimum is a great source for sensible performance improvements.
If you are not aware of reflow / repaint mechanisms you should find further details here: Stoyan Stefanov - Rendering: repaint, reflow/relayout, restyle

Manage reflow/repaint

Upfront: Browser(-vendors) are clever. Modern browsers collect reflow/repaint commands into a batch for optimized execution.
Usually this is a good thing, as it's improving the user-experience due to less (visible) changes on the user-interface. Leveraging this batch method can improve your overall performance significantly. For realizing this, it's crucial not to trigger the rendering and not to flush the batch unintended.
Find further details, about what triggers reflows here: How (not) to trigger a layout in Webkit


    // causes two reflows due to flushing the batch
    // - makes our JS engine a dull boy :(
    var fullWidth = document.body.clientWidth;
    fullSizeDiv.style.width = fullWidth + 'px'; 
    
    var fullHeight = document.body.clientHeight; 
    fullSizeDiv.style.height = fullHeight + 'px';
    
    // leveraging the batch mechanism, causes a single reflow
    // - is the pro way :)
    var fullWidth = document.body.clientWidth;
    var fullHeight = document.body.clientHeight; 
    
    fullSizeDiv.style.width = fullWidth + 'px'; 
    fullSizeDiv.style.height = fullHeight + 'px';
    
DOM injection & manipulation

The short announcement: Bundle your DOM operations!
For injections, you can either create your HTML block with string concatenation or with a so called documentFragment. Either way, you should create the entire block before appending (prepending, replacing) it into the DOM. The same is true for canvas drawings, which should happen in one go, too.
When you need to develop for older browsers (especially Internet Explorer < IE9), there is a performance benefit in using the string concatenation approach. Nevertheless, this can get messy very quickly, so generally you should prefer the document-fragment, as this gets a lot of optimizations in modern browsers (now and in future). You can learn more about the documentFragment here: John Resig - DOM DocumentFragment
When using a library like jQuery anyway, you can use the build-in mechanism, which abstract the native approaches including performance improvements.


    // the string concatenation approach
    // is helping IE performing better :-/
    var sHTML = ["<h1>","Quotes by Yoda","<h1>"].join();
    document.getElementsByTagName('body').item(0).appendChild(sHTML);
    
    // the elegant document-fragment approach
    // - is preferable :)
    var fragment = document.createDocumentFragment();
    var heading = fragment.appendChild(document.createElement('h1')); 
    
    heading.appendChild(document.createTextNode('Quotes by Yoda'));
    document.getElementsByTagName('body').item(0).appendChild(fragment);
    
    // the jQuery approach
    // - if you have it, use it ;)
    var eHTML = $("<h1></h1>").text("Quotes by Yoda");
    
    $("body").append(eHTML);
    
Traversing

In times of jQuery and similar libraries and frameworks, the traversing of the DOM is easy. Even the performance improves with every version due to better caching mechanisms.
Nevertheless, it's crucial to write efficient selectors and cache (static) results, in order to reduce the amount of operations happening on the DOM level. Based on the position of the element within the DOM tree, the traversing can get really slow. Thus you want to make sure, that it happens as few times as necessary and as efficient as possible.

Write efficient query selectors

For JavaScript query selectors you can apply the same rules as for CSS Selectors. The query for an id serves better performance than for classes or tag-names.


    // selector based on an id
    document.getElementById(id)
    // selector based on a tag name
    document.getElementsByTagName(tagName)  // returns live node-list
    // selector based on a css-selector (since IE8)
    document.querySelectorAll(css-selector) // returns node-list
    // selector based on a css-selector (since IE8)
    document.querySelector(css-selector)    // returns first element
    

If you think about the fact, that those native JS selectors are underlying libraries like jQuery, it's obvious why for example a query for a class-name is one of the slowest in performance.
Overall jQuery selectors are fast, thus for readability and simplicity it's absolutely acceptable to also use less performant selectors. The following best-practices are only a hint at where to gain some performance wins:


    // try selecting with id or ...
    $("#id");
    // ... descending from an id ...
    $("#id p");
    // ... better: improve specificity
    $("#id").find("p");
    
    // try to avoid complexity ...
    $("#page div.article p.intro:first-child");
    // ... class or ...
    $(".class");
    // ... attribute selectors
    $("[data-attribute]");
    
Cache query selector results

Way more important than finding the most efficient selector is caching your results for repeating tasks. Instead of traversing the same DOM tree branch over and over again, you should cache the results on initialization (if static) or after a related DOM update (f. e. after AJAX insert). Using jQuery here as an example, but the same is true for native JS or any other library/framework.


    // traversing for "#myList" 2x on every click
    // - makes our JS engine a dull boy :(
    $("#myButton").on('click', function (e) {
      if ($("#myList").hasClass("active")) {
        $("#myList").removeClass("active");
      } else {
        $("#myList").addClass("active");
      }
    });
    
    // caching the "#myList" Object once
    // - is the way to do it :)
    var myList = $("#myList");
    $("#myButton").on('click', function (e) {
      if (myList.hasClass("active")) {
        myList.removeClass("active");
      } else {
        myList.addClass("active");
      }
    });
    

Another library specific (f. e. jQuery) performance optimization could be chaining:


    // instead of multiple operations on one HTML object ...
    var myList = $("#myList");
    myList.hide();
    myList.css("background-color","#bada55");
    myList.show();
    
    // ... chain it and leverage built-in optimizations
    $("#myList").hide()
          .css("background-color","#bada55")
          .show();
    
Beware of live collections (node-lists)

A common trap (especially when using document.getElementsByTagName) is handling a live node-list. As the name indicates this collection holds a live-reference pointing to the DOM node(s) instead of holding a cached (non synched) copy. Rarely this might be an intended scenario, but in most cases it causes serious problems due to unexpected changes to the collections reference. Due to its live characteristics a collection is updated and "re-traversed" with every read/write access or manipulation, respectively. This can become a big performance impact. Thus - as a general rule of thumb - avoid a live-collection, unless you know exactly how to use it.


    // jQuery's default behavior is returning a cached copy
    var coll = jQuery(“div”); 
    
    // assuming a collection of 5 elements ...
    for (var i=0; i < coll.length; i++) { 
      // ... we do 5 iterations, ending up with 10 div elements
      document.body.appendChild(document.createElement(“div”));
    }
    
    // the native JavaScript behavior is returning a live-collection
    var coll = document.getElementsByTagName(“div”);
    
    // assuming a collection of 5 elements ...
    for (var i=0; i < coll.length; i++){ 
      // we create an infinite loop, ending up with a stack-overflow error
      document.body.appendChild(document.createElement(“div”));
    }
    

Event delegation

Delegating your events (precisely: their handling) is not only improving the response time of your interface but increasing the readability, maintainability and re-usability. Creating autonomic modules which handle related events on their own, is a big step towards object oriented development.

In JavaScript events bubble up. That means, when an event is triggered on an DOM element, it is also subsequently triggered on all parent-elements up to the root (window), as described in the following abstract example of a website navigation:


    window                  // click
     document             // click
        #nav            // click
           a           |
           a  // click |
           a
    

The above pseudo code should visualize, why it might be a bad idea to bind all event-handlers to the window or document object (as f. e. in jQuery's live() function). If all events are only handled on the root level, they always need to bubble the whole way up before a response to the user(-interface) can be determined. Thus binding the event-handler for example to the "#nav" reduces the distance to one level.


    // binding handlers to the window 
    // forces the event to bubble up every time :(
    window.addEventListener('click', handleClick, true);
    window.attachEvent('click', handleClick);  // IE6 - 8
    
    // binding handlers to the parent element 
    // fires the response faster, which makes the user happy :)
    var nav = document.getElementById('nav');
    nav.addEventListener('click', handleClick, true);
    nav.attachEvent('click', handleClick);  // IE6 - 8
    

Apart from the responsiveness, re-usability is another benefit. Having all events handled on a related parent (or any other sensible) node, enables you to reuse your code for the same markup in any other context.

bind, live or delegate? - Put it 'on'!

Due to the big distribution of jQuery and the frequent usage in Sapient projects, it's worth to make a note about event delegation in jQuery. Before version 1.7 there were three ways of event-handler binding. The methods bind(), live() and delegate() differ in the way they are bound, handled and preserved when the related elements are destroyed.

If you need to work in an environment with a jQuery version < 1.7, you should use delegate() in most case, because it does precisely what it says and what is described above. The following comparison of event binding methods shall demonstrate their benefits and pitfalls (assuming a navigation with 3 anchor elements).


    // creates 3 event-handlers, binds directly to anchors, 
    // anchor elements must(!) exist on binding,  
    // can't handle new anchor elements (f. e. added later with JS) 
    $("#nav").find("a").bind("click", handleClick); 
    
    // creates 1 event-handler, binds to window object, 
    // anchor elements don't need to exist on binding,  
    // can handle new anchor elements (f. e. added later with JS) 
    $("#nav").find("a").live("click", handleClick);
    
    // creates 1 event-handler, binds to #nav element, 
    // anchor elements don't need to exist on binding,  
    // can handle new anchor elements (f. e. added later with JS) 
    $("#nav").delegate("a", "click", handleClick);
    
    // unifies all former methods to one syntax, depends on how you use it
    $("#nav").find("a").on("click",handleClick);   // bind()
    $(document).on("click","#nav a", handleClick); // live()
    $("#nav").on("click","a", handleClick);        // delegate()
    

If you can work with jQuery 1.7 or higher you should most definitely use on(), because this function abstract all of the former three methods and detects based on the used syntax, which binding is appropriate for the specific situation.
For further details see this comparison of bind(), live(), delegate() and on().

Animation

With modern web-technologies there is also a higher demand for animations within a web-interface. Those animations only appear smoothly when a frame is drawn in less than 16ms or to put it in another way, an animation should happen at 60 frames per second. Due to the "one thread" design of browser engines and the pretty slow manipulation (reflow/repaint) of the DOM, this rate can hardly be reached with pure JavaScript functionality.
Modern browsers have introduced the requestAnimationFrame API, which draws the interface at a rate of 60 frames/s and enables you to execute code (animations) for each of those frames. You can read Paul Irish's article 'requestAnimationFrame' for smart animating to get more details and to learn how to overcome differences in vendor implementations (naming).

Scope chain & execution context

Fundamental principles of modern JavaScript development are closures, the scope chain and execution context, respectively. As the explanation of those principles is out of scope (Ha-Ha: what a wordplay) for this document, there is only a abbreviate description of the necessary context (Ha-Ha again) for the following topics. Recommendations for further reading are Jim Ley's FAQ on closures (including scope-chain and execution context) as well as the JavaScript closure tutorial.

The core idea in JavaScript is: "everything is an object". Thus every function(-object) receives a scope property, that holds references to the global object. When the function is executed, an activation-object (execution context) is created and moved to the first place in the scope-chain. For better understanding a simple example:


    function add(num1, num2) {
      var sum = num1 + num2;
      return sum;
    };
    
Scope chain
Scope chain for add-function

    var total = add(5, 10);
    
Scope chain
Scope chain for add-function in execution context

Use local variables

Giving the fact about how the scope chain works, it becomes obvious why local variables should be used. Referencing to a variable (identifier) that lies outside the scope of a function (f. e. within the global object) forces the JS engine to run down the scope chain in order to access the related value. This process can slow down your performance and gets worse the deeper your function is nested within other functions (scopes).

That said, in modern JavaScript development patterns it's absolutely usual to nest functions into each other for module (object) creation. It's even appreciated, as there are benefits like public/private patterns, namespace encapsulation and similar benefits of object-oriented development. To sum up, take this two rules of thumb:

  • Nest functions where you can get benefits like encapsulation, value integrity, modularisation, etc.
  • When using a variable (value) outside of your current scope more than once, store it in a local variable!
Scope chain
Identifier resolution process

    // access the document identifier 2x 
    // in the global object :(
    function add(num1, num2) {
      var sum = num1 + num2;
      document.getElementsByTagName('body').item(0).appendChild(sum);
      document.body.style.backgroundColor = "#0F0";
    };
    
    // access the document identifier 1x 
    // in the global object :)
    function add(num1, num2) {
      var sum = num1 + num2;
      var doc = document;
      doc.getElementsByTagName('body').item(0).appendChild(sum);
      doc.body.style.backgroundColor = "#0F0";
    };
    

Avoid `with`

A 'with' statement in JavaScript inserts an object at the front scope chain, so any property/variable references will first try to be resolved against this object. That means you add another level to the resolving process, which can impact your overall performance. Moreover conflicting identifier names can cause serious problems. Compare the following figure for with-statement


    function add(num1,num2){
      with(document){
        var sum = num1 + num2,
        n = createTextNode(sum),
        p = getElementById(“t1”);
        p.appendChild(n);
        return sum;
      }
    }
    var total = add(5, 10);
    
Scope chain
Identifier resolution process

Minimize use of try/catch

Upfront: Sometimes it's recommended to use a try/catch block for stability and adequate error handling. Thus, if you're sure it's the appropriate solution, by all means - use it.
However, from a performance perspective the try/catch block acts similar to the 'with' statement and creates an Activation object at the top of your scope chain, including the above mentioned identifier resolution issues. Thus you should try to minimize its usage as much as you can.

Avoid 'eval'

The well known JavaScript rule "eval is evil" is there for a reason. You should avoid, unless you're 100% (better make it 1000%) sure, you are facing one of the rare exceptions in which it's appropriate.
The eval() function in javascript is a way to run arbitrary code at run-time. That means you're running any (!) kind of code within the current scope and execution context. This violates the integrity of your variable values (identifier conflicts) and is a serious thread to the security of your code or even your entire website.

UI-thread

Browser engines are implemented in a "one thread" design. That means it can only do one task at a time (no multitasking ;). The handling of user-input is your highest priority for a fast responding interface and a good user-experience. Thus you need to make sure, that other JS operations & calculations work in quickly "digestible" chunks.
According to usability expert Jakob Nielsen, every interface needs to respond within 100ms, otherwise the user feels disconnected (progress-bars can stretch this time-slot ;). Because of this user-inputs have the highest priority in the UI-Thread. Either they are processed immediately or they are set next in row, if another JavaScript function is currently executed.
However, when you need to process a huge amount of data for example, it's likely to take more than 100ms. In this case try to cut down the process in several tasks and if that's not possible use setTimeout/setInterval for example in order to process one block of data in a defined interval. In this way the UI-Thread is released frequently for handling (& responding to) any user-input.

If you can work for a target-group, which supports modern HTML5 technologies you can have a look into web-workers. That's an API, which enables you to create parallel threads for processing large amount of data without bothering the UI-thread for this. This HTML5 rocks' article is a good starting point to dive deeper into this topic.

Load scripts asynchronously

The less there is to initialize and to process in the beginning, the faster your website loads. This is not directly affecting your JavaScript performance, but at the end of the day the user only cares about the performance of your website.
Based on your requirements and how sophisticated your JS environment (framework) is set up, there are different ways for asynchronously (or deferred / lazy) load your scripts. Moreover asynchronous script loading is especially beneficial when it comes to 3rd party code (ads, social media plugins).
Chris Coyier shows different approaches to this problem in his Thinking async article.

Please note, that this is only relevant when it comes to a certain level of Javascript in size and complexity. For the majority of websites, it's usually recommend to save additional requests and combine & minify your JavaScript into one file as well as compress (gzip) it for delivery. This is also the easiest way to leverage caching mechanisms of browsers.

Don't use JavaScript

This might sound ridiculous, but saved JavaScript code obviously boosts your performance. ;P
To be more serious about it, classical css-selectors (:hover, :focus) and new CSS3 features (:target, transition, transform, keyframe animation) enable you to do stunning effects and create immediate interface-responses without any use of JavaScript. The more your website (user-interface) can act self-sustainingly the more your JavaScript can focus on the background work.
Moreover CSS3 animations are optimized by browser-vendors for their reflow/repaint process, so you don't need to bother with those impacts as you would do with JavaScript.

JavaScript Libraries and Tools

This section describes our most often used used tools.

General utility/DOM abstraction

jQuery: Mostly used tool for DOM abstraction and aligning Browser capabilities. jQuery

Browser Normalization and Feature Detection

Modernizr contains a range of feature detection tests and a HTML5 shiv for IE support. It should be customised to include only the features you require. Modernizr

Build Scripts and Templates

Templates and Build Scripts we use for a starting point and additional build scripts, that helps getting better results in deploy processes.

HTML5 Boilerplate
Grunt

Asynchronous Loading

Asynchronous Module Definition (AMD) specifies a mechanism for defining ressources that can be asynchronously loaded. Synchronous loading of modules incurs performance, usability, debugging, and cross-domain access problems.

AMD
Requirejs
curl.js

Scalable Architecture

Front-End Templating

Performance Testing and Profiling

Graphics

Matrix and Vector Math

Accessibility

Accessibility (often abbreviated as a11y) is hugely important in the modern web. It's a legal requirement in many geographies, an excellent indicator of a quality product and shows you care! Projects should set out to develop to meet WCAG 2.0 Level AA. WCAG 2.0 at a Glance

The start point for an accessible website is always solid, structured, semantic markup. Always use headings to convey structure and where possible start to use HTML5 tags such as main, section and aside to add meaning to your content areas. Be cautious. The article tag is easy to misunderstand, the article tag represents a complete or self-contained item. This could be a forum post, a blog entry, an interactive widget, or a user-submitted comment. W3 reference on the article element.

Do not expect users of assistive technologies to have JavaScript disabled. Whilst having a non-JS fallback is often good proactive it is not longer acceptable to make this your "accessible version". By using using recognized markup, allowing keyboard focus and interaction, and being mindful of user interaction your JS work can be accessible.

The WAI-ARIA Specification – The Next Level.

The elements introduced in HTML5 have growing but limited accessibility support in browsers. Fortunately the WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications) specification has excellent support. Modern web applications are complicated; There are unusual mixes of tags to create UI controls and there are regions on a page which update on screen without a page refresh. ARIA introduces a range of roles (added to tags as attributes) that act as hooks for assistive technologies.

WAI-ARIA Primer
WAI-ARIA Best Practices

Accessible Design

Many of the accessibility guidelines have a direct impact upon wireframes and designs. Accessibility is the responsibility of the whole team so please highlight any issues you spot in the documents supplied to you.

A common issue is color contrast; AA requires a contrast ratio of 4.5:1 for normal text and 3:1 for large text. Level AAA requires a contrast ratio of 7:1 for normal text and 4.5:1 for large text. It may not be possible to correct all issues but it is important for us to be open about these challenges both internally and with our clients.

Responsive Design

Responsive / Adaptive Web Design is an approach that aspires to deliver an optimal experience across a wide range of devices. They completely change creative workflows, requiring concept, design and interactive development domains to work closely together. The two terms are often used interchangably but have different priorities.

Adaptive Web Design (AWD)
Layouts are changed at specific breakpoints. Grids may be fixed flexible or fluid.
Responsive Web Design (RWD)
Layouts respond to the available space using flexible or fluid grids. Breakpoints may be used to adapt the layout.

AWD and RWD can be enhanced with server side code, an approach typically referred to as RESS. RESS often attempt to match the user agent string with a record in a device database, if successful we can use the devices specifications to tailer our response.

In-depth reading

In responsive design prototyping is more important than ever. For this and for kick-starting any projects using a grid-system, such as the Foundation library or Bootstrap, can be a great help.

Coding

Responsive design relies on fluid grids. Thus, you should use the following rules of thumb for front-end coding:

Viewport Meta Tag

Mobiles, tablets, desktop screens - all differ especially in size and resolution. Due to displays with higher pixel-density mobile-vendors started to define a "best-viewed-in" resolution, which is usually very reliable. Two must-reads about this topic are PPK's "A tale of two viewports" (+ "Part II") and "Combining meta viewport and media queries".

Based on this information, the best experiences have been made with a very simple viewport-tag definition:


    <meta name="viewport" content="width=device-width; initial-scale=1.0"/l>
    

maximum-scale=1.0 would fix some orientation-change bugs on iOS devices and "assures" some app-like stability, but we recommend not to use it. It's simply an accessibility concern. People (especially with visual impairments) must be allowed to zoom to their favorite level.
Moreover there are little helpers to fix orientation-change bugs like Scott Jehl's iOS-Orientationchange-Fix

This simple viewport tag base works on a broad range of mobiles and tablets. Only the Nexus 4G and HTC Sensation (so far) seemed to not provide an optimized viewports which triggers higher resolution layouts (e.g. tablet-layout media queries) on those mobiles.

Media Queries

CSS3 media-queries enable you to adjust your (maybe responsively-designed) website modules for specific resolution (device) classes. Please don't blindly follow Andy Clarke's - Hardboiled CSS3 Media Queries, which seem to be widely spread across the web. Although it contains a lot of right stuff, it's probably too detailed for your requirements. Moreover it mostly sets min-width and max-width limits, which partly excludes devices. For example a tablet-focused media query with a max-width of 1024px supports an iPad in landscape mode but will be ignored by a LG-V900 (1280px) tablet.

Joshua Johnson has an interesting alternative approach in his article Responsive Design: Why You're Doing It Wrong. It challenges the idea of defining fixed pixel-ranges for a responsive design (actually quite unresponsive, right?!).

When you start from a mobile-first approach, you should be able to define mostly min-width breakpoints only for enhancing your layout on bigger viewports.

For some browsers it's even worth it to define breakpoints in em instead of px. This enables your layout to fall back to a smaller layout when the user has increased the default font size. Can I get an accessibility-high-5?!

Again, that's not working in every browser, but not failing as well. The ones not reacting correctly to increased font-size simply read it like the related pixel value as before. Read more about it in Lyza Gardner's The EMs have it: Proportional Media Queries FTW!.


    @media screen and ( min-width: 40.625em )  {
      /**
       * put here your > 768px styles
       * (based on 16px default font-size)
       */
    }
    

Credits

This document is a joint effort by