CSS and JavaScript Best Practices


CSS Best Practices

 

DOCTYPE

Browsers can render your HTML code in many different ways. The DOCTYPE of an HTML document tells the browser how you want it to interpret and display your code. The most common DOCTYPES are HTML 4.01 Strict, HTML 4.01 Transitional, XHTML 1.0 Strict and XHTML 1.0 Transitional.

XHTML is a stricter and cleaner version of HTML.

Differences between HTML and XHTML:

 

 

<p>Paragraph <em>emphasized</em></p> because the <em> tag is opened and closed within the <p> tag.

However, this is not allowed:

<p>Paragraph <em>emphasized</p></em> because the <em> tag overlaps the <p> tag.

 

 

 

are invalid. And attributes which used to stand alone, must now be written as name=”value” pairs. For example <hr noshade="noshade" /> adds the noshade attribute to the <hr/> tag.

§         The root element of an XHTML document must be html, and must contain an xmlns attribute to associate it with the XHTML namespace. The namespace URI for XHTML is http://www.w3.org/1999/xhtml. The example tag below additionally features an xml:lang attribute to identify the document with a natural language:

   <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

 

Use XHTML 1.0 Strict DOCTYPE to clean markup, free of presentational clutter. There are two good reasons why we should be headed toward XHTML:

XHTML 1.0 strict DOCTYPE declaration:

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>

Using a DOCTYPE is a necessity for validating one’s XHTML, which is a great way to keep your code compliant, to quickly find any coding mistakes you may have made, and to perhaps help meet any standards requirements.

External Style Sheets

The STYLE tag should be avoided wherever possible. Style sheets should be externally linked and only imported when a special requirement needs to be met, such as Mac/IE consideration.

For larger projects, it is usually easiest to break the style sheets up either by area or code group.

TABLE Tags for Layout?

TABLEs are quirky in the various browsers. They are not “appropriate” to use for layout, they don’t seem to mix well with CSS, and they pose accessibility issues. Use <div> tag for instead.

Pixels, Percentages, or EMs for Font Sizes?

There are other choices for the font-size unit, but pixels (PX) seem to be the most used. They are the most reliable, simply because they cause the least grief during development. However, it is not the most accessible, since IE will not resize the PX unit.

If your project does require relative font-sizes, EM is the best choice. You can combat some of EM’s complexities by preparing the CSS a little. For example, Set the BODY font-size to 16px and then used EM as a measurement throughout to create a design where the majority of elements could be resized according to font size of the user.

1em is equal to the current font size. 2em means 2 times the size of the current font. E.g., if an element is displayed with a font of 12 pt, then ’2em’ is 24 pt. The ‘em’ is a very useful unit in CSS, since it can adapt automatically to the font that the reader uses

Float or Position your Advanced CSS Layout?

CSS-based layouts usually require either FLOATing or POSITIONing techniques to create the illusion of columns. There are drawbacks to both approaches—floating requires “clearing” and positioning limits a layout’s flexibility.

Positioning was the early answer to CSS layouts. It remains a viable option and many examples of its use are widely published on the Internet as “the” answer.

Use Float, it offers flexibility. Accessibility requirements may mean that text needs to be resized, which could cause broken layouts for positioned columns.

Applying Styles to HTML

Styles should always be applied with a CLASS attribute. Only use the ID attribute when absolutely necessary. Applying a style inline with the STYLE attribute should also only be used when necessary.

CSS Shortcuts

Use of CSS shortcuts is a great way to slim down your code. You should use every opportunity to group styles and use shortcuts.

Example:

.foo {margin-top: 11px; margin-right: 11px; margin-bottom: 11px; margin-left: 11px;}
.foo2 {margin-top: 11px; margin-right: 11px; margin-bottom: 11px; margin-left: 11px;}

Could be:

.foo, .foo2 {margin: 11px;}

Use a Reset

Consider using a reset. Resets essentially eliminate browser inconsistencies such as heights, font sizes, margins, headings, etc. The reset allows your layout look consistent in all browsers.

Reference to reset.css: http://developer.yahoo.com/yui/build/reset/reset.css

 

NOTE:      This technique to be only used if necessary on certain pages.

