facebook google plus twitter
Webucator's Free Advanced CSS Tutorial

Lesson: CSS Best Practices

Welcome to our free Advanced CSS tutorial. This tutorial is based on Webucator's Advanced CSS Training course.

In this lesson, we layout practices that we recommend that you consider. We feel more strongly about some than others. At the end of the lesson, we provide a summary table, in which we indicate how strongly we recommend the practice.

Lesson Goals

  • Use best CSS practices in your web development.

Considerations

In compiling this list of best practices, we've considered the following:

  • Cleaner code. Does the practice result in cleaner, better organized, more reusable code?
  • Faster development. Does the practice lead to faster development?
  • Speedier download. Does the practice result in speedier downloads?
  • Greater control. Does the practice give the developer greater control over the layout and/or the development process?
  • Accessibility. Does the practice make your pages more accessible?

Each practice must meet at least one of these conditions.

Use CSS

By now, we hope that you're sold on this. Using CSS for formatting instead of deprecated HTML tags and attributes will result in cleaner, easier-to-maintain code that downloads faster. Using CSS for page layout instead of tables will also result in cleaner, easier-to-maintain code that downloads faster and it will make your pages more accessible. And CSS gives you more control over the look and feel of your web pages.

Use External Style Sheets

In almost all cases, you should use external style sheets instead of embedded style sheets. And you should avoid using the style attribute at all. Using external style sheets results in better organized, easier-to-maintain code. Because the browsers can cache the style sheet, the code doesn't need to be redownloaded as a visitor navigates through your site.

In addition, it's a good idea to avoid multiple stylesheets when possible: forcing the user to download more than one stylesheet - either through several <link> tags in HTML pages or through @import statements in the stylesheets themselves - will result in slower page loads, since most browsers limit the number of concurrent file downloads.

Organize Your Style Sheets/Preprocessors

Some people recommend using different style sheets for different types of content:

  • General styles. These are usually simple type selectors, perhaps with some child, descendant, or attribute selectors included.
  • Special formatting styles. These are generally class and id selectors for styles you're likely to reuse often (e.g., "callout" or "important").
  • Layout styles. These are also generally class and id selectors for laying out your pages.
  • Specific styles. These are styles specific to a section or individual page on your website.

One way to accomplish this organization is to organize the various functional areas (general styles, special formatting, styles, etc.) into sections of one main stylesheet. A better way is to indeed use separate stylesheets - but, to avoid (as we mentioned above) having multiple calls to several stylesheets (and thus slowing down page speed), a better option is to use a CSS preprocessor like Sass. In fact, using a preprocessor like Sass or Less, another popular option, is a great strategy for speeding up CSS development time, organizing CSS for a complex site, and working on CSS as part of a team.

CSS preprocessors/precompilers have grown in popularity in recent years, for good reason. Working from a sort of CSS metalanguage, preprocessors offer a more convenient syntax; the ability to define variables, mixins (reuseable libraries of code), and nesting (all of which we'll look at below); and generally simplify the chore of writing lots and lots of CSS. All generate syntactically valid CSS. We'll look here at Sass (Syntactically Awesome Stylesheets); Less is another popular alternative.

Using Sass means writing Sass code in a .scss file and then compiling that code (using the Ruby-based compiler) to generate syntactically valid, perfectly ordinary CSS code in a .css file. Mac users likely have Ruby already installed (it comes with OSX); Windows users can download the RubyInstaller to install Ruby. Once Ruby is installed, you can download and install Sass (for free) by typing gem install sass (sudo gem install sass and type admin password, if prompted, on a Mac) from a command prompt. Let's look at a simple example:

Open the three files in ClassFiles/CssBestPractices/Demos/sass/. The HTML file is pretty simple - a div containing an h2 title and some paragraph text - and is styled via an external style sheet, sassstyle.css:, which has the following code:

#example {
	border: 1px solid #d98c8c; }
	#example h2 {
		color: #dbc7bd; }

This CSS file was generated by compiling the Sass style sheet sassstyle.scss:

$border-color: hsl(0, 50%, 70%);
$h2-color: hsl(20, 30%, 80%);
#example {
	border:1px solid $border-color;
	h2 {
		color:$h2-color;
	}
}

You can write Sass in a couple of different ways. The example here shows SCSS ("Sassy CSS"); it looks very much like CSS - in fact, any valid CSS is valid SCSS. The other, and older, syntax - often referred to as "indented syntax" or just "Sass" - uses indentation instead of braces to indicate nesting and uses newlines instead of semicolons to indicate the end of properties. Which you use is up to you; we'll use the newer syntax here.

