This document outlines the coding standards and best practices we use for writing demos, sample code, code snippets, and so forth, for use on MDN.
The goal isn't to recommend one way of coding as being "the right way," because there are so many different technologies, practices, styles, tools, frameworks, and libraries to use, and different people have different favorites. Instead, this article presents a way that works; it's a single minimalist way that is predictable, transparent, and simple enough to not get in the way of learning the main aspects of web development that each demo (and associated article) is trying to teach.
The biggest advantage to adhering to these guidelines is that it will foster consistency across our samples and demos on MDN, which increases readability and comprehension overall.
Important: In several places in this article, we recommend using various shims, libraries, and so forth to simplify tasks. These are great for demos, but should not be used in live samples or code snippets on MDN, with few exceptions. The most obvious exception is if your example is, literally, demonstrating how to use these libraries.
General guidelines
This section provides quick general guidelines for creating an understandable minimal code sample to demonstrate usage of a specific feature or function.
Code samples need to be:
- simple enough to be understandable, but
- complex enough to do something interesting, and preferably useful.
There is one overarching consideration that you need to keep in mind:
Readers will copy and paste the code sample into their own code, and may put it into production.
Therefore, you need to make sure that the code example is runnable, but does not do anything that will cause an application to be insecure, grossly inefficient, or bloated. If the code example is not runnable or production-worthy, be sure to include a warning in a code comment and in the explanatory text. This also means that you should provide all of the information necessary to run the example including any dependencies and setup.
Client-side web technologies
Client-side technologies are the core focus of what many of us do, and of most of the docs on MDN. The following guidelines are not hard and fast rules, but they make sense to us.
Note: You should of course comment all your code to make it as clear as possible how your app works, and what you are intending with each major section. There is no such thing as too many comments, as long as they are concise, clear comments, and you can always strip them out as part of your build process, before you deploy your app.
HTML
Here are some guidelines about writing HTML documents that make sense to us.
Use the HTML DOCTYPE
Unless you are working on some kind of CMS system where you don't get to choose such page fundamentals, you should use the HTML5 DOCTYPE. It is short, easy to remember, and backwards compatible:
<!DOCTYPE html>
See Introduction to HTML5 for further information.
Include a basic document structure
Include <html>
, <head>
, <body>
, and static HTML for elements that don't need dynamic updating. It is tempting in this day and age to just generate everything with JavaScript, but this is bad for backwards compatibility and graceful degredation and just makes your browser work harder.
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <p>This is my content!</p> </body> </html>
Include a document language
In your <html>
element, set a document language with the lang
attribute:
<html lang="en-us">
This is good for accessibility and search engines, and helps with localizing content.
Define your document's character set
In HTML5, you can define a document's character set like so:
<meta charset="utf-8">
Use UTF-8 unless you have a very good reason not to; it will cover your character needs pretty much regardless of what language you are using in your document. In addition, you should always specify the character set as early as possible within your HTML's <head>
block (within the first kilobyte), as it protects against a rather nasty Internet Explorer security vulnerability.
General element coding style
HTML5 permits usage of HTML and XHTML markup styles, so it is really up to you what you use. For readability and maximum compatibility, we tend to use a hybrid approach. Specifics are follows:
- DO use lowercase for all element and attribute names, as it looks neater and means you can write markup out faster.
- DON'T include trailing slashes for empty elements (e.g.
<hr />
), as they are unnecessary and slow things down. They can also break old browsers if you are not careful (although from what we can recall, this hasn't been a problem since Netscape 4). - DO put all attribute values in quotes. It is tempting to omit quotes since HTML5 allows this, but markup is easier to read if you do include them, and it can cause problems sometimes if you don't. For example, if you have a class attribute with two values in it such as
class="important header"
, this can be misconstrued if the quotes were ommitted. - DON'T worry about writing out attributes in full, if the value is the same as the name. For example,
required="required"
is not really necessary; justrequired
is perfectly understandable and works fine.
Add the HTML Shiv for cross-browser HTML5 element support
HTML5 elements are fun and funky, and supported natively in all modern browsers. Unfortunately they are not supported by older browsers, which treat them as anonymous inline elements (display
: block
can fix this). Internet Explorer versions 9 and below however go one step further, and don't even allow you to style them with CSS. A fix is to create an instance of each one in the DOM, using document.createElement()
. Fortunately, Remy Sharp's HTML5 Shiv does all of this for you, plus it includes Jonathan Neal's Print Protector, prevents HTML5 content from being scrambled when printed out. Include it using an Internet Explorer conditional comment, so that only the browsers that need it download it:
<!--[if le IE 9]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"> </script> <![endif]-->
Add the viewport meta tag
Especially if you are creating an app-style experience, you will probably want to optimize your layout for viewing on different viewport sizes (and other differences in media features) using media queries. To make mobile browsers interpret media queries properly, you will need to include the viewport <meta>
tag in your HTML <head>
. You should include at least the following in your document, which can be modified later on as the need arises:
<meta name="viewport" content="width=device-width">
See Using the viewport meta tag to control layout on mobile browsers for further details.
CSS
Below are some CSS guidelines to make your code understandable and maintainable. In terms of efficient CSS code, you should read Writing efficent CSS.
Use expanded syntax
There are a variety of CSS writing styles you can use, but for development we prefer the expanded style, with the selector/opening brace, close brace, and each declaration on a separate line. This maximizes readability (and, again, promotes consistency on MDN):
p { color: white; background-color: black; padding: 10px; }
Use CSS flags
There are a variety of ways to break up the CSS inside each stylesheet, but whichever you choose, we would advise using a system of flags — use a comment to mark the start of each major section, and include inside each one a string that is highly unlikely to appear inside any CSS code, so that you can search for this string to browse through section beginnings. Optionally, you could also add a TOC at the start of your CSS outlining the structure of the whole styleheet.
A typical flag system looks like this:
/* || general layout styles */ /* CSS general layout styles go here */ /* || typography */ /* CSS typography styles go here*/
So searching for a double pipe character would allow you to browser the different sections of the document.
Use "mobile first" media queries
When including different sets of styles for different target viewport sizes using media queries inside the same stylesheet, it is good idea to make the default styling before any media queries have been applied to the document the narrow screen/mobile styling, and then override this for wider viewports inside successive media queries.
/*Default CSS layout for narrow screens*/ @media (min-width: 480px) { /*CSS for medium width screens*/ } @media (min-width: 800px) { /*CSS for wide screens*/ } @media (min-width: 1100px) { /*CSS for really wide screens*/ }
This has many advantages, outlined in our Mobile First article.
We appreciate that this is not ideal for every situation. A number of people have issues with Mobile First media queries because older desktop browsers such as Internet Explorer 6-8 do not support media queries, therefore these would be served the mobile view, which would be no good. To mitigate this problem, we would also recommend conditionally applying a media query polyfill such as respond.js to your app, inside a conditional comment:
<!--[if le IE 9]> <script src="scripts/respond.js"></script> <![endif]-->
Use flexible/relative units
For maximum flexibility over the widest possible range of devices, it is a good idea to size containers, padding, etc. using relative units like ems and rems, or percentages and viewport units if you want them to vary depending on viewport width. You can read some more about this in our Responsive design building blocks article.
Think carefully before using resets
For maximum control over CSS across platforms, a lot of people use CSS resets to remove every style, before then building things back up themselves. This certainly has its merits, but CSS resets can often be overkill, resulting in lots of extra time spent reimplementing things that weren't completely broken in the first place, like default margins, list styles, etc.
A more reasoned approach that we'd like to recommend you at least take a look at is normalize.css by Nicolas Gallagher, which aims to just make things more consistent across browsers, fix some default annoyances that we always get rid of (the margins on <html>
and <body>
, for example) and get rid of a few bugs.
Plan your CSS - avoid overriding
Before diving in and writing huge chunks of CSS, plan your styles carefully. What general styles are going to be needed, what different layouts do you need to create, what specific overrides need to be created, and are they reusable? Above all, you need to try to avoid too much overriding. If you keep finding yourself writing styles and then cancelling them again a few rulesets down, you probably need to rethink your strategy.
JavaScript
This current crop of JavaScript guidelines is taken from our Mozilla Coding Style page, which is dedicated more towards creating code specifically for Mozilla projects such as the Firefox browser. The two will probably diverge in the future.
- Make sure you are aware of the JavaScript Tips.
- Do not compare
x == true
orx == false
. Use(x)
or(!x)
instead.x == true
, in fact, is different fromif (x)
! Compare objects tonull
, numbers to0
or strings to""
if there is chance for confusion. - Make sure that your code doesn't generate any strict JavaScript warnings, such as:
- Duplicate variable declaration
- Mixing
return;
withreturn value;
- Undeclared variables or members. If you are unsure if an array value exists, compare the index to the array's length. If you are unsure if an object member exists, use
"name" in aObject
, or if you are expecting a particular type you may usetypeof(aObject.name) == "function"
(or whichever type you are expecting).
- Use
[value1, value2]
to create a JavaScript array in preference to usingnew Array(value1, value2)
which can be confusing, asnew Array(length)
will actually create a physically empty array with the given logical length, while[value]
will always create a 1-element array. You cannot actually guarantee to be able to preallocate memory for an array. - Use
{ member: value, ... }
to create a JavaScript object; a useful advantage overnew Object()
is the ability to create initial properties and use extended JavaScript syntax to define getters and setters. - If having defined a constructor you need to assign default properties, it is preferred that you assign an object literal to the prototype property.
- Never use alert and friends. Use console.log instead.
- Use regular expressions, but use them wisely. For instance, to check that
aString
is not completely whitespace use/\S/.test(aString);
only useaString.search()
if you need to know the position of the result, oraString.match()
if you need to collect matching substrings (delimited by parentheses in the regular expression). Regular expressions are less useful if the match is unknown in advance, or to extract substrings in known positions in the string. For instance,aString.slice(-1)
returns the last letter inaString
, or the empty string ifaString
is empty.
More to come
Other sections will be added as we get to them, and they are deemed necessary. Please feel free to add your own ideas if you wish.
Shell prompts
A shell is a program that waits for you to type in a command and then press the return key. To indicate which commands you should type, MDN documentation lists them in a code block, similar to code examples. Such a block looks like this:
# This may take a while... hg clone https://hg.mozilla.org/mozilla-central/ firefox cd firefox
There are a some conventions when writing a shell code block:
- Do not include a "$" or ">" at the beginning of a shell instruction. It confuses more than it helps and it is not useful when copying the instructions.
- Comments start with "#".
- Choose the "Bash" syntax highlighter.
Tools and libraries
There are many tools and libraries out there, and different developers have their own preferences. Therefore, we don't really want to recommend any single toolchain as being the right one to use. We'd rather present demos that use mostly vanilla HTML, CSS, JavaScript, etc., so that it is as easy to follow the subject matter as possible, and apply it to your own particular workflow, rather than becoming frustrated by setting up and working through a load of unfamiliar JavaScript libraries, build tools, etc.
Apps template
We have created a simple app template to help speed up app development of installable Firefox OS apps. There are a few things that we include in our basic template, to make life easier for rapid app prototyping, but this is only one way to do it, and not the only right way.
The app template can be downloaded from github — see the mdn-app-template github page.
The template contains the following directory structure.
- index.html - contains a minimalist markup structure, as outlined in our HTML best practices section, above, plus an install
<button>
(id="install-btn"
), which is styled and scripted by the appropriate CSS and JavaScript files mentioned below. - webapp.manifest - a minimal manifest, as required by installable apps. If you don't want to make an installable app, you can delete this, but it is useful to outline the basics for those that do.
- .htaccess - a simple
.htaccess
file containing a few universal rules that you should always include, such as Adding video Mime types so videos will play without hassle across browsers, and adding manifest file Mime type. - favicon.ico - a simple favicon, just as a reminder.
- app-icons - a separate folder containing app icons, in three sizes appropriate for Firefox OS apps: 16, 48 and 128 px.
- images - A folder for your images.
- styles - a folder for your styles.
- normalize.css - as outlined above, in Think carefully before using resets, normalize provides consistency and bugfixes, as a slightly more sane alternative to resets.
- app.css - the main stylesheet for the app. Inside here we've included a minimal mobile first media query structure as a reminder.
- install-button.css - the CSS for styling our install button, delete if you don't want your app installable.
- scripts - a folder for your JavaScript.
- app.js - the main JavaScript file for our app; empty to begin with.
- respond.js - added in to provide width/height media query support for older browsers that don't support media queries natively.
- install.js - checks whether the app is installed or not; if so, it hides the install button. If not, it adds a click handler to the button so that the app is installed on the device when clicked (currently only works with Firefox OS and Firefox Aurora/Nightly).
Note: We think CSS preprocessors like Sass and Less are awesome. Build systems and automation tools like Volo and Grunt are also cool. And, yes, linters like JSHint and JSLint are also great. However, we avoided using these in our template because we don't want them to present a barrier to those who don't use them (or prefer different ones). By and large, our goal is to teach Web technologies, not specific libraries and tools.