Organize the Stylesheet with a Top-down Structure

Lay your stylesheet out in a way that allows you to quickly find parts of your code. Consider top-down format that tackles styles as they appear in the source code. So, an example stylesheet might be ordered like this:

  1. Generic classes (body, a, p, h1, etc.)
  2. #header
  3. #nav-menu
  4. #main-content

Comment each section!

/****** main content *********/

styles goes here…

/****** footer *********/

styles go here…

Use CSS Compressors

CSS compressors help shrink CSS file size by removing line breaks, white spaces, and combining elements. This combination can greatly reduce the file size, which speeds up browser loading. Yahoo YUI compressor can be used.

java -jar yuicompressor-x.y.z.jar [options] [input file]
More info can e found at http://developer.yahoo.com/yui/compressor/

Add Margins and Padding to All

Different browsers render elements differently. IE renders certain elements differently than Firefox. IE 6 renders elements differently than IE 7 and IE 8. While the browsers are starting to adhere more closely to W3C standards, they’re still not perfect.

One of the main differences between versions of browsers is how padding and margins are rendered. If you’re not already using a reset, you might want to define the margin and padding for all elements on the page, to be on the safe side. You can do this quickly with a global reset, like so:

* {margin:0; padding:0;}

JavaScript Best Practices

 

Stick to a strict coding style

Browsers are very forgiving when it comes to JavaScript syntax. This should not however be a reason for you to write sloppy code that relies on browsers to make it work.

The easiest way to check the syntactical quality of your code is to run it through

 JSLint — a JavaScript validation tool that gives you a detailed report about the syntax warnings and their meaning.

Clean and valid code means less confusing bugs to fix, easier handover to other developers and better code security. When you rely on hacks to get your code to work it is likely that there is also a security exploit that uses the same hacks. In addition, as hacks get fixed in browsers, your code will cease to work in the next version of the browser.

Avoid mixing with other technologies

Whilst it is possible to create everything you need in a document using JavaScript and the DOM it is not necessarily the most effective way of doing so. The following code puts a red border around every input field when its class is “mandatory” and there’s nothing in it.

var f = document.getElementById('mainform');
var inputs = f.getElementsByTagName('input');
for(var i=0,j=inputs.length;i<j;i++){
  if(inputs[i].className === 'mandatory' &&
     inputs[i].value === ''){
    inputs[i].style.borderColor = '#f00';
    inputs[i].style.borderStyle = 'solid';
    inputs[i].style.borderWidth = '1px';
  }
}

This works, however it means that if you later need to make a change to these styles you need to go through the JavaScript and apply the changes there. The more complex the change is the harder it’ll be to edit this. Furthermore, not every JavaScript developer is proficient or interested in CSS, which means there’ll be a lot of back and forth until the outcome is reached. By adding a class called “error” to the element when there is an error, you can ensure that the styling information is kept inside the CSS, which is more appropriate:

var f = document.getElementById('mainform');
var inputs = f.getElementsByTagName('input');
for(var i=0,j=inputs.length;i<j;i++){
  if(inputs[i].className === 'mandatory' &&
     inputs[i].value === ''){
    inputs[i].className += ' error';
  }
}

This is much more efficient as CSS was meant to cascade through the document. Say for example you want to hide all DIVs with a certain class in a document. You could loop through all the DIVs, check their classes and then change their style collection. In newer browsers you could use a CSS selector engine and then alter the style collection. The easiest way however is to use JavaScript to set a class on a parent element and use syntax along the lines of element.triggerclass div.selectorclass{} in the CSS. Keep the job of actually hiding the DIVs to the CSS designer, as he’ll know the best way of doing that.

IDed Element Retrieval

 

The preferred to retrieve an element reference from the DOM method would be the W3C Core DOM standard document.getElementById method which is supported on the widest number of browsers.

Reference Forms and Form Elements Correctly

All forms in an HTML form should have a name attribute. For XHTML documents, the name attribute is not required and instead the form tag should have an id attribute and should be referenced using document.getElementById(). Referencing forms using indexes, such as document.forms[0] is a bad practice in almost all cases. Some browsers make the form available as a property of the document itself using its name. This is not reliable and shouldn’t be used.