At the start of sassstyle.scss, we define two variables, $border-color and $h2-color. While not a big deal in this example, you can see the value CSS variables brings to code organization, making it easier to change a set color, width, or other value throughout thousands of lines of code by changing the value of one variable.

The Sass file also shows the simplicity of nesting: the styles for the <h2> are defined within the open/close braces that define the styles for #example - the generated output lists the styles correctly, with #example h2.

There's lots more Sass can do: functions, interpolation (using #{$i} to display the actual value of Sass variable $i), mixins (allowing re-use of styles, optionally with arguments), and other features of the language offer a cleaner, quicker way to write and maintain complex CSS code. We can even write a for loop:

@for $i from 1 through $number-of-items + 1 {
	ul li:nth-child(#{$i}) {
		background-color: darken($key-color, $i * 5);
	}
}

This code would write multiple statements using the :nth-child selector to set the background color of a list item darker and darker, making use of Sass's darken function (which darkens a color, its first parameter, by the percentage given in its second parameter.)

While delving too deep into using Sass or other preprocessors is beyond the scope of this course, we do encourage you to check it out - you can put to use all of the CSS you've learned so far (since valid CSS code is valid Sass code), and you can leverage the power of code organization, variables, and other Sass features to write cleaner, faster, and easier to maintain CSS. We'll ask you to try out Sass with the next exercise:

Using Sass

Duration: 20 to 30 minutes.

In this exercise, you will download, install, and use Sass to write some simple CSS.

  1. If needed, install Ruby on your computer; RubyInstaller is your best bet if running Windows.
  2. If you haven't yet, install the Sass Ruby gem: type gem install sass (sudo gem install sass and type admin password, if prompted, on a Mac) from the command prompt.
  3. From a command prompt, navigate to the directory ClassFiles/CSSBestPractices/Exercises/.
  4. Type the following command from the command prompt and hit enter: sass --watch style.scss:style.css. This tells Sass to watch file style.scss for changes and, for each change, to compile the results of style.scss into style.css. Note that:
    • Provided that you don't close the command-prompt window, Sass will continue watching for changes, compiling CSS from your Sass code each time you make a change.
    • Because the exercise file style.scss is unfinished (waiting for you to write some code), the compilation will fail until you fill in the missing code.
    • index.html references, through a standard link tag, style.css to get its styles - index.html doesn't know anything about our Sass file style.scss!
  5. Add values for the five Sass variables at the top of style.scss, values like #000, #F00, etc. Note that style rules below reference these variables' values.
  6. In the @for loop, use darken($bg_box_start, $i * 5) for the background-color style rule and lighten($color_box_start, $i * 25) for the color rule. Experiment with different starting colors (from the variables at top) and values for the second parameter ($i * 10 instead of $i * 5, say) to see how these changes affect the page.

Solution:

CssBestPractices/Solutions/style.scss
$bg_body: #CCC;
$bg_main: #FFF;
$bg_box_start: #F00;
$color_box_start: #000;
$border_color: #000;
$number_of_items: 4;

* {
	padding: 0;
	margin: 0;
}

body {
	background-color: $bg_body;
}

#main {
	width: 60%;
	padding: 2% 5%;
	margin: 20px auto;
	background-color: $bg_main;
}

h1 {
	margin-bottom:20px;
}

#main div {
	float: left;
	width: 41%;
	margin: 0 5% 20px 0;
	border: 1px solid $border_color;
	padding: 1%;
}

@for $i from 1 through $number-of-items {
	#main div:nth-of-type(#{$i}) {
		background-color: darken($bg_box_start, $i * 5);
		color: lighten($color_box_start, $i * 25);
	}
}

footer {
	clear:both;
}

ID the Body

Using an id attribute on the body provides a hook into the page for your CSS selectors. The id needs to be unique for that page, but different pages on your website can share the same id. For example, you might set the id to "products" for all the pages in the products section of your web site. You can then precede rules specific to your products pages with #products, like this:

#products h1 { /*declarations go here*/ }

Note that your h1 elements will still inherit all the other h1 properties set elsewhere unless you explicitly override them.

Some developers prefer to use the class attribute rather than the id attribute. You can do either or both.

Use CSS Shorthand

You should get used to using CSS shorthand. It will speed up your development time and make your pages download faster.

Combine CSS Rules

This is most easily explained with an example:

Don't do this:

ol {
	margin-left:10px;
	padding-left:10px;			
}
ul {
	margin-left:10px;	
	padding-left:10px;				
}

Do this instead:

ol, ul {
	margin-left:10px;
	padding-left:10px;					
}

It will download faster and it's easier to maintain.

Use a CSS Reset

We first discussed using CSS Resets in our Advanced CSS Page Layout lesson. We highly recommend this practice if you're using CSS at all heavily. It makes it much easier to create pages that work and look the same across browsers.

