Simple CSS Tips

It wasn't that long ago that the de-facto way to layout web pages was to use tables.  You ended up with these heinously nested tables that made it very difficult to find anything in your code and were not very flexible.  Then came the advent of CSS.  It opened up a lot of possibilities, but it could be abused, or misused just as easily as tables -- you still see a lot of very poorly written CSS that is worse to maintain that tables.

All that to say, it took me a while to feel really comfortable with CSS, but here are a few tips and tricks I've picked up along the way to make your CSS clean and reusable.

Tip 1 margin: 0 auto;

One of the most confusing things to me when I started using CSS was trying to figure out how to align something centered on the page.  The trick is to create a div, set the width you want and set the margin to 0 auto.  The first 0 tells the div to have no top or bottom margin and the auto tells the left and right margins to have equal margin, aligning the div in the center of the page.

#wrapper
{
    width:600px;
    margin: 0 auto;
}

Tip 2 Multiple Classes

You can assign multiple classes to your html elements.  For example, You might have a class called "product" that set a particular font size and color for a product on your website.  You could keep the product class on your div and add to it a "featured" class that might highlight the product using a background color.  The beauty of CSS is that you can apply both classes and not have to replicate the product attributes in the featured class. You separate multiple classes with a space in your HTML.  Here is an example below:

<div class="product featured">
    <h3<Chacos>/h3>
    The best thing your feet have ever walked in!
</div>

.product {
    width: 150px;
    height: 150px;
    font-family: Arial;
}

.product h3 {
    font-weight:bold;
    font-family: Tahoma, Verdana;
}

.product.featured { /* This applies to elements with product and featured applied. */
    background-color: Red;
}

Tip 3 Absolute Positioning

Absolute positioning can be abused, but it is very helpful sometimes.  When you want to stick something somewhere and don't want it's positioning affected by other things on the page, absolute positioning is the way to go.  A lot of times I'll have a header div and I want the menu to sit at the bottom right of the header.  You could float the menu right and add top margin until it was positioning at the bottom of the header, but what if you change the height of the header, you then have to adjust your margin.  Here is some html and css I typically use for this type of setup (simplified):

<div id="header">
    <ul id="menu">
        <li><a href="Home.aspx">Home</a></li>
        <li><a href="About.aspx">About us</a><li>
        <li><a href="Contact.aspx">Contact Us</a></li>
    </ul>
</div>

#header {
    width:900px;
    height:100px;
    background-color: Blue;
    position: relative; /* Important so our menu is positioned relative to the header */
}

#menu {
    position:absolute;
    bottom: 5px;
    right: 10px;
    list-style: none;
}

#menu li {
    display:inline;
    margin-left:10px;
}

[super awakeFromNib]

Being my first blog post, it seems appropriate that I deal with awakeFromNib. I work for a software company developing websites on a Microsoft stack, but I've been playing around with Cocoa for almost a year now and it has been a lot of fun to work with. It is always challenging to work with a new technology and who doesn't like to work on a mac?

My hope is to share some things I've learned along the way as a software developer and help other people avoid the mistakes I've made. I got the idea of Coding Scars from my friend Ken, who mentored me as a programer. Just about every time I am pulling my hair out over some nasty bug and I call Ken over, he usually knows the answer in a few minutes. I tell him how incredible he is and he always says, "Scars, I just have more scars." So, hopefully those days when you trace down through the debugger or spend a week parsing web service xml, you are developing some coding scars that will serve you well later.

With that out of the way, I spent the last week trying to debug a nasty issue, that ended up being a dumb mistake. I had a subclassed NSWindowController that I was using to load a window from a nib and show it on the screen. My code to load the nib and show the window was as follows:

-(IBAction)showCustomWindow:(id)sender 
{
    if(!windowController){
        windowController = [[MyWindowController alloc] initWithWindowNibName:@"MyWindow"];
    }

    [windowController showWindow:self];
}

On a machine running 10.6 when showCustomWindow was called, the window would show as normal; however, on 10.5 the method would have to be called twice before the window would appear. I was using functions that were available on both 10.5 and 10.6 (10.0 for that matter), so I couldn't figure it out.

Finally, I bit the bullet and pulled down my project in XCode onto a machine running 10.5 and ran it through the debugger. I finally realized that my app was failing when the nib was loaded and a subclass of NSView in my nib called it's awakeFromNib function. My awakeFromNib looked like:

- (void)awakeFromNib
{
    [super awakeFromNib];

    .... bind to objects ....
}

Seemed perfectly normal to me! But, as I came to find out, not every super class implements awakeFromNib! So, when I called [super awakeFromNib] it failed with a "does not respond to selector". The simple solution is to take out the [super awakeFromNib], but a little more elegant solution is to check to see if the superclass responds to awakeFromNib, like so:

if([NSView instancesRespondToSelector:@selector(awakeFromNib)]) {
    [super awakeFromNib];
}

With that change, it worked like a dream. Note: I initially thought i could do:

if([super respondsToSelector:@selector(awakeFromNib)]) {
    [super awakeFromNib];
}

but, you can't call respondsToSelector on super in awakeFromNib, it seems to always return true. So, hopefully this has been helpful or informative and will save someone else some pain.