CSS tips and tricks, Part 2

This is the followup to last week’s post, CSS tips and tricks, Part 1, where you can find tips on shorthand, default values, colours, inheritance, cascading, and more.

In this part I’ll be giving you some tips on grouping selectors, clearing floats, horizontal centring, importing CSS, and a couple of troubleshooting tips. If you think something is missing, check part one in case it’s been covered there.

Group selectors

When several element types, classes, or id:s share some properties, you can group the selectors to avoid specifying the same properties several times. This will save space – potentially lots of it. Whether you put each selector on the same line or separate them with a line break is mostly a matter of personal taste.

So, to specify the font family, colour, and margins for all heading elements, you can do the following:

h1,h2,h3,h4,h5,h6 {

font-family:"Lucida Grande",Lucida,Arial,Helvetica,sans-serif;

color:#333;

margin:1em 0;

}

Compared to setting the properties individually for each element type this saves a great deal of space. The savings are obviously greater the more properties that are the same.

You can then separately specify any properties that are different for some of those elements, for example font-size:

h1 { font-size:2em; }

h2 { font-size:1.6em; }

Specify link styles in the right order

When applying CSS to the different states of a link you need to think about the order of the rules. In most cases you’ll want to specify them in the order :link :visited :hover :active. Take the initial letter for each state and you get “LVHA”, which can be expanded to “LoVe HAte” or something else that is easy to remember. The order is affected by specificity, and is explained well by Eric Meyer in Link Specificity.

You may also want to think about specifying the :focus state to make it easier for those who navigate with the keyboard to see which link is currently selected. Where you place the :focus rule depends on what you want to happen. If you want elements that have focus to display the :hover effect you have specified, place it before :hover. If you want the :focus effect to override the :hover effect, place it after : hover.

Clearing floats

A very common CSS problem is how to handle the situation that occurs when you have a floated object in a container and do not want that object to stick out of the bottom of the container. A typical example is floating a tall image within the main body text. If there is not enough text to cover the entire height of the image, the image will extend out of the box it is in. Sometimes that is what you actually want, sometimes it isn’t.

The traditional way of controlling this has been to add an extra element, either a div or a br element, inside the element that you want to contain any floated descendants and style it to clear:both. Adding extra markup is a bit ugly, but luckily there is a method that eliminates the need for that: How To Clear Floats Without Structural Markup.

Both of these methods work very well unless you have a layout that involves floats that appear earlier in the markup than the object you actually want to clear. That’s where a trick that hasn’t been widely known until recently looks like it will come in very handy for controlling floats within page content: using the overflow property, originally described in Simple Clearing of Floats. The method is also analysed and discussed in Clearance and Super simple clearing floats, among other places.

Which of these clearing methods to use depends on the circumstances. Read up on them, experiment, then decide.

Centring (centering)

A simple trick, but worth repeating since this is something I see many CSS beginners having problems with. To horizontally centre an element with CSS, you need to specify the element’s width and horizontal margins. If your entire layout is wrapped in a container like this:

<div id="wrap">

<!-- Your layout goes here -->

</div>

you can centre it horizontally by using the following CSS:

#wrap {

width:760px; /* Change this to the width of your layout */

margin:0 auto;

}

The width of #wrap is subtracted from the available window width and the difference is equally split between the left and right margins. The width doesn’t have to be fixed – you can use any unit you like for the width.

IE5/Win does not understand this, but it has a useful bug that makes it apply the text-align property to block level elements. If you need the layout to be centred in that browser, use this CSS instead of the above:

body {

text-align:center;

}

#wrap {

width:760px; /* Change this to the width of your layout */

margin:0 auto;

text-align:left;

}

The first rule makes IE5/Win centre everything in the body element. Other browsers will centre just the text, and since the text-align property is inherited, all text in the document will be centred. You rarely want that, so the next rule overrides that by left aligning all text withing the #wrap element.

Obviously this technique can be used to horizontally centre any block level element within another.

Oh, if IE5/Win support is not required, you don’t need the #wrap element for centring the layout. You can style the body element instead. Just be aware that it doesn’t work in IE5/Win.

Importing and hiding CSS

