These days, CSS development is a complex process. You may be working on sites with large CSS files, multiple developers ,and long development timelines. The more complex your CSS files become, the more difficult it is to work with them. This article will present some tips and tricks for keeping your CSS files organized and easy to work with.
Things to keep in mind
Always remember that:
You may not be the only one who needs to work with this code. You may
decide to distribute your Wordpress theme in the future. You may leave
your job. You may pass the site on to another developer. Someone else
needs to be able to work with your code.
Everyone has their own preferences. That doesn’t mean that we can’t all
follow some simple processes to make our code easier to work with.
Keeping your CSS organized
Note: the tips listed below are listed roughly in order
of difficulty. Basic techniques are described first.
Avoid using inline CSS or in-page CSS
CSS can be applied to elements in three different ways:
inline (<p style="margin-left: 20px;")
on page (<style> block inside the page
<head>)
imported using @import or
Using imported CSS is the best way of keeping your CSS separate
and easily maintainable. Only use inline CSS if you have no other choice,
or it is a truly one-off situation that won’t be used elsewhere. On
page CSS should only be used for properties that only apply to the
current page. Even then, if there is a lot of CSS it’s best to create a
new .css file and import it.
Use classes and id’s where appropriate
Remember the difference between a class and an id. An id is to be used
only once on a page. If something occurs once and only once on a page, use an
id. If it occurs multiple times, use a class. Also consider future changes to
the site — ask yourself: is there any chance that I would want to repeat this style on
the page? If the answer is yes or maybe, use a class.
Use a consistent style
You may choose to write your CSS inline, like this:
p {font-size: 10px; margin-bottom: 1em;}
Or in block format, like this:
p {
font-size: 10px;
margin-bottom: 1em;
}
There are several variations of the block format, depending on where you
put the opening { and whether the properties are indented or not. This is
largely a matter of personal preference; some developers find that the
inline method makes it easier to find selectors, while others find that the
block method makes it easier to find properties. Choose a format and stick to
it throughout your CSS file.
If you encounter a CSS file that uses a different format from the one you
prefer to use, you can use a CSS formatting tool
to reformat it to suit your needs.
Don’t specify the same selector more than once
Poor organization or laziness may result in some selectors being specified
more than once. For example, you may specify some properties for lists at the
top of your stylesheet, then decide later on to add some additional
properties. These new properties may get added in a new block at the bottom
of the CSS file, rather than with the original selector earlier on.
Before adding a selector — particularly a generic element selector —
make sure to check through you CSS first to make sure it hasn’t already been
used.
Use lower case selectors only
Selectors are case sensitive, meaning that #Content is not
the same as #content. In order to avoid mistakes, it’s best to
always specify selectors in lower case. It’s also helpful to be consistent
about other characters used in your selectors, e.g. use only underscores or
dashes, not both.
Use standard conventions for common ids
Web designers have come to an informal consensus about how to name certain
elements. The header is called #header, the footer is called
#footer, and the main menu is #nav or #navbar. There is
some variation about container elements (#container,
#wrapper etc.). It’s best to follow what others are doing, rather than inventing your own names. Sticking to conventions means other developers
will be able to understand your code.
Use meaningful selector names
Whenever possible you should choose semantic (or meaningful), names for your selectors. Other developers should be able to tell by reading your CSS what the selectors are for.
In addition, class names should be able to account for changes in design. For example, if you decide to change that red text to orange, you shouldn’t have to change the name of the class as well. Instead, think about why that text is red. Is it because it’s important? Good, then call it .important.
The only time when you would use presentational names is when there really is no logical reason why this element is styled the way it is. For example, if you have a class that aligns a photo to the left, there is no more meaningful way to label it than .photo-left (or .imgleft, or .figure-left, or whatever you prefer).
This is also a matter of balancing meaningfulness with clarity. There may be a tendency to get too strict about semantics, to the point where people don’t understand your code anymore. For example, the id "footer" really describes the location on the page. To be more semantic, you could call this "site-meta" or something like that. However, in reality "footer" is a much clearer label.
Use shorthand wherever possible
Instead of:
ul {
margin-left: 20px;
margin-top: 10px;
margin-bottom: 10px;
}
use:
ul {
margin: 10px 0 10px 20px;
}
For margins and padding, the order is always top, right, bottom, left. You
can further this shorthand by dropping the bottom and left values if they are
the same as top and right. For example:
Personally, I like to sort things by purpose (see how height and width
aren’t placed together in the above example?). Colours and backgrounds go
together (color, background color, background image), box model properties go
together (height, width, margin, padding, position etc.), text properties go
together (font, text-align, line-height etc.). It might look like this:
A CSS reset declaration overrides all of the browser’s default settings.
All browsers come with default stylesheets that control how basic elements
look. Paragraphs have margins. Unordered lists have round bullets and a left
margin.
Usually, designers will want to override most of these values. Instead of
individually overriding every setting you want to change, it’s often best to
just wipe the slate clean and start over.
Eric Meyer has developed a good CSS reset that you can copy and paste into your CSS file.
Divide your CSS file into sections for particular tasks
Useful common classes
There are several common classes that I usually like to include in my
stylesheets. They include:
.important
.fineprint
.photo (or .thumb)
.photo-left
.photo-right
.caption
.update and/or .correction (for a blog)
Arranging selectors into groups for different purposes helps to keep
things together. For example, it wouldn’t make sense if the ul
selector was on line 25 while the li selector was on line 164.
Keeping them together will ensure that you see related selectors and ensure
that you don’t accidentally call a selector more than once.
This is how I like to do mine:
CSS Reset
Basic elements (body, paragraphs, lists etc.)
Commonly used classes (these are things that I might need to reference
frequently, such as classes that align images to the left or right)
Specific selectors for certain parts of pages (e.g. A special section
of one page that creates a block around some text and an image)
Template layout:
containers
header
navigation
content
footer
Inside these groups, similar items are grouped together as well. For
example, all list related selectors would be put together in section #2.
Higher level selectors go first, so ul would precede
li.
The reason I organize it in this way is mainly to support the CSS cascade
but also for accessibility. The CSS reset and basic elements need to go first
so they can be overridden later by more specific selectors. After that, I need
to find those common classes and elements more frequently, while the template
layout rarely changes.
Add a header for each section
Many developers have a favourite way of marking sections in their CSS,
such as:
/* ------------ common classes ------------ */
/*======= common classes ====== */
/* ----------------------------------------- common classes */
This makes it easy to find elements you need to work on. The style you
choose for these headings is up to you, just be consistent about which format
you use.
Include a colour reference
How many times have you gone hunting for the correct hex value for the
colours used in your design? Specifying the colours at the top make them easy
to access. All you need to do is scroll to the top and copy and paste. It
might look like this:
/*
Main medium green: #d7ecaa
Lighter green: #f1fcdb
Very light green: #e8f7c4
Medium brown: #a66c38
Lighter brown: #632f00
*/
Otherwise, use comments only when necessary
If you write your CSS well there should be little need to explain what
you’re doing. Any designer who understands CSS will understand how and why
you’ve used certain properties. Extra comments clutter the stylesheet and
increase the file size. The only exception to this would be cases where
something you’ve done really doesn’t make sense. For example, you had to
include an extra property to correct a display problem in a particular
browser.
Consider dividing your CSS into separate files
If you have very large CSS files, it might be worthwhile to separate it
into two or more different files. This way you can use different files for
particular tasks. I often separate the template layout into a different file
since it doesn’t change very much after the initial site launch. The CSS
reset could also go into a separate file. In addition, you could create
separate files for large sections of CSS used only on certain pages,
such as forms. This way all pages won’t be loading code that is only used on
a few pages.
Your list of CSS files might look like this:
reset.css
content.css
layout.css
forms.css
Ensure @import declarations are written in the correct order, so that they cascade correctly.
Avoid using browser specific hacks
There are many ways to target particular browsers with CSS
(see Web Devout for some examples). These usually involve
exploiting bugs in a browser’s rendering engine which cause it to ignore
certain selectors or groups of characters.
The first problem is these hacks are not usually documented very
well. Months or years later you may not remember why that voice-family
property was there. Secondly, future versions of the browser
being targeted may correct the very problem you are exploiting. This is fine
if they have also corrected the bug, but what if they haven’t?
If you learn to write CSS well there shouldn’t be much of a need for
hacks. I find that there’s usually a good method of solving the problem for
standards-compliant browsers. However, Internet Explorer is often an
exception.
Target IE using conditional comments
Internet Explorer’s conditional comments make it easy to add code that can
only been seen by IE. Not only that, but you can target specific versions or
ranges of versions, anything less than IE 6 for example.
There are two ways to serve different CSS to IE using
conditional comments. The first is to simply insert a different CSS file for
IE:
However, some designers believe that this is a problem because it
separates the IE-only CSS from the rest. When making a change to the
regular stylesheet you may not realize that the same element is also adjusted
in the IE-only stylesheet. Instead, you could add a containing DIV around
your page with an IE-only id.
After the body tag put:
<!--[if IE]>
<div id=”ieroot”>
<![endif]-->
And don’t forget to close it at the bottom:
<!--[if IE]>
</div>
<![endif]-->
Using this technique, you simply use your #IERoot selector in
your regular CSS file to add extra rules for IE only. This way you can keep
the special IE-only CSS together with the main CSS for that selector.
Remember: any code targeted to IE only should
only be used when the fix breaks the layout in other browsers.
Otherwise, there’s nothing wrong with including a few extra properties if
they have no effect on other browsers.
In CSS, more specific selectors will override more general selectors.
Let’s say we want to add some padding to list items. We could do it like
this:
div#wrapper ul li {
padding: 4px 0;
}
If #wrapper is a containing div for the whole page, all lists
will have 4px top and bottom padding. Now, what if I wanted lists inside the
#content div to have less padding. I would have to do something
like this:
div#content ul li {
padding: 2px 0;
}
You can see how this leads to more and more complex selectors over time.
The more selectors you add, the more you need to include to override those
properties later on. In order to avoid this problem it’s best to minimize the
specificity of your selectors (use as few selectors as possible). Instead of
the above I could have simply done this:
li {
padding: 4px 0;
}
#content li {
padding: 2px 0;
}
You don’t have to put a class or id on every element you want to style
differently. Instead, learn about all the different CSS selectors available
to you. You could, for example, create a navigation menu like this:
The main problem with this is that you end up with a lot of extra classes
in your html that really don’t need to be there. Instead, you could simply
use descendent selectors to apply some CSS to the list items inside the
navbar div. While we’re at it, we don’t really need that div either. Instead,
we can apply the id to the ul instead:
Remember that not all selectors are supported in all browsers. Check this
handy reference chart to make
sure the selectors you want to use are supported in most browsers. Less
supported selectors can also be used in combination with the progressive
enhancement techniques described below.
Consider progressive enhancement
With progressive enhancement you can take advantage of newer standards
while still presenting an attractive and usable interface to older browsers.
Newer CSS properties and selectors are used for optional design elements,
such as creating rounded corners.
Instead of creating multple nested divs with background images to create
rounded corners, you could simply use the -moz-border-radius and
-webkit-border-radius properties to create rounded corners in
Firefox (using the mozilla/gecko rendering engine) and Safari (using the
webkit rendering engine):
With techniques like this you can create additional effects and take
advantage of new CSS without writing a lot of extra code or degrading the
experience in older browsers. That’s why it’s called progressive
enhancement!
Redundancy or Dependency?
If you’ve been writing CSS for awhile you’ve probably come across this
problem. It’s normal to have a lot of elements with similar propertes. After
all, visual consistency is one of the keys to a good design. The problem is
that you may end up writing that same set of properties repeatedly throughout
your CSS.
An alternative would be to break out these common groups into their own
classes or use grouped selectors to apply a generic set of properties. This
class would then be applied to any elements that require them. But wait –
what if you want to modify one of the properties applied to one of these
elements? Now you need to add a more specific selector to get the element you
need.
If you continue following this method you may end up with a lot of
selectors applying CSS to the same element. Changing one property may have
unforseen consequences to other parts of the design.
Wouldn’t it be easier to separate the CSS properties for each selector?
But now we’re back to where we were in the beginning, rewriting the same CSS
multiple times.
This, again, is a matter of personal preference. Experiment with both
methods and see which one works best for you. Redundancy often works fine for smaller projects while larger, more complex projects benefit from the dependency approach.
Megan is co-founder and editor of A Padded Cell and administrator at The Webmaster Forums. She has been designing websites since 1997, with expertise in design, information architecture, usability, HTML/CSS, Drupal theming, and more. Megan is also a partner and co-founder of Woolwich Web Works: A small team that can do big things!