Use the "LoVe HAte" Rule

The "LoVe HAte" rule specifies the order you should use for rules affecting link pseudo-classes:

  1. :link - unvisited links
  2. :visited - visited links
  3. :hover - links over which the cursor hovers
  4. :active - links on which the user has clicked

This has to do with the specificity of the selectors and the fact that a link can be in multiple states simultaneously. Because all of these pseudo-classes have the same specificity, the rule that is defined last will take precedence. So, for example, if you define the :visited rule after the :active rule, then a link that is visited will never appear active.

Open CssBestPractices/Demos/LoVeHAte.html in your browser to see this in action. The code is shown below:

Code Sample:

CssBestPractices/Demos/LoVeHAte.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<style>
#working a:visited {
	text-decoration:underline;
	color:#f0f;
}
#working a:active {
	text-decoration:none;
	color:#f00;
}

#broken a:active {
	text-decoration:none;
	color:#f00;
}
#broken a:visited {
	text-decoration:underline;
	color:#f0f;
}
</style>
<title>The LoVe HAte Rule</title>
</head>
<body>
<p>After visiting the linked site, return to this page and click and hold each link. The first link will change color and style.  The second will not.</p>
<p>This is because, after the linked page has been visited, when the use clicks down, the link is both active and visited. Which ever rule is defined second will take precedence.</p>
<ol>
	<li id="working"><a href="http://www.cnn.com">CNN</a></li>
	<li id="broken"><a href="http://www.cnn.com">CNN</a></li>
</ol>
</body>
</html>

Use HTML Lists for Navigation Menus

Navigation menus present a list of options and should be structured as HTML lists. This is covered in detail in CSS Lists as Hierarchical Navigation.

Avoid CSS Hacks

If you look for solutions to problems you are having getting your pages to appear the same in different browsers, you're very likely to come upon many "CSS hacks". These are tricks that take advantage of browser bugs to get them to behave the way you want them to. One problem with using CSS hacks is that it is often unclear how the code will affect new browsers, future versions of existing browsers, or other devices that view web pages. Another problem is that these hacks can add a lot of complexity to your code, which runs counter to one of the main benefits of CSS - code simplification.

It doesn't take new CSS developers too long to discover that early versions of Internet Explorer are the most problematic of browsers. The most current versions of IE are some of the best at rendering to strict standards but versions 7 and below have some quirks. Microsoft introduced conditional comments with IE5 and they work great.. We recommend you use them instead of CSS hacks. In fact, you might want to have a special style sheet devoted to Internet Explorer's quirkiness and use a conditional comment to load it.

Use a CSS Compressor

A CSS compressor is a program that minimizes a CSS style sheet by removing all extra white space. It may also do additional things to make the style sheet smaller. The purpose of a CSS compressor is to make the file size smaller so that it downloads more quickly. You should use one to compress your style sheets. There are many available for free on the web.

There is a simple web-based CSS compressor at http://www.cssdrive.com/index.php/main/csscompressor.

Here is another excellent free compressor at http://csscompressor.com/.

Use a Master Style Sheet

This is one we don't feel so strongly about, but a lot of people recommend it so we thought we should give it a nod. Proponents suggest that a master style sheet helps to organize your code. An example is shown below:

@import url("reset.css");
@import url("general.css");
@import url("formatting.css");
@import url("layout.css");

We don't have anything much against using this, but we don't see that it adds much benefit either. Storing the style sheets in a single folder gives you a similar gain. Using a master style sheet also makes an additional download necessary. Might it be better to call the pages directly from the HTML page?

Summary of Best Practices

Below is a table summarizing the practices discussed in this lesson. The right-most column contains a number between 1 and 3.

  1. A 1 means we think you should absolutely follow this practice.
  2. A 2 means we think it makes a lot of sense to follow this practice, but recognize that there might be some reasons not to.
  3. A 3 means we think you should consider it, but don't consider it mandatory.
Summary of CSS Best Practices
Best Practice Benefits *
Use CSS
  • Cleaner code
  • Faster development
  • Speedier download
  • Greater control
1
Use External Style Sheets
  • Cleaner code
  • Faster development
  • Speedier download
1
ID the Body
  • Greater control
2
Use CSS Shorthand
  • Speedier download
  • Cleaner code
  • Faster development
2
Combine Rules
  • Speedier download
  • Cleaner code
2
Use a CSS Reset
  • Greater control
  • Cleaner code
  • Faster development
1.2
Use HTML Lists for Navigation Menus
  • Accessibility
1
Avoid CSS Hacks
  • Cleaner code
  • Faster development
2
Use a CSS Compressor
  • Speedier download
2
Use a Master Style Sheet
  • Cleaner code
3