Bo Allen's Web Coding Standards

This is a very basic set of web coding standards aimed to maintain code consistency. Last updated: December 29, 2010

General Practices

Indentation and Line Breaks

All indentation is done with 4 spaces, not tabs.
Why spaces?

  • Helps to avoid problems with diffs, patches, SVN history and annotations.
  • When people using different tab settings the code is impossible to read or print, which is why spaces are preferable to tabs.
  • Makes your code consistent if you happen to edit it in a web interface (textarea).
  • Zend framework uses 4 spaces.

Vim rules for 4 spaces:
set expandtab
set shiftwidth=4
set softtabstop=4
set tabstop=4

Line breaks must be in UNIX format (LF: Line Feed, U+000A, chr(10), \n).

Maximum Line Length

Lines of code should not exceed 120 characters in all reasonable circumstances.

Naming Conventions

Everything falls into one of five of the following naming conventions:

Private and protected variables begin with an underscore.

Camel-cased acronyms remain camel-cased (i.e., getHtml, getDbTable, etc.).

Indent Style

K & R Style: Variant 1TBS
http://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS

Correct
function favorite_indent_style($style) {
    if ($style != '1TBS') {
        return false;
    } else {
        return true;
    }
}

Code Documentation

Source code should always be generously commented and documented. Please use the appropriate inline documentation system (i.e., phpDoc).

Cross Browser Testing

The latest versions of the following browsers should be tested for compatibility.

IE6 died on march 1, 2010. Let's not support dead browsers.

Third-Party Conventions and Standards

When using a third-party script, library, or framework, the conventions and standards of that script, library, or framework should be used when appropriate.

For example, if I were building an application with CodeIgniter I would stick with these standards mostly since the CodeIgniter standards are so contrary, and my application can be encapsulated in the "application" directory. Although, when writing libraries and such that need to be auto-loaded, I have to stick with the CodeIgniter standards for it to work properly. If I were to write a community library for CodeIgniter, I would stick to the Code Igniter standards 100%.

HTML

Doctype

XHTML 1.0 Transitional will be used (until HTML5 is solidly supported (2012? 2022?)).

Valid XHTML 1.0 Transitional Template
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link type="text/css" href="css/reset.css" rel="stylesheet" />
<title>Valid XHTML 1.0 Transitional Template</title>
</head>
<body>
</body>
</html>

Layout

The div element is to be used for layout elements. HTML tables are intended for tabular data only.

All div elements with an id attribute must be marked at the closing div. See the example below.

Correct
<div id="header">
    <h1>Title</h1>
</div> <!-- end #header -->

Self-closing Elements

A space is required before the forward slash of a self-closing element.

Correct
<br />
Incorrect
<br/>

Tags and Attributes

All tags and attributes must be written in lowercase. Additionally, it is preferred that any attribute values also be lowercase, when the purpose of the text therein is only to be interpreted by machines. For instances in which the data needs to be human readable, proper title capitalization should be followed, such as:

For machines
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
For humans
<a href="http://example.com/" title="Description Goes Here">Example.com</a>

Quotes

In keeping with the strictness of XHTML code conventions, according to the W3C, all attributes must have a value, and must use double-quotes. The following are examples of proper and improper usage of quotes and attribute/value pairs.

Correct
<input type="text" name="email" disabled="disabled" />
Incorrect
<input type=text name=email disabled>

CSS

Inline Styles

Inline style attributes should be avoided (style="..."). Please use external stylesheets or style tag declarations in the head section. Do not put style tag declarations outside of the head section.

An exception to this rule is style="display: none;" for revealing hidden elements via JavaScript.

CSS Validation

All cascading stylesheets should be verified against the W3C validator, to ensure correct syntax and to check for possible accessibility issues with text and background colors. This in and of itself is not directly indicative of good code, but it helps to weed out problems that are able to be tested via automation. It is no substitute for manual code review.

Validation errors related to -moz*, -khtml*, -webkit*, and opacity should be considered "warnings" rather than errors. Just be sure to cross-browser test your styles.

CSS Reset

It is recommended to implement a CSS reset in order to minimalize cross-browser style differences.

CSS Formatting

To ease potential headaches for maintenance, all CSS must be written in a consistent manner. For one, all CSS selectors must be listed on their own line. As a general rule of thumb, if there is a comma in CSS, it should immediately be followed by a line break. This way, we know that all text on a single line is part of the same selector. Likewise, all property/value pairs must be on their own line with standard indentation (4 spaces), and end with a semicolon. All property values must begin with a space (after the colon). The closing brace must be on the same level of indentation as the selector that began it - flush left.