A common way of hiding CSS files from old browsers is to use the @import trick. However, the way I see it used most often does not hide the CSS from Internet Explorer 4:

@import url("main.css");

This had me scratching my head for a while. I’d read somewhere that using @import would hide the CSS from the old browsers, but when I checked the result in IE4 it imported the CSS file, with horrible results. Instead, I use the following syntax for @import:

@import "main.css";

That stops Internet Explorer 4 from importing the file. As an extra bonus, it saves a couple of bytes. For an overview of how the syntax used in the @import rule will affect which browsers will import the stylesheet, see centricle’s css filter chart.

Giving Internet Explorer what it needs

Sometimes (read: most of the time) you need to send different rules to Internet Explorer to work around bugs in its, shall we say, less-than-perfect CSS implementation.

There are many CSS hacks that do this, but I tend to use just a couple of them, and only when I can’t find a better, hack-free way to accomplish what I want. With Microsoft’s recent announcement of an upcoming beta release of IE7 for Windows, which may or may not include better support for CSS, and may or may not change the way CSS hacks work, I think the safest way of taking care of IE/Win is to use conditional comments – more on that below.

Another option – and I tend to use this more and more since it feels more future-proof than CSS hacks – is to use Microsoft’s proprietary conditional comments. You can use this to give IE/Win a separate stylesheet that contains all the rules that are needed to make it behave properly. I think it’s a good way of keeping the hacks and noise out of the main CSS file. You also avoid invalidating the “real” CSS file with proprietary IE extensions to CSS, like expressions, that are sometimes needed.

<!--[if IE]>

<link rel="stylesheet" type="text/css" href="ie.css" />

<![endif]-->

This has the additional benefit of preventing the Flash of Unstyled Content which can occur in IE/Win if there are no link or script elements in the document’s head element.

How big is that box?

When something goes wrong, start by validating your CSS. Anybody can make a typo.

If there are no errors in the CSS you need to start analysing what’s going on. I like applying background colours to the elements I’m having trouble with to clearly see the space they occupy. Some people suggest using borders, which is fine in many cases. The problem with that approach is that borders will increase an element’s dimensions, and top and bottom borders will prevent vertical margins from collapsing. Background colours are generally safer.

Another potential troubleshooting property is outline. Outlines look like borders, but don’t affect the dimensions or positioning of the element they are applied to or that of any other elements. The downside is that very few browsers currently support the outline property – as far as I know it’s only supported by Safari, OmniWeb, and Opera.

CSS coding style

There are many different approaches to the use of indenting, line breaks and whitespace when writing CSS. I’ve been going a bit back-and-forth on that, but I I’ve settled for the following coding style (for now, anyway):

selector1,

selector2 {

property:value;

}

When I combine selectors, I normally put them on separate lines. I find it easier to find things in the CSS file that way. Next, I leave a space between the end of the last selector and the opening brace. Each declaration goes on a separate line, with no indentation and no spaces around the colons separating properties from values.

I always end each declaration with a semicolon. Doing so isn’t necessary for the last declaration in a rule, but it’s really easy to forget adding a semicolon before adding a declaration, and that will introduce hard-to-find problems in your CSS.

Finally, the closing brace goes on a line of its own.

Yes, whitespace can be good for readability, but I like to keep it as minimal as possible without negatively affecting readability too much.

Of course, there are exceptions to these rules, and I’m not always fully consistent with my CSS formatting. We all have room for improvement, and I’m working on it, OK.

There’s more where that came from

In these two articles I’ve covered some of the tricks I use when writing and troubleshooting CSS. There are more, so who knows, maybe there will be a part 3 some day. Did I leave out something important, like your favourite tip or trick? Let me know.

Comments

What might be the problems with definding the body of a page with a width, centering the text within the body and defineing the left and right margins with auto instead of using a wrapper div? I’ve done a few sites like this and see it working in Opera, Firefox, IE6, Mozilla, Camino, Safari, OmniWeb etc…

Chris: That would cause problems for of our old friend IE5/Win, which doesn’t allow styling of the body element. If you can live with that you don’t need the wrapper div just for centring. I’ll add a clarification about that.

