Case study: Re-using styles with a body class Ryan 03 Mar 2006

39 comments Latest by RS

Work continues on the new Basecamp Files tab. The new upload process is under control, and now we’re redesigning the Files tab index, where you can view all the files you have uploaded. During this process, I used a favorite trick: repurposing existing styles with a body class. Here’s a little about how the problem sprung up, and how applying a body class helped to solve it.

First I looked at the epicenter, the most important design element. The epicenter of the files page is an individual file with its data. The question was: How do I display a single file? Looking at the parts that belong to a file, I realized the structure of Files maps very closely to the structure of Messages.

Part of a File Maps to Part of a Message
Filename Title
Description Body
Details (file size, author, etc.) Details (author, comments, etc.)

That meant I could base the Files layout on the existing Messages design. The image was clear in my mind. I wanted to get from this:

Messages layout:
Messages in Basecamp

To this:

(Files layout)
Files in Basecamp

I wanted Files to use the same styles as Messages, but with some adjustments. The margins needed to be different, and the header size should be a touch smaller. The task was clear enough. The question was how to implement it cleanly.

Each Message is wrapped in a container named .Post (div class="Post"). I could copy the structure and style of .Post and its children, then rename them as .File, and make my alterations to the copy. But that would increase the cost of change due to repetition. Fortunately there’s a better way to use the existing styles while adapting them to a new purpose.

The trick is to use a body class. I’ve recently started giving a body class to screens that corresponds to their controller in Rails. For example Files would get <body class="Files">, Messages <body class="Messages"> and so on. This allows me to copy the markup for Messages into the Files template, and also specify style differences based on context:

For example I can indent only Files:

div.Post { margin-left: 0; }
body.Files div.Post { margin-left: 10px; }

And decrease the header size:

div.Post h1 { font-size: 16px; }
body.Files div.Post h1 { font-size: 14px; }

More and more, I find the key to success with HTML and CSS is being able to define basic styles and specify the conditions under which they change. Body classes are a great way to do that. Especially if you’re on Rails, there is a sense of satisfaction when you take the domain language all the way into the CSS. That’s beautiful code.

39 comments so far (Jump to latest)

Aaron Gustafson 03 Mar 06

Yeah, I use that technique a lot. It’s really quite powerful.

Luke Karisny 03 Mar 06

I find that this is an excellent way to approach working with styles. In the same sense that CSS declarations cascade, we can apply this same logic to our sites. We start off with a base set of styles and enter more highly specialized declarations the further into the website we traverse. Each page acts as another child in our tree of descendants, allowing styles to be created much in the same way that we view a website.

Mark J 03 Mar 06

You really don’t have to use the Body tag for this, you can also enclose your post, with another div; say a div with id “Files” or class “Files”, so i think you can do something like this:

#Files div.Post …

Thanks!

Mark

Joe Van Dyk 03 Mar 06

Mark — wouldn’t that mean adding extra HTML to solve a style problem? Seems better to handle this in CSS.

Matt Turner 03 Mar 06