The example below uses square bracket notation and correct object references to show the most fool-proof way of referencing a form input.

Correct Reference To Form Input

document.forms["formname"].elements["inputname"]
 

Bad Practice

document.formname.inputname
 
 

Avoid document.all

document.all was introduced by Microsoft in IE and is not a standard javascript DOM feature. Although many newer browsers do support it to try to support poorly-written scripts that depend on it, many browsers do not.

There is never a reason to use document.all in javascript except as a fall-back case when other methods are not supported and very early IE support (<5.0) is required. You should never use document.all support as a way to determine if the browser is IE, since other browsers also now support it.

Don’t Use HTML Comments In Script Blocks

In the ancient days of javascript (1995), some browsers like Netscape 1.0 didn’t have any support or knowledge of the script tag. So when javascript was first released, a technique was needed to hide the code from older browsers so they wouldn’t show it as text in the page. The ‘hack’ was to use HTML comments within the script block to hide the code.

Using HTML Comments in Script is bad

<script language="javascript">
<!--
   // code here
//-->
</script>

No browsers in common use today are ignorant of the <script> tag, so hiding of javascript source is no longer necessary. In fact, it can be considered harmful for the following reasons:

Use Correct <script> Tags

The LANGUAGE attribute is deprecated in the <script> tag. The proper way to create a javascript code block is:

<script type="text/javascript">
// code here
</script>

Multiple Browser Coding Guidelines

The features of different Web browsers, such as CSS and JavaScript support, can cause Web applications to work differently from one browser to another. This lack of continuity among browsers not only causes an application to look bad, but it often causes it to break.

Acid3 Test

 Acid3 is a test from the Web Standards Project that checks how well a web browser follows certain selected elements from web standards, especially relating to the Document Object Model (DOM) and JavaScript.

 Acid3 test focuses on technologies used on modern, highly interactive websites characteristic of Web 2.0, such as ECMAScript, HTML 4.01 Strict, XHTML 1.0 Strict and DOM Level 2. It includes several elements from the CSS2 recommendation that were later removed in CSS2.1 but reintroduced in World Wide Web Consortium (W3C) CSS3 working drafts.

Layout Engine

Browser

Acid3 Score

Presto

Opera 10

100/100

WebKit

Safari 4.0

100/100

Chrome 4.0

100/100

Gecko

 

Firefox 3.5.7

93/100

Firefox 3.6

94/100

Firefox 3.7a2

97/100

Firefox 4.0

?/100

Trident

 

IE 6.0

12/100

IE 7.0

14/100

IE 8.0

20/100

IE 9.0

32/100

Acid3 Test Score Chart

 

Tool of Choice

 One can handle most of the browser issues by using hacks but hacks are dangerous. Since they are based on non-standard exploits, you can’t predict how they are going to behave in future browsers. The tool of choice for fighting these problems is the conditional Stylesheet and JavaScript. Browsers provide comment tags, to target specific versions, as well as greater-than/less-than stuff for targeting multiple versions at once.

Conditional Stylesheets and JavaScripts

 The core idea is based on the method of Conditional Comments found in Internet Explorer, extended to include other browsers, and to move the conditional statements inline with your CSS definitions.

Conditional-CSS isn’t really all that interested in which browser the user using, but rather what is rendering engine the user’s browser utilizes. This is why Conditional-CSS uses ‘Gecko’ rather than the well known Firefox as one of its browser conditions. Likewise for Safari ‘Webkit’ is used. This allows other browsers using the same rendering engines to receive the same targeted CSS. An exception to this rule is made for IE (rather than using ‘Trident’) since this is what the IE conditional comments use and Trident isn’t particularly well known. Similarly for Opera, since only the Opera browser uses it’s Presto rendering engine, ‘Opera’ is used.

