Style Guide

These are the general style qualities that we expect your web pages to have in order to receive full credit. Certainly it is possible to write good code that violates these guidelines, and you may feel free to contact us if you are unclear about or disagree with some of them. But we do expect you to follow these rules (unless there is an error in this document). In most professional work environments you are expected to follow that company's style standards. Learning to carefully obey a style guide, and writing code with a group of other developers where the style is consistent among them, are valuable job skills.

This document is a work in progress. Any guidelines written here are in addition to what is mentioned in the given assignment's spec, so you are responsible for reading that spec and following its instructions.
Last updated Mon 2013/04/04

Languages:


HTML
  • indenting: Increase your indentation by one increment (one tab, or four spaces, etc., consistently) every time you open a new block-level element, and decrease it once each time you close a block element.

  • line breaks: Place a line break after every block element. Do not place more than one block element on the same line.

    <!-- bad -->
    <p>Hello, how are you</p>  <p>I am fine</p>
    
    <!-- good -->
    <p>Hello, how are you</p>
    <p>I am fine</p>
    
  • long lines: We permit long lines, but never begin a block element past character index 100 on a given line. When any line is longer than 100 characters and you need to begin a new block element, break it into two lines by pressing Enter after a token and resuming on the next line.

  • blank lines: Place a blank line between sections of the page and between large elements containing a lot of content.

  • elements: Do not place whitespace between a tag's < brace and the element name.

    < p >
    
    <p>
    
  • self-closing tags: End them with a space, followed by />.

    <br>
    
    <br />
    
  • choosing semantic tags: Choose appropriate tags that represent the semantic meaning of the content. For example, do not use a <p> tag around something that is not a paragraph, or do not use a <h4> unless you have already previously used h1-h3 for three other more important levels of headings, or do not use a blockquote just because you want some non-quote content to be indented to the right.

  • closing tags: You should close ALL tags, unless they are self-closing. For example, every <p> should have a corresponding </p>, and every <li> should have a corresponding </li>. Note that the HTML5 validator does not require this, but we do.

    <p>first paragraph
    <p>second paragraph
    <ul>
        <li>first item
        <li>second item
        <li>third item
    </ul>
    
    <p>first paragraph</p>
    <p>second paragraph</p>
    <ul>
        <li>first item</li>
        <li>second item</li>
        <li>third item</li>
    </ul>
    
  • nesting: Close tags in the opposite order in which they were opened. Always nest every inline element inside of a block element. (For example, don't just put an <a> tag directly inside the body; instead, place it inside a p or li or other block-level element.

  • presentational tags: Do not ever use deprecated tags whose meaning is entirely based on their appearance, such as b, i, u, big, small, center, or font. (Use CSS instead to achieve such an appearance.)

  • attributes: Do not place a space between an attribute's name, the equals sign, and its value. Enclose the value in " " quotes, not bare, and not in ' ' apostrophes.

    <a href = 'foo.html'>
    
    <a href="foo.html">
    
  • boolean attributes: For attributes that are essentially boolean flags, set them equal to themselves.

    <input type="text" disabled />
    
    <input type="text" disabled="disabled" />
    
  • img tag alt attribute: Every img tag must have an alt attribute so that it can be understood by visually impaired users.

    <img src="kittens.jpg" />
    
    <img src="kittens.jpg" alt="a long cat" />
    
  • names: When giving an element an id or class, give it a descriptive name, such as mainheading or announcements. Avoid one-letter names like x or c.

  • capitalization: Always favor lowercase, for elements, for attributes and their values, for classes and ids. Multi-word names for classes and ids should simply concatenate the words in lowercase without any in-between character (such as _) and without capitalization of the next word.

    <h1 id="first_heading">
    <P Class="importantReminder">
    
    <h1 id="firstheading">
    <p class="importantreminder">
    
  • class vs. id: Choose appropriately between classes and ids. If an element belongs to a general category that can include multiple elements, use a class. If it is a unique part of the page that deserved to be named on its own, use an id.

  • class-itis and id-itis: Do not over-use classes and ids on elements that do not need them. If an equivalent style can be described cleanly using a CSS context selector such as .announcements li > strong rather than a class or id, consider doing that instead. A class or id is still more appropriate than a context selector if the context is very complicated or not really related to the styling.

  • tables for layout: Do not use HTML table tags to lay out the contents of a web page. For example, it is inappropriate to use a table to divide the page's main content sections into columns, or to get a sidebar or navigation bar, etc. Instead, use div and other related tags along with the CSS box model and the float property as appropriate. See Chapter 4 of the Web Programming Step by Step textbook for examples.

  • inline css styles: Should never be used. All CSS styles should be specified within a .css file and never as part of an HTML tag with the style attribute.

CSS
  • whitespace: Place a line break after a { or }, and between each property declaration. Place spaces between selectors and { }. Place a space after a colon or a comma. Place a semicolon after every property declaration.

    p,h1{color:red; font-family:serif; font-size:16pt;}
    a {text-decoration:none}
    
    a {
        text-decoration: none;
    }
    
    h1, p {
        color: red;
        font-family: serif;
        font-size: 16pt;
    }
    
  • property order: Alphabetize the order of the properties of every style rule, always. As much as is reasonable, also alphabetize the order of selectors in a rule that contains more than one selector (like with h1 and p below).

    p, h1 {
        font-size: 16pt;
        text-decoration: underline;
        font-family: serif;
        color: red;
    }
    
    h1, p {
        color: red;
        font-family: serif;
        font-size: 16pt;
        text-decoration: underline;
    }
    
  • minimize redundant CSS: If you repeat the same styles two or more times, and the styles are related in some way, find a way to remove the redundant code so that it appears only once. For example, place it into a common style rule that is used in both places. Note that not every common style should be combined; if two completely unrelated tags happen to share a style attribute (such as both being bold), this does not necessarily mean that they should be combined. A good example of when styles should be combined is if a site has a common font or color scheme that is used on several elements. The style should be written once and used throughout the page so it can be changed easily later if needed.

    p {
        font-family: "Comic Sans MS", sans-serif;
    }
    h1 {
        font-family: "Comic Sans MS", sans-serif;
    }
    
    h1, p {
        font-family: "Comic Sans MS", sans-serif;
    }
    
  • avoid unnecessary CSS rules: If a rule is not ever used in the page, remove it from your CSS file.

  • "vendor prefixed" CSS rules: Some CSS3 properties have browser-specific versions with prefixes like -webkit- and -moz-. Do not use these vendor-specific properties in your homework assignments unless you are specifically granted permission to do so.

    div {
        -webkit-border-radius: 10px;
    }
    
    div {
        border-radius: 10px;
    }
    
JavaScript
  • frameworks (e.g. jQuery): Please follow any restrictions in your assignment spec about the use of external JavaScript libraries such as jQuery. If the spec forbids using such libraries, do not link to them or use them in your code. These libraries can be very useful and powerful, but in a course setting, sometimes the assignment is intended to be solved without the use of these tools.

  • unobtrusive JavaScript: Always use unobtrusive JavaScript to keep all JavaScript commands entirely out of your HTML code and entirely inside your JavaScript file. The only JavaScript-related change to your HTML file is to link to your JS file using a script tag. No onclick, onchange, onmouseover, etc. handlers should ever be declared in your HTML files.

    <!-- bad (HTML) -->
    <button onclick="foo();">Click Me</button>
    
    // bad (JS)
    function foo() {
        alert("You clicked the button.");
    }
    
    <!-- good (HTML) -->
    <button id="clickme">Click Me</button>
    
    // good (JS)
    window.onload = function() {
        document.getElementById("clickme").onclick = foo;
    };
    
    function foo() {
        alert("You clicked the button.");
    }
    
  • use strict: Always write a "use strict"; declaration at the top of your JS file to tell the browser to enable strict syntax checking of your JavaScript code.

  • JSLint: All of your JS files must pass the provided JSLint tool with zero errors. JSLint "warnings" or "notices" are less serious messages; it is okay to have these in your code.

  • module pattern: Always use the "module pattern" of wrapping your JS file's code inside an anonymous function that is immediately invoked, to get rid of global variables.

    // bad
    var x = 3;
    var y = 4;
    
    function f() {
        x++;
    }
    
    // good
    (function() {
        "use strict";
    
        var x = 3;
        var y = 4;
    
        function f() {
            x++;
        }
    })();
    
  • minimize global and module-global variables: Avoid global variables as much as possible. If you use the module pattern, your code should declare 0 global variables. Even when using the module pattern, you should try to minimize the number of "module-global" variables that are declared at the outermost scope within your anonymous wrapper function.

    // global variables: avoid these at all costs
    var globalBad = 123;      // bad
    var globalBad2 = 456;     // bad
    
    (function() {
        "use strict";
    
        // module-global variables: some are okay, but don't over-use them
        var x = 7;
        var y = 8;
    
        function f() {
            // local variables: these are great!
            var z = 9;
        }
    })();
    
  • DOM objects as globals: Do not store DOM element objects, such as those returned by the document.getElementById or document.querySelectorAll functions, into global or module-global variables. Every time that you need them in a function, call the appropriate "get" function locally.

    // bad
    var inputBox = document.getElementById("passwordbox");
    
    function f1() {
        inputBox.value = "giraffe";
    }
    function f2() {
        inputBox.value = "horse";
    }
    
    // good
    function f1() {
        var inputBox = document.getElementById("passwordbox");
        inputBox.value = "giraffe";
    }
    function f2() {
        var inputBox = document.getElementById("passwordbox");
        inputBox.value = "horse";
    }
    
    // alternative
    function f1() {
        document.getElementById("passwordbox").value = "giraffe";
    }
    function f2() {
        document.getElementById("passwordbox").value = "horse";
    }
    
  • other global variable hacks: Some students try other bizarre hacks to basically achieve global variables. For example, you can stuff various variables and values as dynamically created fields inside global DOM objects such as the document object, or you can store anything into the global localStorage array. In general such trickery should be avoided, and global DOM objects should not be abused as a way around declaring global variables.

  • anonymous functions: Anonymous functions are useful and expressive in some cases where a function's name is meaningless and cumbersome, such as an initial window.onload handler. But over-using anonymous functions leads to code that is too heavily nested and has too few names to guide the programmer, so over-use of anonymous functions should be avoided. In general, give names to your functions unless the name is truly useless and meaningless.

    // bad
    window.onload = function() {
        myButton.onclick = function() {
            setTimeout(function() {
                alert("hi!");
            }, 1000);
        };
    }
    
    // good
    window.onload = function() {
        myButton.onclick = myButtonClick;
    }
    
    function myButtonClick() {
        setTimeout(displayHiMessage, 1000);
    }
    
    function displayHiMessage() {
        alert("hi!");
    }
    
  • setting styles in JS code: If you are setting several styles on a DOM object in JS code, instead declare a class in your CSS file and use the JS code to apply that class to the DOM object. This helps keep most of the style decisions in your CSS file where they belong and out of your JS code.

    // bad (JS)
    myButton.style.border = "2px dotted green";
    myButton.style.color = "red";
    myButton.style.fontSize = "20pt";
    myButton.style.fontWeight = "bold";
    myButton.style.textDecoration = "underline";
    
    /* good (CSS) */
    button.urgent {
        border: 2px dotted green;
        color: red;
        font-size: 20pt;
        font-weight: bold;
        text-decoration: underline;
    }
    
    // good (JS)
    myButton.className = "urgent";
    
  • semicolons: JavaScript often still works if semicolons are omitted, using complex logic called automatic semicolon insertion (ASI). But you should not rely on this and should always insert semicolons wherever you end a complete statement of code.

    // bad
    var x = 3
    var y = 4
    
    function foo() {
        alert("hi!");
    }
    
    window.onload = function() {
        x++
        foo()
    }
    
    // good
    var x = 3;
    var y = 4;
    
    function foo() {
        alert("hi!");
    }
    
    window.onload = function() {
        x++;
        foo();
    };
    
  • indenting: Increase your indentation by one increment on each brace {, and decrease it once on each closing brace }.

  • line breaks: Place a line break after every { . Do not place more than one statement on the same line.

    // bad
    var x = 3;  var y = 4;  x++;
    if (a == b) { foo(); }
    
  • long lines: When any line is longer than 100 characters, break it into two lines by pressing Enter after an operator and resuming on the next line. Indent the trailing second part of the line by two increments (e.g. two tabs). For example:

    var result = reallyLongFunctionOne() + reallyLongFunctionTwo() + 
            reallyLongFunctionThree() + reallyLongFunctionFour();
    
    var result2 = reallyLongFunction(parameterOne, parameterTwo, parameterThree,
            parameterFour, parameterFive, parameterSix);
    
  • expressions: Place a space between operators and their operands.

    var x = (a + b) * c / d + foo();
    
  • blank lines: Place a blank line between functions and between groups of statements.

    function foo() {
        ...
    }
                              // this blank line here
    function bar() {
        ...
    }
    
  • names: Give variables descriptive names, such as firstName or homeworkScore. Avoid one-letter names like x or c, except for loop counter variables such as i.

  • capitalization: Name variables and functions with camel-casing likeThis, name classes with Pascal casing LikeThis, and name unchanging "constant" variables in uppercase LIKE_THIS.

  • scope: Declare variables in the narrowest possible scope. For example, if a variable is used only inside a specific if statement, declare it inside that if statement rather than at the top of the function or at the top of the class.

  • constants: If a particular constant value is used frequently in your code, declare it as a module-global "constant" variable in uppercase, and always refer to the constant in the rest of your code rather than referring to the corresponding value.

    var DRINKING_AGE = 21;
    
  • for vs while: Use a for loop when the number of repetitions is known (definite); use a while loop when the number of repetitions is unknown (indefinite).

    // repeat exactly size/2 times
    for (var i = 0; i < size / 2; i++) {
        ...
    }
    
    // repeat until the user clicks OK
    while (!confirm("Are you sure?")) {
        ...
    }
    
  • break and continue: In general, you should avoid using the break or continue statements in loops unless absolutely necessary.

  • if/else patterns: When using if/else statements, properly choose between various if and else patterns depending on whether the conditions are related to each other. Avoid redundant or unnecessary if tests.

    // bad
    if (grade >= 90) {
        alert("You got an A!");
    }
    if (grade >= 80 && grade < 90) {
        alert("You got a B!");
    }
    if (grade >= 70 && grade < 80) {
        alert("You got a C!");
    }
    ...
    
    // good
    if (grade >= 90) {
        alert("You got an A!");
    } else if (grade >= 80) {
        alert("You got a B!");
    } else if (grade >= 70) {
        alert("You got a C!");
    }
    ...
    
  • boolean zen 1: If you have an if/else statement that returns a boolean value based on a test, just directly return the test's result instead.

    // bad
    if (score1 == score2) {
        return true;
    } else {
        return false;
    }
    
    // good
    return score1 == score2;
    
  • boolean zen 2: Don't ever test whether a boolean value is == or != to true or false.

    // bad
    if (x == true) {
        ...
    } else if (x != true) {
        ...
    }
    
    // good
    if (x) {
        ...
    } else {
        ...
    }
    
  • exception handling: We don't use exceptions really in JS in this material. So in general you should avoid try/catch statements because this is not how we intend you to solve the problems. But if you do need to use one, don't ever catch an exception with an empty catch block.

    // bad
    try {
        foo();
        bar();
    } catch (npe) {}
    
  • minimize redundant code: If you repeat the same code two or more times, find a way to remove the redundant code so that it appears only once. For example, place it into a helper function that is called from both places. If the repeated code is nearly but not entirely the same, try making your helper function accept a parameter to represent the differing part.

    // bad
    foo();
    x = 10;
    y++;
    ...
    
    foo();
    x = 15;
    y++;
    
    // good
    helper(10);
    helper(15);
    ...
    
    function helper(newX) {
        foo();
        x = newX;
        y++;
    }
    
  • if/else factoring: Move common code out of if/else statements so that it is not repeated.

    // bad
    if (x < y) {
        foo();
        x++;
        alert("hi");
    } else {
        foo();
        y++;
        alert("hi");
    }
    
    // good
    foo();
    if (x < y) {
        x++;
    } else {
        y++;
    }
    alert("hi");
    
  • function structure: If you have a single function that is very long, break it apart into smaller sub-functions. The definition of "very long" is vague, but let's say a function longer than 20-30 lines is pushing it. If you try to describe the function's purpose and find yourself using the word "and" a lot, that probably means the function does too many things and should be split into sub-functions.

  • save expensive call results in a variable: If you are calling an expensive function and using its result multiple times, save that result in a variable rather than having to call the function multiple times.

    // bad
    if (list.indexOf("abc") >= 0) {
        list.remove(list.indexOf("abc"));
    }
    
    // good
    var index = list.indexOf("abc");
    if (index >= 0) {
        list.remove(index);
    }
    
JavaScript Framework: jQuery
  • Usage: When explicitly allowed by the homework specification, you can use jQuery, but we expect your Javascript to be written in the style of the jQuery framework. There are many many bad resources for jQuery so be careful how you Google, below are the best style practices for the most common jQuery actions, if you have style questions on other features feel free to post on the message board.

  • Function calls: They SHOULD be chained when possible, most jQuery calls return the original object so they can be chained appropriately. Chained method calls should be on their own line for readability

    // bad
    var obj = $("#selected").callOne();
    obj = obj.callTwo();
    obj = obj.callThree();
    obj = obj.callFour();
    
    // good
    var obj = $("#selected").callOne()
                            .callTwo()
                            .callThree()
                            .callFour();
    
  • Global functions: When calling a global function (e.g. post, ajax)you should call the $ object instead of the jQuery object.

    // bad
    jQuery.globalFunction();
    
    // good
    $.globalFunction();
    
  • Document onload: When using jQuery it is incorrect to specify listeners directly on the window or document object. Instead you should use the ready event listener. Note that for page loads you should always use ready and not load

    // bad
    window.onload = pageReadyHandler;
    
    // good
    $(document).ready(pageReadyHandler);
    
  • CSS properties: All CSS properties should be accessed and set via the css() method

  • Nested selectors: It is better to use find than to nest when possible, this is because the sizzle engine that is internal to jQuery can optimize these calls more.

    // bad
    var children = $("#overallDiv .subClass");
    
    // good
    var children = $("#overallDiv").find(".subClass");
    
  • Manipulating page content: If jQuery provides a method to manipulate a value or attribute it should be used instead of manually manipulating things. Here is a non-exhaustive list of examples:

    • When adding HTML content to the page you should use html() instead of innerHTML
    • When creating content nodes you should use append() to add it to the page
    • When getting/setting text you should use text() instead of attributes like textContent
    • When getting/setting input values you val() instead of the value attribute
  • Avoid looping when possible: Most jQuery result objects can apply calls to every value in the returned set and this should be used instead of looping over the results

    // bad
    var results = $('.findMe');
    for(var i = 0; i < results.length; i++) {
    	results.css({ "color" : "red" });
    }
    
    // good - jQuery knows to apply it to everything
    $('.findMe').css({ "color" : "red" });
    
  • Attaching events: jQuery provides a number of named event methods like click() or mouseover(), when attaching events to objects these should be preferred over manual bindings. If no named method exists the bind() method should be used.

  • Detaching events: To detach you must use the unbind() method, no other method will completely unregister your event handlers and this may cause adverse side effects.

  • AJAX requests: You should use the specific $.get and $.post methods when possible, falling back to $.ajax when the request type is dynamically determined. In addition all parameters should be sent via a data object instead of directly in the url

    // bad
    $.ajax({
    	url : "service.php?param1=data1&param2=data2",
    	type : "GET"
    	...
    })
    
    // good
    $.get({
    	url : "service.php",
    	data : {
    		param1 : data1,
    		param2 : data2
    	}
    	...
    })
    
JavaScript Framework: Prototype
  • Usage: When explicitly allowed by the homework specification, you can use Prototype, but we expect your Javascript to be written in the style of the Prototype framework. Below are the best style practices for the most common Prototype actions, if you have style questions on other features feel free to post on the message board.

  • Querying for ids: You should use the provided $ object instead of document.getElementById

  • Querying with css selectors: You should use the provided $$ object instead of document.querySelector[All]

  • Querying for form controls: You should use the provided $F when querying for form controls

  • Manipulating content: Instead of looping over a result set form Prototype to apply a function, you should take advantage of the special invoke function that is added to result sets.

    // bad
    var results = $$('.findMe');
    for(var i = 0; i < results.length; i++) {
    	results.hide();
    }
    
    // good
    $$('.findMe').invoke('hide')
    
  • AJAX requests: Ajax requests should be sent using the Ajax.Request object instead of the XMLHttpRequest. Responses will be automatically decoded by this library so you won't need functions like JSON.parse

  • Animations: Any animations should be done via the Effects object that is part of prototype. More complex animations should use the extended library scriptaculous

Comments
  • file header: Place a descriptive comment heading on the top of every file describing that file's purpose. Assume that the reader of your comments is an intelligent programmer but not someone who has seen this assignment before. Your comment header should include at least your name, course/section, and a brief description of the assignment. If the assignment asks you to submit multiple files, each file's comment header should describe that file/class and its main purpose in the program.

  • function headers: Place a comment heading on each function you declare. The heading should describe the function's behavior.

  • parameters/return: If your function accepts parameters, briefly describe their purpose and meaning. If your function returns a value, briefly describe what it returns.

  • inline comments: Inside the interiors of your various functions, if you have sections of code that are lengthy or complex or non-trivial, place a small amount of inline comments near these lines of complex code describing what they are doing.

  • implementation details: Comment headers at the top of a function or class should describe the function's behavior, but not great detail about how it is implemented. Do not mention language-specific details like the fact that the function uses a if/else statement, that the function declares an array, that the function loops over a collection and counts various elements, etc.

  • wording: Your comment headers should be written in complete sentences, and should be written in your own words, not copied from other sources (such as copied verbatim from the homework spec document).

  • commented-out code: It is considered bad style to turn in a program with chunks of code "commented out". It's fine to comment out code as you are working on a program, but if the program is done and such code is not needed, just remove it.

Valid HTML5 Valid CSS JavaScript Lint
This document and its content are copyright © Allison Obourn and Marty Stepp, 2015. All rights reserved. Any redistribution, reproduction, transmission, or storage of part or all of the contents in any form is prohibited without the author's expressed written permission.