Gotta love body switching, this site i built out recently (http://www.ebxusa.com/) changes colors, nav, images… a total of 15 elements in all via body switching depending which section you’re in.

RS 03 Mar 06

Mark J:

It’s true that wrapping with an ID can work as well. There are some advantages to using body instead.

First, the code is clean. All I have to do is add <% @body_class = “files” %> to the top of the template.

Second, I can re-style elements outside the scope of the current template, which is nested in a layout template, by using body. That gives me flexibility, and it’s also good style.

Don Wilson 03 Mar 06

Thanks Ryan for yet another excellent post.

Mark J 03 Mar 06

RS, Joe: Yeah, i think you’re right.

I was thinking more of the semantic structure of the site, that the new div tag might add another logical encapsulation (higher level). But I think it’s adding another clutter to the HTML tags.

Xian 03 Mar 06

I’ve been using similar techniques for ages.

In rails I’ve improved on it by allowing for multiple body classes assigned anywhere throughout the request process.

In my application_controller I have a before filter that sets @body_class = Array.new. Then in my controllers or in my templates depending on what is appropriate I can just do @body_class .

Then I round it off with a helper method body_tag that generates the body tag and adds all the classes space separated if tehre are any. It ends up like this

Xian 03 Mar 06

Sorry, the system ate some of my code. Here it is again.

In rails I’ve improved on it by allowing for multiple body classes assigned anywhere throughout the request process.

In my application_controller I have a before filter that sets @body_class = Array.new. Then in my controllers or in my templates depending on what is appropriate I can just do @body_class << ‘new_class’.

Then I round it off with a helper method body_tag that generates the body tag and adds all the classes space separated if there are any. It ends up like this

Brian Rose 03 Mar 06

I’m wondering how your Rails implementation for body switching is set up. Do you specify a class name as an instance variable and simply add it to the proper layout as in , or is it something more interesting?

Brian Rose 03 Mar 06

Bah, that was supposed to be &lt%= “class="#{@class_name}"” %&gt.

Dave 03 Mar 06

And by stringing classes together, like class=”portfolio admin” you can do double the damage. Good stuff.

Eric Coleman 03 Mar 06

Where do you guys get the icons your using for the file types?

Kyle 03 Mar 06

To touch on what Lindsey mentioned briefly, why would you use a class, and not an id in this situation? Seems to me the id is the proper usage.

I get tired of seeing developers using classes for everything. Of course, I probably err on the side of too many ids.

Kyle

Hrush 03 Mar 06

Eric Coleman: there’s an easy way to grab these icons if you’re using Mac OS X.

1. Select a file whose icon you want to use
2. Activate the “Get info” window from the “File” menu or by typeing Command + I
3. Copy the icon from the “Get info” window
4. Paste into Photoshop or whatever you happen to be using

Daniel Morrison 04 Mar 06

I always love using body class/id but using the controller name… great idea!

Maybe even add the action name as a second class…

I’m getting excited.

bitbutter 04 Mar 06

kyle : “To touch on what Lindsey mentioned briefly, why would you use a class, and not an id in this situation? Seems to me the id is the proper usage.”

In my projects i use id’s for the body tag too, since it seems like the ‘proper’ way to do this; there is only ever one ‘body’..

But by an id on the body you loose the ability to assign multiple rules (like you can when you use classes, as Dave mentioned), so using classes for body switching is perhaps a more flexible approach.

Hrush 04 Mar 06

chy: Copy the icon from the “Get info” window into Photoshop. The icon will be in the top left corner of the window. Clicking on it selects the icon. Once selected, you can copy the icon to the clipboard and paste into your image editor.

Oz Alfert 04 Mar 06

I always set the body class to both the controller name and action name, space separated. The flexibility of being able to refer to the particular body in two separate ways has come in handy many times. I won’t get into the specifics, but I find that using classes gives more flexibility than ID in this case.

Jack 04 Mar 06

Avoiding repetition is great but I think the one drawback of this method is that you couldn’t display messages and files on the same page. (If that’s not something that would never need to happen in Campfire then that’s fine.)

Personally I could have done something like <div class=”Post File> and then style it with the selector div.Post.File { … }

While there’s a potential for IE to incorrectly parse some of the CSS due to the complicated selector, it makes the CSS a little more flexible.

Christopher Fahey 04 Mar 06

My first thought was, “But Files and Messages are different things, why should they share classes?”. Then I thought, “Would this work if you ever wanted to display Files and Messages on the same page? What if in a future version you wanted to display the two elements in wildly different ways, or add more unique parts to each element?”

I suspect you are trying to create overly clean code, trying to reduce the number of classes at the expense of the real purpose of CSS: semantic accuracy. Something seems a little wrong about reducing the number of semantic elements in use by combining unequivalent elements into a single display class. For example, while you may intend to display the File Details (file size, author, etc.) in a manner very similar to the Message Details (author, comments, etc.), the two elements are not identical semantically. Semantically, you’re misnnaming each “File” a “Post” simply in order to reduce the number of classes used in the system.

Think about it from a database point of view: Would you consider storing Messages and Posts in the same database table, for example by storing each File’s ‘filename’ in a Message ‘title’ field, etc?

I find the key to success with HTML and CSS is being able to define basic styles and specify the conditions under which they change

That’s using your visual design objectives to drive the CSS classes, instead of using the semantics of the actual content to drive them. The approach of defining presentation classes and modifying them by context may seem simpler in the sense that is uses less code, but it’s not so simple insofar as you’re semantically referring to two or more different things with the same name.

I’m not much of a CSS guy at all, but this smells a little like a violation of the rule that “things should be made as simple as possible, but no simpler.” Either that, or I’m as much of a “semantic-accuracy” fundamentalist as you are a “avoid repetition” fundamentalist.

JF 04 Mar 06

“Would this work if you ever wanted to display Files and Messages on the same page? What if in a future version you wanted to display the two elements in wildly different ways, or add more unique parts to each element?”

Slow down. From Getting Real: “It’s not a problem until it’s a problem.” Translation: Don’t solve problems you don’t have yet. Work with what’s real, not what may be real sometime in the blurry future.

This works great for now. Will it work in 1 year if things change? Maybe, maybe not, but the future is uncertain so don’t worry about it now. Chances are you’ll guess wrong, so we prefer not to guess. We solve the problems we have now and solve the problems we have later later.

Christopher Fahey 04 Mar 06

�It�s not a problem until it�s a problem.� Translation: Don�t solve problems you don�t have yet.

Amen to that. My impression, though, is that this is an example of doing just that: solving a non-problem. Calling Files Files and Posts Posts and using different styles for each was the initial situation, and from a semantic point of view not only is this not a problem, it is the standard and correct way of structuring content. Coming up with a clever way of using the same classes for both elements seems to me like a solution to a problem that didn’t exist.

Pius Uzamere 04 Mar 06

Thanks for the informative post.

RS 04 Mar 06

… trying to reduce the number of classes at the expense of the real purpose of CSS: semantic accuracy.

Semantics shemantics. The reason I use CSS is because it lowers the cost of change. That’s all.

gwg 04 Mar 06

The whole question of files and messages on the same page doesn’t bother me because this is a very quick and easy solution. The cost of change is low.

However, semantic HTML is important. Fundamentally misusing HTML elements just because you can apply some css is amateur. Doing raises the cost of change.

To clarify, I’m not saying that RS or anyone else here is amateur; writing semantic HTML has a lot of hidden benefits.

Wilson Miner 04 Mar 06

This technique starts to get really powerful with large section-based sites with lots of content that shares a similar structure (oh, say a news site).

I’ve taken to overloading the body tag with as much information about the page as id useful, depdending on the scope of the site.

The body id becomes a unique identifier for the individual page or template, (story-detail, catalog-index, etc.). The body gets multiple classes depending on the context. One class for the section (news, sports, help, etc.) and one class for the page type or format if necessary (wide, etc.).

Combined with smart stylesheets, this can be really useful, from simple things like styling the nav based on the current section without adding any markup to completely customizing the display for an individual section or type of page.

Bas 04 Mar 06

Wouldn’t it be better if you just used a list like this:

  • file
  • file


Or have an extra class on your content area, let’s say you’re using a class called ‘content’:

Bas 04 Mar 06

I noticed basic HTML is allowed, I meant this:

Have a list with class=”Files” in the ‘ul’ tag or have an (extra) class on your content area called ‘Files’.

Christopher Fahey 04 Mar 06

gwg: The whole question of files and messages on the same page doesn�t bother me because this is a very quick and easy solution.

To clarify my original post in light of this and JF’s comments: I totally agree that the potential need to display both Files and Messages on the same page is not by itself a compelling reason to keep the styles separated. But that possibility occurred to me immediately, and I suspect that I thought about it precisely because I think of HTML as semantic markup and because I saw potential confusion down the line when trying to debug display problems or make functional/display changes.

RS: Semantics shemantics. The reason I use CSS is because it lowers the cost of change. That�s all.

A perfectly valid point, given your particular needs. My takeaway from this is that some people use CSS in a semantically-centered way, others use it in a presentation-centered way. The paradox of CSS is that it can be used either way.

Michael Ward 06 Mar 06

gwg - I don’t see how the semantics of this example could be improved - we’ve got a h tag where it is appropriate, and the rest is marked up using suitable generic markup.

Id and class names do not carry semantics. They are purely an aid for the coder and the parser. The is no specified meaning behind any id or class name.

Darrel 06 Mar 06

Just wanted to say that it’s nice to see some good ol’ nuts-and-bolts posts back on the blog.

John Hamman 06 Mar 06

This kinda goes along with why they are called “Cascadeing” style sheets :)

John Hamman 06 Mar 06

Ok, after my smart alec remark, I have an question. Why not use an #id instead of a class for the body tag. In other words, what is your reasoning for using a class over an Id?

RS 07 Mar 06

Why not use an #id instead of a class for the body tag. In other words, what is your reasoning for using a class over an Id?

It’s a personal choice. It’s really not important.