Lean XHTML and Precise CSS
Monday, December 5th, 2005 by Mike Rundle
Paul often tells me the CSS I write tends to look like complicated C code, and for the most part, I’d agree. The stylesheets I usually produce rely almost exclusively on descendant selectors which let me pinpoint <div>’s, headings, and other tags in a very precise manner for styling. In this entry I’ll talk about my theories behind XHTML and CSS code, practices I feel are better than others, and my thoughts on image replacement.
CSS Examples & Structure
Check out the Business Logs CSS file million.css, the Gigaom.com style.css, or the 9rules.com homepage stylesheet gameover.css.
One thing you’ll notice off the bat is the way I organize my stylesheets — I normally group styles by what they apply to rather than where they apply it visually. For example, at the top of my stylesheets I keep all structural elements together in a catch-all titled “Body and Box-like elements” which usually holds IDs that I reserve for structural elements since they appear only once on the page. Rules like #frame, #sidebar, and #footer will go here. Under those are all my heading styles (H1-H6), then all paragraph styles, then link styles, lists (including navigation), and so on. Compare this to how my friend Dan writes his style sheets; he normally groups styles by where the style is going (top section styles, sidebar styles, content styles, footer styles) rather than the type of style it is. Neither style of coding is “the right way”, they’re just two different ways of looking at a site’s design and structure. I personally think that the reason I write mine that way is because of all my experience with real programming (Java, C, PHP, Perl) so my way of organizing CSS files just seems more logical in my brain. Who knows.
I’ve been writing CSS commercially now for a shade under three years, and once you have a few thousand lines of CSS under your belt you tend to develop patterns that make it easier and faster to get work done. One of the patterns that I use that helps me immensely is the indentation of CSS rules based on their parent/child relationship. Here’s an example from the 9rules CSS:
#frontpageads ul {
display: block;
margin: 24px 0 16px 0;
_margin-top: 12px; /* Double margin bug, IE6 */
padding: 0;
list-style: none; }
#frontpageads ul li {
height: 75px;
margin: 0 16px 8px 8px;
padding: 0; }
#frontpageads ul li a {
border: 0 !important; }
See the pattern? The #frontpageads ul rule is the parent and start of the unordered list style, then the child element is the #frontpageads ul li which is next (indented one level), and then the #frontpageads ul li a style is last which is the child of the list item. The indenting of child rules helps set up a visual hierarchy which is really handy when you’re dealing with 1000-line CSS files since they can get unruly pretty quickly. On a normal site, I might have numerous navigation or list styles: one for the top navigation, one for a secondary nav, a sidebar list (say, categories on a weblog), and then a normal list style for content. That’s four different unordered list styles, all with the same ul -› li -› a code progression needed to style all parts of the list. The indenting is really handy because I can identify each list style block visually without having to look closer at the name of the rule. This helps me jump directly to a code block without having to waste time to see where one block starts and another begins.
Make Your XHTML Lean
The very first thing I do after I have the visual design of a page mocked up (in Photoshop, OmniGraffle, etc.) is jump into the XHTML. I have the visual design open in one part of the screen, and TextMate open in another so I can look at the design while I write the most semantic XHTML I can muster. I always write the XHTML/CSS for my own designs because I can just look at it and see the XHTML/CSS in my head. I can see how the structure will be laid out, which areas will be blocked off, how navigation will be coded, etc. A few weeks back my girlfriend said that in the middle of the night I was talking in my sleep, saying things like “H5 and H6!” after a long day of CSS coding, I mean how lame can ya get :)
One of the hallmarks of CSS-based design, to me, is the separation of design from content. In my HTML files you will never, ever find an <image> tag that links to something that is used for the design of the page rather than the actual content. Images that build the design structure of the page are meant to be contained in the CSS file as background-images, not as images in the HTML itself. If you keep all the design in the CSS file and all the structural markup and content in the HTML, the project will be much better off and Jeffrey Zeldman will smile down upon you.
In order to have background-images as design elements in your CSS, you’ll probably need to use some form of image replacement. Image replacement, for those who aren’t accustomed to the term, is the method that moves the text that would normally show up in an element’s display out of the way so that element’s background-image can show through. The advantage is that you can use regular HTML tags like H1 to give semantic meaning to things like logos, where before you would just drop an HTML image tag in there and call it a day. By still using the H1 for the logo, you are giving meaning to the ordinarily meaningless image, and you can keep all the design in the CSS and not muddy up your HTML with image tags.
A few years ago I wrote about the technique I used for image replacement by way of a negative text-indent (which instead of indenting it to the right, it indents it way off screen so it’s not visible any more.) This technique is the one I use every single day, and I’ll go ahead and recommend it to newer CSS coders because it’s very simple to implement and doesn’t require extraneous HTML tags to function. I won’t get into the details of it here, but if you jump over to the 9rules CSS or Om’s CSS, and do a find for “text-indent” you can check out the code in action. Many other designers use this technique as well (Doug Bowman rocks it) so it’s not just me saying this because I’m biased :)
Round Up
These are just a few of the CSS tips I have, and I’m sure our readers have a bunch more, so feel free to share them.
Reader Comments
36 Responses to “Lean XHTML and Precise CSS”
I’ve loved using the Phark image replacement method ever since I discovered it. So simple and yet beautifully consistent across the browsers.
I tend to use a lot of CSS selectors in each rule to the point where it’s almost unreadable… on the flip side it keeps the number of classes and ids down to a minimum.
One issue with having a lot of selectors in one rule is that IE tends to ignore some of the selectors and applies the rule anyway. So I guess that’s Microsoft’s way of telling you that it’s sometimes ok to create a new class/id.
December 6th, 2005 at 1:11 am
I organize by order of appearance in the XHTML, and then alphabetically. Y’all can have a look if you want, just don’t steal…
SonSpring.com CSS
December 6th, 2005 at 2:55 am
I seperate my styles in a similar fashion, first placing all general tag-centric styles (i.e. a{color: #123456;}), then adding all general class and ID tags and descendant selectors related to the parent tags.
Recently I’ve started importing common CSS files into other CSS files by using the @import url(myfile.css); command at the top of the external CSS document. This is useful for like styles that need to be used on several style sheets where you do not want to replicate information. For example, a screen and a print stylesheet that both have common styles could both import a common third stylesheet for the content, etc.
I find this method useful when working with other developers in a templating environment where they do not need to know what specific CSS files I am importing. However, when doing this, I strongly recommend good commenting and clearly named files. I also recommend *not* nesting more than one level deep.
December 6th, 2005 at 9:44 am
Its great to see how you code css, but do you tend to layout your html with alot of divs or do you try to keep it lean and just code with more semantic block elements?
By the way, nice article. Its great to get some insight on another coder’s technique.
December 6th, 2005 at 10:13 am
Great recommendations, Mike. I haven’t tried the image replacement yet, despite the fact that I’ve known about it for probably 3 months (about as long as I’ve been doing all this). I’ve always felt like it was a “why” issue, but after seeing it again and again (from designers whom I respect), I think it’s probably time to give it a try. Thanks for the tips!
December 6th, 2005 at 11:08 am
I do my XHTML Page and create CSS File in the same way like you. At first the structure with Eclipse, than the Styles with TopStyle and finally the finetuning ;o) By the way Mike, nice article!
December 6th, 2005 at 11:32 am
Frankly, I found this page to be horribly layed out and only readable when I’d used FireFox’s ‘View -> Page Style -> No Style’ enabled. I’m not sure that it says much about your CSS coding abilities when the body of the text takes up 25% of the width of the page surrounded by acres of whitespace when it fit neatly onto 1 page by ignoring your CSS.
I do have to congratulate you on your ordering of items in the XHTML, though; the important stuff is at the top, and all the crap is at the bottom.
December 6th, 2005 at 11:51 am
A man after my own heart!
I’ve never looked at indenting my styles in quite the same way you have. It’s interesting and makes scanning the css much easier. I’ll be using it from here on out, thanks!
December 6th, 2005 at 11:53 am
Which page Alex? This page?
The main content is 400px wide, and the content of the entire width of the page is only about 760px so I’m a bit confused about why you would say it’s only 25%. The reason that the entire width of the page is only 760px across is so it fits neatly into an 800×600 resolution, which is the normal resolution for projectors at conferences. This site, BusinessLogs.com, gets shown at conferences fairly often, and I tried to make a site that doesn’t look bad when shown in a smaller browser window.
The reason there is a lot of whitespace on the left of this entry is because the sidebar isn’t very long on purpose. A lot of our designs tend to be very graphically heavy and detailed, and I wanted our company site to be a nice change of pace.
Thanks for the feedback though, I do appreciate it.
December 6th, 2005 at 11:59 am
Hey Carlos-
I really try to make an effort to only use div’s for laying out the main structure of a page, and then using headings H1-H6 and other semantic tags like paragraphs and list styles after that. I have this thing about tight XHTML that forces me to leave out the fluff ;)
December 6th, 2005 at 12:02 pm
Wow, what a smack in the forehead moment. I indent everything, but I’ve never indented my CSS. I’ll have to start remembering to do that.
I’d have to argue that a logo is not necessarily presentational. If the logo is just text then it’d be fine. But I think I’d rather use an image with alt text. Though that’s more a personal preference, you could just as easily have the same text pushed off screen with a replacement as you included in the alt text.
December 6th, 2005 at 12:11 pm
Hey Jacob-
One of the reasons why I probably drop the logos into the CSS is that normally my design has the logo integrated into the rest of the header in a semi-complicated way (see 9rules) so it’s just a tad easier for me to put it in the CSS. I don’t think I’ve ever worked on a project where the logo was just kinda dropped in a white background or something, so that’s probably the reason I’m biased haha.
December 6th, 2005 at 12:14 pm
I second what Mike said about styling H1, P, etc. That definitely helps you avoid span and class-itis. Plus, based on the Div that the H1 or P is in, you can use descendant selection, like Mike pointed out, to have really tight control over presentation, while keeping (X)HTML to a bare minimum.
December 6th, 2005 at 12:30 pm
I particularly like how you order your CSS styles. For the most part, I order it according to appearance in the XHTML. Unfortunately, this method breaks down when, say, styling for a webapp where different pages serve up totally different types of content.
I’ve also been indenting my styles for several months now - and it has made a huge difference in readability.
December 7th, 2005 at 10:30 am
Hey Mike,
Nice article. I agree with a previous comment about indenting the CSS being a “smack me in the forehead” moment - I’ve never even considered it, or seen it done. Thanks for opening my eyes to a new method.
One thing you didn’t mention was what sort of tool you use to author your CSS - I’m just curious. Do you prefer any specific tool over any other, or just a basic text editor?
December 9th, 2005 at 9:48 am
I am sure getting caught by your girlfriend saying things like h5-h6 in your sleep is much better than getting caught saying something else :)
Great article Mike. I tend to form my css like your friend Dan, but I like your way better. It makes MUCH more sense, especially when there is a LOT of code. Good call.
December 10th, 2005 at 1:45 pm
A few weeks back my girlfriend said that in the middle of the night I was talking in my sleep, saying things like “H5 and H6!” after a long day of CSS coding, I mean how lame can ya get :)
That reminds me of when I regularly used to code 90K+ HTML pages in Notepad that were full of nested tables (ergh!). Eating in a restaurant one night after work, a waiter said to me:
“I’m afraid there’s a problem with your table, sir.”
“Check both the and tags are closed properly,” I said, without even thinking. The look of confusion on the guy’s face was classic, until I realized and explained.
December 12th, 2005 at 2:22 am
Descendant selectors rock! :-)
The intendation approach was interesting to see. Can’t decide yet if I like it or not, but still intriguing!
December 12th, 2005 at 4:00 am
Oh, and if you’re interested, my take on image replacement is in my post Is image replacement really worth it?.
Mike, sorry for the shameless self-promotion… :-)
December 12th, 2005 at 7:46 am
Seeing your indentation method combined with the reference to programming made me think - why can’t CSS work like this?
#frontpageads {
ul {
display: block;
margin: 24px 0 16px 0;
_margin-top: 12px;
/* Double margin bug, IE6 */
padding: 0;
list-style: none;
li {
height: 75px;
margin: 0 16px 8px 8px;
padding: 0;
a {
border: 0 !important;
}
}
}
}
Just an example, and perhaps overdoing it, but you’ll have to admit that nesting rules like this would prevent a lot of unnecessary typing. If you ask me, typing the same #css.selector ten times in a row does get annoying.
December 12th, 2005 at 8:11 am
Having seen your CSS, I have found it incredibly well organized. I actually find the indenting distracting because I often scan as I scroll to find styles and the indentation impedes that. Otherwise, we take a very similar approach. My stylesheet for snook.ca is a little messy it’s what I’ve had for years now (albeit with tweaks). My more current stylesheets are closer to what yours look like now.
(and the tabindex from this should really take me to Post Comment. argh)
December 12th, 2005 at 9:14 am
Is there any reason for:
_margin-top: xxpx;
rather than:
margin-top: xxpx;
?
December 12th, 2005 at 9:30 am
Hey Mike,
Good article. I was looking through the CSS (million.css in particular) and I noticed a lot of IDs (#). Is it pretty common practice for you to use multiple IDs on within your pages structure? I only ask because I have typically found this to cause more headaches (for me at least) down the road in terms of specificity. On larger projects it always seems to get to messy for me down the road as I have to use IDs to style simple P tags. How do you manage it? Just curious.
December 12th, 2005 at 9:50 am
Always good to hear how others are doing it.
For what it’s worth - here’s my method:
- I create one style sheet - called styles.css
- styles.css uses @import to pull in other style sheets - named per their function - e.g. text.css contains all styling related to text (all H1’s, all
’s, etc.), layout.css, navigation.css, etc.
- I find this way works well *for me* because I can quickly identify the style sheet involved if I need to make a change, say, to a paragraph styling, without scrolling through 000’s lines of CSS.
- also, if I want to add something out of the ordinary, I create a new style sheet, and only have to link to it from styles.css for it to be applied across the board.
I think it was Doug Bowman, or Andy Budd, who, in a similar write up, used distinctive character sequences to divide up their single style sheet. So, to find all the styles for layout, they’d just have to search for (say) ‘###layout’. Simple, but effective.
Good discussion,
David
December 12th, 2005 at 10:34 am
Love the idea of image replacement, but the logo example is an unfortunate one. Logos should be clickable, and background images aren’t.
December 12th, 2005 at 11:14 am
Nick - The underscore style is a hack to only show that style to IE6. Google “IE6 underscore hack” for more information. Very handy!
Keith - I think the comment system might have edited out some HTML from your comment. I don’t think you mean multiple of the same ID on the same page though, because that won’t validate. I normally only use IDs on structural elements, but sometimes I might mix it up ;)
Marla - If you check out the image replacement link I posted, you’ll notice that I change the display of the link from inline to block, which makes a big rectangle for users to click on. Background-images aren’t normally clickable, but in this case, it is because I made it so. Same functionality as you would get if you stuck an image tag in your HTML, but in my opinion, much cleaner.
December 12th, 2005 at 11:23 am
Hey Robert - I just dropped a comment on your image replacement entry with my take on the whole thing. Sorry it’s a bit long ;)
December 12th, 2005 at 11:42 am
Can someone please explain to me why the logo should go within a header tag? - Surely this is against web standards practise and against the semantics of the document as logos are not a form of heading, nor should they be considered as a background image…
I don’t see how background colour is an argument for wrapping a logo within a h1 tag either haha… Apart from proving you can do it, which it isn’t really difficult, can you explain to us why it is done in preference to using the logo as a graphic image? - Which is actually what it is after all…
Indentation is something that i have found to be very useful, along with using very visible comment blocks to section off the various parts of the css code… -I find this aids in easy navigation through long css documents, it should also be noted to include the cascading feature of css to split the orginasation of styles into varying area’s print/screen etc…
December 12th, 2005 at 11:57 am
Tobe - The point of image replacement is to provide screen-reader users a more semantically-rich experience, and turning important images into H1-H6 heading tags does just this. Normally, images would be announced with the same emphasis as any other images, including ones like email icons and such, but by making the logo area an H1, you are conveying the importance of the logo to the screen reader which will read it aloud in a more prominent manner than just a regular image with an alt attribute.
I wrote more about this topic as a comment on my friend Robert’s site, so that can probably help you learn more about image replacement techniques and their use.
December 12th, 2005 at 12:02 pm
Thanks for the response, I’ve actually used an image replacement technique on a few sites (i seem to remember firefox needing the a link underline removing even when its bumped off the screen), but I’m left wonding about the issues these techniques prompt.
Firstly i wonder if this is actually being strictly semantically correct, as the logo is not actually a page heading. -and if we are being very strict about the meaning and use of our tags, tables for tabular data, lists for lists etc, this method seems to me to go slightly over the semantic line, as logos would seem to best catergorised under visual content, and not headings or background images…
I am concerned about what tim berners lee thinks about the future development of the web (i forget the term he uses), but if you were to ask the question -what are the headings in all pages on the web related to lean xhtml and precise css? the logo would (or should!)not be what you want to find at the top of your results summary…
As there are no real alternatives, beyond the various image replacement techniques (which mainly work in a similar manner to each other). There isn’t much to do, and I wonder what is best? -I am begining to think its best just to be simple about these matters rather than to bend meaning of tags - the meaning of which will become more important in the future…
I actually quite like your method of invisible block, rather than a bg image on the actual element, i can see this being much easier than worring about the various browser positioning issues.
Thanks for making me think about the issues!
December 12th, 2005 at 12:59 pm
First, nice article! I have read about indenting the CSS file before, but never have done it yet. Maybe I will try it in the next design.
I usually do my CSS files as Roger Johansson does (well, not as good as the one Roger does, but I took some ideas from him about how to keep my stylesheets).
Second:
(…) the separation of design from content. In my HTML files you will never, ever find an tag that links to something that is used for the design of the page rather than the actual content.
In order to have background-images as design elements in your CSS, you’ll probably need to use some form of image replacement. [...] The advantage is that you can use regular HTML tags like H1 to give semantic meaning to things like logos, where before you would just drop an HTML image tag in there and call it a day. By still using the H1 for the logo, you are giving meaning to the ordinarily meaningless image, and you can keep all the design in the CSS and not muddy up your HTML with image tags.
I feel those paragraphs a little contradictory (hey, that’s not a bad thing, I see myself as a contradiction ;) ).
I mean, using IR techniques, isnt it to “put” design and “remove” content?
If you are replacing a logo or words (specially in this last case), you are replacing meaningful content with background-images (design).
What about using something like this?
My article title
or
Company Name
It’s probably I’m missing something.
December 12th, 2005 at 1:05 pm
You gotta escape those < and > entities Maniquí ;)
For those that can’t see the HTML, Maniquí wants to put a span tag inside the H1 with the company’s name, then the logo next to it. Then, I’m assuming, use CSS to make the span display: none; so it can’t be seen.
If that’s the case, then it still doesn’t solve the problem. Screen readers are smart enough not to announce elements that are not visible via the display CSS property, so it wouldn’t make the ALT text of the image any louder or more emphasized than any other image. As long as there is an image tag, it won’t be read aloud the way it should considering this image is a pretty important thing like a logo.
Also, one thing to remember, is that the image replacement articles all went down a few years back and there were HUNDREDS of weblog entries dedicated to image replacement, why it’s needed, etc. If you weren’t around back then to read the bruhaha, I can understand the confusion. No worries ;)
December 12th, 2005 at 1:15 pm
I think there is a major differance between using image replacement for headings and quotes, and using it for logos.
The web is developing into an application platform, and eventually we will utilise applications to find and catergorise information on the web for us. In order for the machines to do this our content needs to be semantically correct and well organised.
The problem lies not with image replacement or alternative content, but with the organisation of specific data. A logo is a visual element, and if we give a document a heading of ‘logo’, it doesn’t make sense when we later ask, what are the headings in the document?
I have no problem at all with image replacement per se, but if it means obfuscating the content then it is not a good solution. That this solution can be seen as being good for standards, when it relies on the misuse of tags is odd to say the least, and i think some confusion about these standards present. On whose behalf i am not sure ;)
December 12th, 2005 at 3:00 pm
That indentation tip is so simple but so powerful! I’m using that from now on - that simplifies scanning through the styles immensely. Nice!
December 15th, 2005 at 5:03 pm
All good points. For image replacement I usually wrap the text in an em or strong tag and then position absolute -9999px, the text-indent is a nice solution too, but I have run into a couple of situations where it won’t quite do the job.
For an example of a well documented/structured (and really long lol) stylesheet check out this: http://navy.com/c/screen.css
December 24th, 2005 at 9:27 pm
Thanks for sharing :)
Really helpful for newbies.
Cheers.
Sergio
November 8th, 2006 at 9:12 pm
Add Your Comment
Comments are moderated because spam's not tolerated.