Correct
#selector-1 span,
#selector-2 span,
#selector-3 span {
    background: #fff;
    color: #000;
}
Incorrect
#selector-1 span, #selector-2 span, #selector-3 span {
    background:#fff; color: #000
}
Also incorrect
#selector { background: #fff; color: #000; }

Hex Colors

Hex values should be lowercase. No upper-case or RGB, please! Additionally, all colors should be written as tersely as possible. This means that colors such as full blue, which can be written lengthily as #0000FF, should be simply written as #00f. Obviously, for colors that require more precision, all six characters should be used. For example, a light shade of grayish beige: #f9f9f0.

Background

Correct - shorthand
#selector {
    background: #fff url(../images/file.png) repeat-x fixed left bottom;
}
Incorrect - longhand unnecessary
#selector {
    background-color: #fff;
    background-image: url(../images/file.png);
    background-repeat: repeat-x;
    background-attachment: fixed;
    background-position: left bottom;
}

Internet Explorer Bugs

Inevitably, when all other browsers appear to be working correctly, any and all versions of Internet Explorer will introduce a few nonsensical bugs, delaying time to deployment. While it is encouraged to troubleshoot and build code that will work in all browsers without special modifications, sometimes it is necessary to use conditional if IE comments to serve up specific fixes, which are ignored by other browsers.

Fixing IE
<!--[if IE 7]>
<link type="text/css" rel="stylesheet" href="/assets/styleshseets/ie7.css" />
<![endif]-->

<!--[if IE 8]>
<link type="text/css" rel="stylesheet" href="/assets/styleshseets/ie8.css" />
<![endif]-->

Javascript

Variables

All JavaScript variables shall be written in lowerCamelCase, because every variable in Javascript is a property of an object.

Quotes

The preferred method of delineating strings is to use single quotes for everything. Since JavaScript exists to manipulate markup, and because HTML is generally written with double quotes in W3C specifications, using single quoted strings will better facilitate handling HTML fragments, and keep code more readable.

Correct
var my_html = '<img class="photo" src="/path/file.jpg" alt="Text" />';

Incorrect
var my_html = "<img class=\"photo\" src=\"/path/file.jpg\" alt=\"Text\" />";

CDATA

CDATA tags should be used around inline Javascript blocks in order to prevent it from being parsed by the XHTML validator.

CDATA Tags
<script type="text/javascript">
//<![CDATA[
$(function() {
    $('a.confirm').bind('click', function() {
        return confirm('Are you sure?');
    });
});
//]]>
</script>

Event Listeners

Rather than using attributes such as onload, onfocus, onsubmit, or onclick directly in markup, it is recommended to attach event listeners to these elements via unobtrusive techniques. The reasoning for this is the same philosophy that is behind not using inline declarations. So doing inextricably ties the behavior of a web page to its data, and makes maintenance more difficult.

Event Listener (via jQuery.bind())
<button class="toggle-list">Toggle List</button>

<ul id="list">
    <li>Item A</li>
    <li>Item B</li>
    <li>Item C</li>
</ul>

<script type="text/javascript">
//<![CDATA[
// We're setting up the event handler here instead of
// using the "onclick" parameter in the <button> tag.
$(function() {
    $('button.toggle-list').bind('click', function() {
        $('ul#list').toggle('fast');
    });
});
//]]>
</script>

Event Delegation

When assigning unobtrusive event listeners, it is typically acceptable to assign the event listener directly to the element(s) which will trigger some resulting action. However, occasionally there may be multiple elements which match the criteria for which you are checking, and attaching event listeners to each one might negatively impact performance. In such cases you should use event delegation instead.

Event Delegation (via jQuery.delegate())
<table id="data">
    <thead>
        <tr>
            <td>ID</td>
            <td>Name</td>
            <td>Value</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>Biofuel Gourmet Caffeinated Popcorn</td>
            <td>7.99</td>
        </tr>
        <tr>
            <td>2</td>
            <td>Javapops</td>
            <td>9.99</td>
        </tr>
        <tr>
            <td>3</td>
            <td>Caffeinated Perky Jerky</td>
            <td>5.99</td>
        </tr>
    </tbody>
</table>

<script type="text/javascript">
//<![CDATA[
// We're setting up the event handler on the whole table, instead of each table row.
// If this table were 1000 rows, we'd have 1000 event listeners without delegation.
$(function() {
    $('table#data').delegate('tr', 'hover', function() {
        $(this).toggleClass('tr-hover');
    });
});
//]]>
</script>

Closures & Scope

To maintain proper scope for variables, it is highly recommended that self-executing anonymous function be used as a closure. For the most part, variables defined correctly using the var syntax, within the scope of a function will not add to global scope pollution. However, from time to time, you may need to access variables via two or more functions. In such cases, multiple functions can be grouped together inside a closure.