You didn’t tell me anything I didn’t already know, but I’m thanking you for the concise dictionary on the hacks. I know about all those hacks, but I always forget and have to look up which hack to use to hide from which browser. :-)

The Holly Hack is definitely one I, unfortunately, use quite often. Even the strangest bug in IE — one that makes a block element ‘walk’ down a page which each hovering over a link — is solved when the Holly Hack is carefully applied.

I haven’t tested this extensively, since I only really worry about supporting IE6 and Gecko. But it’s been very useful to me at times. Unlike most hacks, it depends on Firefox/Moz/etc breaking the standard, and IE following them. Using C-style one line comments (//) will cause a line to be ignored by Gecko, but IE will still process it.

I most recently used this building a forms-based web app. IE has spectacularly ugly legend rendering, so I used this line in the stylesheet:
// legend {display:none}

The // syntax is C++ (not C), and it’s not a valid comment style in CSS. With invalid CSS, anything can happen. I wouldn’t say that Mozilla (nor IE in this case) is doing anything wrong, because it’s not valid CSS to begin with.

Thanks so much for both parts - I maintain a CSS/Design mailing list and forwarded the link to much positive response.

I have two questions, though:

Regarding centering, you said: “Oh, if IE5/Win support is not required, you don’t need the #wrap element for centring the layout. You can style the body element instead.” Can you clarify? I tried applying “margin: 0 auto” to the body selector instead of my content div, instead, and found that it no longer centered properly.

Are you (or anyone) aware of a IE/Win repeating background-image rendering bug? I’ve got this white line under a footer img and can’t for the life of me figure out why. Screenshot below, and code available for any kind souls interested to help out:

Roger: Sure enough, stating an explicit width did the trick. Good to know, thanks!

Regarding the bug, I don’t know if anyone else has had this happen, but apparently IE flips out with a bare img used as a footer, so I resorted to replacing it as a background image in a div a la FIR headings, and it worked. If I can reproduce it, I’ll report it.

Thank you for a terrific article. I’m getting ready to attempt my first CSS design and this couldn’t have come at a better time. I printed out both parts and stuck them prominently in my already raggedy copy of CSS by Meyer, which never leaves my side these days. You’ve made me a little less nervous.

On certain sites that are written in CSS, I often find that when the browser is not maximised to full screen a lot of the content disappears. In order to view the full content the user either has to scroll across using the horizontal scrollbar or maximise the page. Personally I find this tiresome.

I think this is due to element widths being specified in px or em by the author so that their content stays as intended no matter what browser or screen resolution used etc.

There’s nothing wrong with that at all, but, first impressions count for a lot on whether your visitor is going to spend their time looking around your site.

I have found that if the element widths and positions are specified using %, then everything displayed is then relative to the window size of the browser used. It is no where near perfect as everyting tends to squash up if the window is very small, but on general I find this is a good presentation method.

[Another “benefit” of this approach is that if a large image is placed in the element, it is also resized relative to the window, although the aspect ratio of the image itself can be thrown out if the window is sized more “portrait” than “landscape”.]

It’s probably not a major thing, (and i could be wrong lol) but with your centering technique (as described when just applying this technique to latest gen browsers) you have :

body {

width:760px; /* Change this to the width of your layout */
margin:0 auto;
}
which works .. but if you are ever in an instance where for some reason you then need to use a wrapper that has a position of absolute…for example:

wrap

{
position: absolute;
background-color: #06C;
width: auto;
}

IE 6 (and maybe 5x) won’t redraw the screen as you resize the window. Forcing you to refresh to see the div and it’s contents new actual position.

besides all that, it sure is hard to make those combo selectors work (in many experiments, Firefox doesn’t react to much and Opera changes layouts on 1st and 2nd reload :-) )

also, regarding background-color as diagnostic; i use an external css for diagnostic. this

<link title=".." rel="stylesheet" href="..." type="text/css" />

is easily commented in or out. but background colors don’t show behind images. i also use opacity or :hover (firefox/moz)

[if IE] has been inconsistent for me, sometimes acting in reverse! (i.e., IE obeys the “exposed” style) Also the ff/opera style should precede [if IE] else they can’t see the stuff that follows [if IE]