How to go about it?

  1. Choose one of the standard conforming browsers (Acid3 score 100/100) like Chrome 4.0 or Opera 10 to create and test a standard compliant Stylesheets and JavaScripts common for all browsers.
  2. Create a separate Stylesheet and Javascripts for each of the browser versions you want to target e.g. IE and Firefox versions.
  3. Include the Stylesheets and JavaScripts from step 2 by using conditional comments. This overrides the statements in the common CSS and javaScript file created in step 1.

 <!--[if IE]> <style type="text/css">@import "IE-override.css";</style> <![endif]-->

 This CSS file is only loaded if the detected browser is IE, otherwise it won’t. You should put this conditional statement into the head of your html file after every other CSS import code. It should be the last in the list, so that it overwrites the main css files:

 Now if for example you had a statement in your main.css file: #logo { margin:10px } and it doesn’t work properly in IE, you can add the same statement with a different value in your IE-override.css file: #logo { margin:20px }.

 

The Conditional Comment Code Examples

 The syntax to note is “!” stand for “not”, so !IE means “not IE”. gt means “greater than”, gte means “greater than or equal”, lt means “less than”, lte means “less than or equal.”

Target ALL VERSIONS of IE

 <!–[if IE]>

            <link rel=”stylesheet” type=”text/css” href=”all-ie-only.css” />

<![endif]–>

 Target everything EXCEPT IE

 <!–[if !IE]>

            <link rel=”stylesheet” type=”text/css” href=”not-ie.css” />

<![endif]–>

 Target IE 7 ONLY

 <!–[if IE 7]>

            <link rel=”stylesheet” type=”text/css” href=”ie7.css”>

<![endif]–>

 Target IE 6 ONLY

 <!–[if IE 6]>

            <link rel=”stylesheet” type=”text/css” href=”ie6.css” />

<![endif]–>

 Target IE 6 and LOWER

 <!–[if lt IE 7]>

            <link rel=”stylesheet” type=”text/css” href=”ie6-and-down.css” />

<![endif]–>

 <!–[if lte IE 6]>

            <link rel=”stylesheet” type=”text/css” href=”ie6-and-down.css” />

<![endif]–>

 Target IE 7 and LOWER

 <!–[if lt IE 8]>

            <link rel=”stylesheet” type=”text/css” href=”ie7-and-down.css” />

<![endif]–>

 <!–[if lte IE 7]>

            <link rel=”stylesheet” type=”text/css” href=”ie7-and-down.css” />

<![endif]–>

 

Target IE 8 and LOWER

 <!–[if lt IE 9]>

            <link rel=”stylesheet” type=”text/css” href=”ie8-and-down.css” />

<![endif]–>

 <!–[if lte IE 8]>

            <link rel=”stylesheet” type=”text/css” href=”ie8-and-down.css” />

<![endif]–>

Target IE 6 and HIGHER

 <!–[if gt IE 5.5]>

            <link rel=”stylesheet” type=”text/css” href=”ie6-and-up.css” />

<![endif]–>

 <!–[if gte IE 6]>

            <link rel=”stylesheet” type=”text/css” href=”ie6-and-up.css” />

<![endif]–>

 Target IE 7 and HIGHER

 <!–[if gt IE 6]>

            <link rel=”stylesheet” type=”text/css” href=”ie7-and-up.css” />

<![endif]–>

 <!–[if gte IE 7]>

            <link rel=”stylesheet” type=”text/css” href=”ie7-and-up.css” />

<![endif]–>

 Target IE 8 and HIGHER

 <!–[if gt IE 7]>

            <link rel=”stylesheet” type=”text/css” href=”ie8-and-up.css” />

<![endif]–>

 <!–[if gte IE 8]>

            <link rel=”stylesheet” type=”text/css” href=”ie8-and-up.css” />

<![endif]–>

How To Create an IE-Only Stylesheet

The tool of choice for fighting IE problems is the conditional stylesheet. IE provides comment tags, supported all the way up to the current IE 8 to target specific versions, as well as greater-than/less-than stuff for targeting multiple versions at once.

Why use conditional stylesheets?

1.    Create a stylesheet and javascript common for all browser, without using any hacks to work around rendering problems in MSIE
2.    Create a stylesheet and javascripts common for all versions of MSIE.
3.    Create a separate stylesheet and javascripts for each of the MSIE versions you want to target.
4.    Include the stylesheets and javascripts from 2 and 3 by using conditional comments.

One good example can be found at http://www.gpuri.com