Closure
(function() {
    var first_variable = 'value 1';
    var second_variable = 'value 2';

    function first_func() {
        // Do something.
    }

    function second_func() {
        // Do something.

    }
})();

Inline Documentation

Doxygen should be used for inline Javascript documentation.

PHP

General

Parenthesis

require_once './config.php';

if ($test) {
    // ...
}

if (!$test) {
    // ...
}

while ($test == $other) {
    // ...
}

array_push($one, $two);

return $test;

Classes, Methods, and Properties

/**
 * A simple car class example.
 *
 * <code>
 * require_once 'Car.php';
 * $lambo = new Car('Lamborghini', 'Countach', 'ZA9CA05A8JLA12353', array('xm_radio' => true, 'nitrous' => true);
 * echo $lambo->getOption('nitrous');
 * </code>
 *
 * @author Bo Allen http://boallen.com
 */
class Car {
    
    /**
     * The make (i.e., Ford, Honda, etc.)
     *
     * @var string
     */
    public $make;
    
    /**
     * The model (i.e., Focus, Civic, etc.)
     *
     * @var string
     */
    public $model;
    
    /**
     * The VIN
     *
     * @var string
     */
    private $_vin;
    
    /**
     * Car options
     *
     * @var array
     */
    protected $_options;
    
    
    /**
     * Car class constructor
     *
     * @param string $make The make of the car (i.e., Honda)
     * @param string $model The model of the car (i.e., Civic)
     * @param string $_vin (Optional) The VIN.
     * @param array $_options (Optional) Car options
     */
    public function __construct($make, $model, $_vin = '', $_options = array()) {
        $this->make = $make;
        $this->model = $model;
        $this->_vin = $_vin;
        $this->_options = $_options;
    }
    
    
    /**
     * Returns the car make
     *
     * @return string
     */
    public function getMake() {
        return $this->make;
    }
    
    
    /**
     * Returns the car model
     *
     * @return string
     */
    public function getModel() {
        return $this->model;
    }
    
    
    /**
     * Returns the VIN
     *
     * @return string
     */
    private function _getVin() {
        return $this->_vin;
    }
    
    
    /**
     * Returns a car option
     *
     * @param string $key The option name
     * @return mixed
     */
    protected function _getOption($key) {
        if (isset($this->_options[$key])) {
            return $this->_options[$key];
        } else {
            return false;
        }
    }
}

Functions and Variables

Functions and variables user lower_case_underscore format.

/**
 * Returns a true random number from RANDOM.ORG's integer http interface. Requires cURL.
 *
 * @author Bo Allen http://boallen.com
 * @param int $min Minimum number
 * @param int $max Maximum number
 * @return mixed Returns random integer on success, and a string error or message on failure
 */
function get_true_random_number($min, $max) {

    // Sanitize parameters
    $min_int = (int) $min;
    $max_int = (int) $max;
    
    // Curl options
    $options = array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HEADER => false,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_ENCODING => "",
        CURLOPT_USERAGENT => "PHP",
        CURLOPT_AUTOREFERER => true,
        CURLOPT_CONNECTTIMEOUT => 120,
        CURLOPT_TIMEOUT => 120,
        CURLOPT_MAXREDIRS => 10,
    );
    
    // Run curl
    $ch = curl_init("http://www.random.org/integers/?num=1&min={$min_int}&max={$max_int}&col=1&base=10&format=plain&rnd=new");
    curl_setopt_array($ch, $options);
    $content = curl_exec($ch);
    curl_close($ch);

    return trim($content);
}

Arrays

Example:
$user['salt_type'] = 'iodized';

Constants

Source Formatting

While a bit of source formatting can help readability, excessive formatting should be avoided.

Not Enough
$string = "MegaMan\n";
$string .= "X7\n";
$array = array('level' => 30, 'head_armor' => 4, 'body_armor' => 4, 'x_buster' => 9, 'energy' => 200, 'lives' => 3);
Too Much
$string  = "MegaMan\n";
$string .= "X7\n";
$array = array( 'level'         => 30,
                'head_armor'    => 4,
                'body_armor'    => 4,
                'x_buster'      => 9,
                'energy'        => 200,
                'lives'         => 3);
Just Right
$string = "MegaMan\n";
$string .= "X7\n";
$array = array(
    'level'         => 30,
    'head_armor'    => 4,
    'body_armor'    => 4,
    'x_buster'      => 9,
    'energy'        => 200,
    'lives'         => 3
);

File Structure

Inline Documentation

phpDoc should be used for inline PHP documentation.

This page was heavily borrowed from the MODx Revolution Code Standards page. Thanks!