« November 2006 | Main | January 2007 »

December 2006 Archives

December 3, 2006

Keeping CSS file sizes lean for practicality and sport

One of the benefits touted by separating style from structure is smaller html file sizes. But with many sites, the accompanying CSS file(s) can offset the savings in size, with CSS declarations that can quickly add up. Doug Bowman's site, for example, has 50 KBs worth of CSS. Since CSS is cached, and therefore only downloaded once, and since a growing number of people are on broadband connections, some developers might not see this as a problem.

But there are still some dial-up users out there who still do value the time of initial page load. There are still server admins who care about bandwidth. And fortunately, there are still some web developers out there who not only still care about those dial-up users and server bandwidth, but also take great pride in keeping their CSS files as slim as possible. If you think that only comes by sacrificing readability and structure to the CSS, you may be surprised. Here are some tips in doing so.

1. Use shorthand properties

I thought I'd start by stating the obvious, and say that you should use CSS shorthand properties. (Is anyone learning CSS without learning these, too?) I won't go into all of the shorthand properties here (if you need to know all of them, use this handy page.

Basically, instead of declaring things this way:

#menu {
	margin-top:20px;
	margin-right:5px;
	margin-bottom:10px;
	margin-left:12px;

Do it like this instead:

#menu {margin:20px 5px 10px 12px;}

I'll get another obvious one out of the way with my next suggestion.

2. Cut Colors in Half

Hexidecimal color codes can be shortened in many cases. #ff6600 can just be #f60. This only works when the values are given in pairs, but it's still helpful. White and Black are both common declarations, so instead of #ffffff and #000000, use #fff and #000 respectively. This may not save much, but every little bit helps.

3. Plan ahead

Backpack enthusiasts care about every ounce they carry when hiking. The weights of the tent, flashlight, even silverware, was an important factor when purchasing and packing. Similarly, one can plan ahead when creating a site, and can shave off some bytes in the process.

When planning what CSS is used, make sure to research to find out how many different layouts your page can have. Are there some pages with three columns and some pages with only two, but the column with the main content will be the same in each? Then use classes and IDs wisely.

For example, take the following xhtml for a page with two columns:

<div class="layout2col">
	<p>Dogs smell.</p>
</div>

... and on another page with three columns:

<div class="layout3col">
	<p>More about smelly dogs.</p>
</div>

The CSS for that site might look like this:

.layout2col {width:400px;}
.layout2col p {
	font: normal 1em/1.2em Verdana;
	color:#333;
	}
.layout3col {width:250px;}
.layout3col p {
	font: normal 1em/1.2em Verdana;
	color:#333;
	}

It's ok, but a bit repetitive. If the xhtml could instead look something like this:

<div id="content" class="layout3col">
	<p>More about smelly dogs.</p>
</div>

The following, more concise, CSS could be used and achieve the same results as above:

#content p {
	font: normal 1em/1.2em Verdana;
	color:#333;
	}
.layout2col {width:400px;}
.layout3col {width:250px;}

4. Ids, Classes, and File names

If a naming convention is used for ids, classes, and images, it can mean a big difference in the CSS file size.

For instance, instead of have a ul with an id of #primarynavigation and another ul with an id of #secondarynavigation, use #nav1 and #nav2 instead. Instead of #header and #footer, maybe use #head and #foot. Instead of a class of .content, maybe use a class of .main.

Image names are another place you can apply this technique. Instead of naming the background image to an h1 "background_h1.gif", consider a name like "bg_h1.gif".

5. Change Directories

File names aren't the only place to trim some letters. Consider the directory where images are stored. The image directory has to be referenced with every mention of a background or list-style image. Many people call that directory "images", but what if it was named "img", or just "i"?

#logo {background: #fff url(../i/logo.gif)}

Not only would you save a few letters over the course of a CSS document, but it could be enough to keep many lines from wrapping, and therefore adding to the readability of a CSS file.

6. Consider ditching alternative fonts

I was always told to offer alternative fonts, such as the following:

p {font:normal 1em/1.2em Verdana,Arial,sans-serif;}

...which says that paragraphs should be of font-family Verdana, and if Verdana isn't available on the user's system, use Arial, and if Arial isn't available, use whatever the default sans-serif font would be.

But I think some fonts, such as Verdana and Georgia, are on everybody's system, so why bother offering a back-up? You could save a few bytes by ditching those alternatives:

p {font: normal 1em/1.2em Verdana;}

I usually only do this for Verdana, Arial, and Georgia. If a less boring font was to be used, it would still be good to list alternatives.

7. Work in one CSS file, but publish another

One easy way to trim file size is to take out comments and white space for the final version of the CSS file. Comments, white space, and putting one declariation per line are all great ways for developers to organize and write their CSS. But once you're ready to publish that file, make a copy of it and strip all the comments and white space from the copy. Upload that new slim file to your server. After all, browsers don't care about your CSS comments and white space. If you ever need to troubleshoot, rewrite, or add to your CSS, you can do so in your 'working copy'. Then make another slimmed down copy to republish. CSS Tweak is a great service for stripping white space and comments.

Knowing that one will later publish a slimmed down CSS file can be quite freeing to a developer, and may result in that developer using more thorough comments than one would otherwise. And comments help everyone, even the person who originally wrote them.

I'd love to hear of any other techniques people find helpful.

December 5, 2006

What's with the candy apples?

When creating this blog, I imagined to get CSS questions directed to me. The main question I've gotten so far is, "What's with the candy apples?" I guess if you're going to ask the CSS guy a question, I better answer it, even if it isn't CSS-related.

The site is going for a carnival theme. If we were at a real carnival, maybe between the booth where a guy guesses your weight and the trailer with the bearded lady, you'd have me waiting to tackle some CSS stumpers. Call me a geek, but I find figuring out CSS solutions fun. I also find it fun to start a fresh new blog for a while. It's about as fun, you might say, as going to the fair. So I think the theme fits right in.

Not long after I created this blog I knew I had to get away from the Movable Type default template. I asked JD to help me come up with a design, and he came back with a photoshop document of much of what you see here. Not only was I happy to get away from the default Movable Type template, but I was excited to move towards a design that seemed so fresh. Much appreciation, JD.

So among many things that you might see at the fair are candy apples, and I found an image of some candy apples that could help decorate my new home. At the fair, you may also see ferris wheels, 'ring-the-bell' games, among other things. As this site progresses, you might see images of those things here, too.

So keep the questions coming. I'm happy to answer them. (BTW, I do relationship advice, too. )

December 7, 2006

The CSS Guy Facts

Chuck Norris became a living legend the day Chuck Norris facts hit the Internet. Maybe if I start a list of larger-than-life 'facts' about my xhtml and css prowess, I'll become one, too, and possibly be a story book hero for your nerdy great-grandchildren.

  • The CSS Guy has created many online forms, but has never completed one, as he refuses to "Submit" to anybody or anything.
  • The CSS Guy once escaped from a deserted island on a raft he built using only a transparent spacer gif and some javascript.
  • Most secure sites require SSL digital certificates and firewalls. All the CSS Guy needs is "Coded by the CSS Guy" in the footer.
  • The CSS Guy once took a dump on a keyboard, and it validated as XHTML 1.0 Strict.
  • The blink tag was originally created because the Internet lost a staring competition to the CSS Guy.
  • The CSS Guy's web browser doesn't just accept cookies, it demands them.
  • The CSS Guy does not use search engines. Instead, all information on the Internet seeks out the CSS Guy.
  • When the CSS Guy was in grade school, his crayons were labeled in hexadecimal.

I tried to wrap this post in a <roundhousekick> tag, but my browser couldn't handle it.

December 8, 2006

Row Locking with CSS and JavaScript

I was recently asked about the effect used to highlight a table row with a mouse click. This is different than highlights while hovering, as the clicked row should stay highlighted until clicked again. To differentiate this effect from 'row highlighting', I'll refer to it here as 'row locking', since the effect stays in place until the user re-clicks (or unlocks) the row.

This effect is not achieved by CSS alone, but by a combination of CSS and JavaScript. While I'm confident in CSS, I'm quite a novice at the latter, which I'm sure will become evident by the end of this post. However, after reading Jeremy Keith's DOM Scripting, I feel I have the tools to tackle the matter and come up with a possible solution. Much of the code I use to achieve the effect is directly derived from code examples in Keith's book.

An Aside

Jeremy Keith's DOM Scripting is a must for the XHTML and CSS designer who has put off learning javascript. I realized that as a web designer, I might be able to get away with not knowing PHP, mySQL, and other back-end stuff, but there's no reason to limit myself to just two-thirds of front-end web design. Copying and pasting from prototype/scriptaculous/moo.fx/etc. is no substitute for learning how to do this kind of stuff, some of it very simple stuff, on my own. I appreciate Keith's book for making the remaining third element of front-end web design so approachable.

Why?

Before going further, it might be good to mention why the effect may be useful.

  • If you're scanning over a long table, it's nice to mark a row to help guide the eye
  • If you wanted to compare two rows in a table, but they were several rows apart, highlighting each row could serve as a handy helper.
  • I noticed my Movable Type system panel uses this effect in the comments review section, and that the highlighted row also serves as a label for a checkbox on that row (handy stuff), although they are probably using a different method to achieve the effect.

The Blank Slate

I assume that a table that could use this effect would already be using table striping (making every other row a different color). So my 'blank slate' will be table with some basic data with no classes or style attributes in the xhtml. I'll use a very simple script from Jeremy Keith's book for striping the table (with a minor tweak so that it only stripes rows in the <tbody> tag, not the <thead> tag). The function works by attaching a class of row="odd" to every other row on page load.

View Example 1: The Blank Slate.

Row Locking Successfully Achieved

Now that I have a table to work with, it's time to decide how to achieve the row-locking effect. In DOM Scripting, Keith offers an example of code to achieve row highlights with a function called 'highlightRows', which uses onmouseover to change the class (and consequently, the color) of the row when the mouse moves over the table. If I can modify that script to use onclick instead, that might be all that is necessary to achieve row locking. With some minor tweaking, I ended up creating the function 'lockRow', which worked. On click, it adds a class (using addClass) to the row called 'selected'.

View Example 2: Row Locking Successfully Achieved.

Doing More

I had mentioned that I modified Jeremy Keith's 'highlightRows' function to create the 'lockRow' function. Ideally, I would like to use both effects.

To see the 'highightRows' function in action (without row locking), view Example 3: Row Highlighting. This script attaches a class of 'highlight' to any row that is hovered over.

Unfortunately, to combine 'highlightRows' and 'lockRow' in one table is not as easy as just placing all the functions on the same page.

View Example 4: Attempt at Using Both lockRow and highlightRows Not Working So Well.

I think I need to change the 'highlightRows' function to be conditional, so that it would only work on rows that wouldn't have the 'selected' class. My attempts at achieving this have turned up unsuccessful. (Update Dec 22, 2006: Thanks to simu in the comments, there is now a working example - see end of post.)

For instance, here's the 'highlightRows' function without modification:

function highlightRows() {
   if(!document.getElementsByTagName) return false;
   var tbodies = document.getElementsByTagName("tbody");
   for (var j=0; j<tbodies.length; j++) {
      var rows = tbodies[j].getElementsByTagName("tr");
      for (var i=0; i<rows.length; i++) {
         rows[i].oldClassName = rows[i].className
         rows[i].onmouseover = function() {
           addClass(this,"highlight");
         }
         rows[i].onmouseout = function() {
           this.className = this.oldClassName
         }
      }
   }
}

Here's what I thought would make the function only work:

function highlightRows() {
   if(!document.getElementsByTagName) return false;
   var tbodies = document.getElementsByTagName("tbody");
   for (var j=0; j<tbodies.length; j++) {
      var rows = tbodies[j].getElementsByTagName("tr");
      for (var i=0; i<rows.length; i++) {
         if (rows[i].className.indexOf("selected") == -1) {
            rows[i].oldClassName = rows[i].className
            rows[i].onmouseover = function() {
               addClass(this,"highlight");
            }
            rows[i].onmouseout = function() {
               this.className = this.oldClassName
            }
         }
      }
   }
}

But that doesn't do the job, so I'm kind of stumped at the moment. (Who's going to start the 'Ask the JS Guy' web site?)

Another thing I found myself wanting to do is use shift+click to highlight several rows in a row. I'm not sure why I'd want to do that with my simple table example, but for some (like in the Movable Type checkbox scenario), it could be helpful. Right now, I'm not certain how to approach that one, either.

Update December 22, 2006

Simu (first comment below) has offered a modified highlightRows() function that allows for both the highlightRows() and lockRow() functions to co-exist and work together. (Thanks!) The javascript is very clear. View Example 5: Revised highlightRows JavaScript - lockRow and hightlightRows together a Success!

Update December 26, 2006

Tom pointed out my link to example 5 was in fact still pointing to example 4. It's been corrected now - many thanks to Tom. Sorry for any confusion to others.

Update February 5, 2007

Kenny asked of a way to apply these effects to only tables of a certain class, which is a very good idea. View Example 6: Targeting tables with a specific class.

Update February 6, 2007

Raj asked about having, among other things, a checkbox for each row. Great ideas. View Example 7: Adding checkboxes to each row.

Update May 14, 2007

On my example with checkboxes, clicking a row would check the corresponding checkbox, but if I actually clicked on the checkbox, it was havoc. I toyed around with cancelBubble and stopPropagation, and ended up with a working example 8, which has an additional function to fix the issue.

Update August 19, 2007

Locking rows with radios is now working. See example 9 to see it in action and view source/copy.

December 13, 2006

Image Captions Generated with CSS and JavaScript

For a online news article I used to update, one thing we'd always feature is an image of some CEO and present a caption to go with it. I was unsure of the 'best' way to display image captions. This is one of those things for which I wish there was a SimpleQuiz.

Which is the best way to display an image and its caption?

  1. <p>
    <img src="person.jpg" alt="person" /><br />
    This is a person
    </p>
  2. <div>
    <img src="person.jpg" alt="person" />
    <span>This is a person</span>
    </div>
  3. <img src="person.jpg" alt="person" />
    <p>This is a person</p>
  4. <table>
    <tr>
    	<td>
    		<img src="person.jpg" alt="person" />
    	</td>
    	<td>
    		This is a person
    	</td>
    </tr>
    </table>
  5. Make the caption part of the image.

I'm sure there are several other ways. When I received a new update for the newsletter that involved an image and a caption, I found myself checking previous issues to remember how I'd done it before so that I could be consistent. I had always wondered if there could be an easier way so that I wouldn't have to remember. With the power of DOM Scripting, I can do just that.

I chose answer B above for the purposes of this demonstration, with some slight deviation. Here's the picture I chose to work with:

I wanted my caption to be on the bottom of image, appearing as if it's part of it, with a strip of color behind it for readability, but have the strip being somewhat transparent so that the part of the image that I'm covering could still be visible. The final result to look like this:

The only thing I want to put in the markup is the <img> tag.

<img src="dave.jpg" alt="" />

...but I know that I'll have to give a tad more information for the DOM to work its magic. For one, I need to add a class. Another thing is the text to use as a caption. I could use the alt attribute for this, but instead I'm going to use the title attribute.

<img
  src="dave.jpg"
  alt=""
  class="captioned"
  title="Dave Letterman" />

And I want the DOM to create the caption for me. For the most part, I used example from choice B above, with some tweaks. The end markup to create this would look like this:

<div class="imgcontainer">
	<img
	  src="dave.jpg"
	  class="captioned"
	  alt=""
	  title="Dave Letterman">
	<div class="caption">Dave Letterman</div>
</div>

When thinking about how to write a script to accomplish this, it's best to write out the steps in plain English:

  1. Look through all the images on the page.
  2. Check to see if the images have the class "captioned".
  3. If so, take the title attribute value from the image, create a div with a class=caption and put that title attribute text within that div.
  4. Place that caption div immediately after the image.
  5. Wrap the img and the caption in a div together, giving that container div a class of "imgcontainter".

Here's the script I came up with. I call it 'captionizeImages'.

function captionizeImages() {
  if (!document.getElementsByTagName) return false;
  if (!document.createElement) return false;
  var images = document.getElementsByTagName("img");
  if (images.length < 1) return false; 
  for (var i=0; i<images.length; i++) {
    if (images[i].className.indexOf("captioned") != -1) {
      var title = images[i].getAttribute("title");
      var divCaption = document.createElement("div");
      divCaption.className = "caption";
      var divCaption_text = document.createTextNode(title);
      divCaption.appendChild(divCaption_text);
      var divContainer = document.createElement("div");
      divContainer.className="imgcontainer";
      images[i].parentNode.insertBefore(divContainer,images[i]);
      divContainer.appendChild(images[i]);
      insertAfter(divCaption,images[i]);
    }
  }
}

And, of course, each of those elements need to be styled:

.imgcontainer {
	position:relative;
	float:left;
	}
.caption {
	font: normal 1em/1.3em arial;
	background:#fff;
	color:#000;
	position:absolute;
	bottom:0;
	left:0;
	text-align:center;
	width:100%;
	opacity:.75;
	filter:alpha(opacity=85);
	}

The .imgcontainer needs position:relative because the .caption div will need to be absolutely positioned relative to that container div. I had to float it left so that the div would wrap nice and snug around the img (with a float, the div expands all the way across the screen).

For the caption, I wanted to have a little transparency, which is where the opacity declaration comes in. For IE, I have to use filter:alpha(opacity=XX) instead of the opacity:.XX declaration.

View the example.

December 16, 2006

Baseball Card Image Captions with CSS and JavaScript (Near-Mint)

With my last entry, I discussed how to have the DOM generate text captions for images. Now I'm going to take it further, and with a little pre-drawn blank baseball card in png* format, I'm going to have the DOM turn my images into 1987 Donruss (or even 1987 Topps) baseball cards, with the caption showing as the player's name.

Go straight to the example.

*Why .png? As we all know, IE6 doesn't play ball with .pngs. I could've used .gif format for the pre-drawn transparent baseball card, and this technique would work fine in IE6 without any hacks. But I'm wanting to use the 1987 Topps and 1987 Donruss card designs as frames (my heyday of collecting), which have rounded borders and special angles. There needs to be some varying levels of opacity in those corners, which .gif doesn't do. It would all just look like ass unless I used a more boxy frame, like the 1988 Score set, but that's not the one I'm going to use for this tutorial. I'm also not going to include the IE6 htc hacks, or the alpha-transparency hacks, which would've juiced up IE6 so that things will work, but instead I'm leaving them in the dugout. IE6 has a pitcher's batting average when it comes to standards support, so upgrade to IE7 and call it a day. But know that this works in Firefox, Safari, and IE7, and if you wanted to create your frames as .gif instead of .png so that it'll work in IE6, it's your privilege to do so.

On with the game.

The idea is that you start with an image, a portrait in a vertically-rectangular fashion:

...and that image would be marked up like so:

<img
  src="dave.jpg"
  alt=""
  class="donruss"
  title="Dave Letterman" />

By the time I mix in a little JavaScript, that markup will turn out looking like this:

<div class="imgcontainer donruss">
  <img 
     style="width: 318px;
     height: 446px;"
     src="dave.jpg"
     class="donruss"
     alt=""
     title="Dave Letterman">
  <img 
     class="frame"
     src="frameDonruss.png">
  <div class="caption">Dave Letterman</div>
</div>

...producing our desired effect:

Note that the original image is stretched to meet the dimensions of the outer frame (in this case, 318 x 446). That's why it's best to use a vertically oriented image to begin with - so that it at least scales proportionately - if not the exact dimensions of the final product.

The markup generated by the JavaScript would by styled so that the different elements are layered to form the card:

An outer div is created and styled as position:relative so that the card frame and caption can be absolutely positioned in the right spot.

View the example and enjoy. If someone ends up making them with different card designs, let me know - I'd love to see them.

December 20, 2006

Showing Hyperlink Cues with CSS

I like the little icons next to hyperlinks that signify if that link will take me offsite, open a popup, or link to a file (as opposed to another html page). Here's how to do it in a way that's supported in IE7, Firefox, and Safari.

Images

First, find some nice little icons (or better yet, create them yourself) in gif format that will be used as the cues. It might be easier for them all to be the same size (the ones below are 14 x 16) and have a transparent background.

Links to popup window
Links to external sites
Indicates a mailto: link
Links to pdf files
Links to Word files
Links to Excel files

Example 1 - link to pdf file - HTML

As an example, we'll start with the link to the pdf file. Take a look at the following html:

<a href="files/holidays.pdf">View Holidays</a>

The link it generates might look something like this:

Notice there are no classes, ids, etc. that distinguish this link from any other. The only reason we know that it leads to a pdf file is that the last bit of the href attributes value ends in ".pdf".

With some new CSS selectors that are supported in IE7, Firefox, and Safari, you can apply style declarations that are based on the values within tag attributes.

Example 1 - link to pdf file - CSS

If we apply the following styles to the html above:

a[href $='.pdf'] { 
   padding-right: 18px;
   background: transparent url(icon_pdf.gif) no-repeat center right;
}

We would get something like this:

How does it work?

The above CSS rule looks for all a tags whose href attribute ends in ".pdf", then gives it some extra padding on the right of the link to make room for a small pdf icon as a fixed position background image. The dollar sign is what means "end". Since the href in the html has a value of "files/holidays.pdf", it will match the above CSS declaration, and the little pdf icon will be visible next that link.

Example 2 - mailto: links

Easy enough. Now what about the mailto: link? Take the following html:

<a href="mailto:billg@microsoft.com">Contact Me</a>

and apply the following style:

a[href ^="mailto:"] {
   padding-right: 20px;
   background: transparent url(icon_mail.gif) no-repeat center right;
}

Notice the caret (^) in the rule. The caret and equals sign means "starts with". The rule looks for all a tags whose href starts with "mailto:", then gives that link some extra right padding to display a small mail icon as a background image.

Here is the result:

Example 3 - Links to popup windows

Developers who separate markup from behavior should be linking to popups in a very web standards fashion - using a value of something like "popup" as a class or rel attribute in the link. Like so:

<a class="popup" href="help.html">Help Page</a>

Use that same class or rel to show our little icon.

a[class ="popup"] {
   padding-right: 18px;
   background: transparent url(icon_popup.gif) no-repeat center right;
}

The rule looks for all a tags whose class is set to "popup", then gives that link some extra right padding to display a small popup icon as a background image.

Finding one value out of many

But what if we have multiple class or rel values? Like in the following example html:

<a class="popup specialstyle" href="help.html">View Help</a>

Now class doesn't equal "popup", but instead equals "popup specialstyle". So the rule above won't work. It'd be nice to have a way to see values that might be separated by spaces. You can by using the following:

a[class ~="popup"] {
   padding-right: 18px;
   background: transparent url(icon_popup.gif) no-repeat center right;
}

That tilde (found in the top left of most keyboards, requires shift key) and the equal sign together means "look for this word separated from other words with spaces". Perfect for trying to match one value when there are several present.

In Summary

These selectors aren't new, and the ones mentioned here are far from a comprehensive list. What's new is IE7, and so I cherry-picked a few CSS selectors that I knew worked in IE7 and other modern browsers, and knew those are useful for the above effects. If it helps for you to see the code and have some images to play with, you can download the zip which has some examples.

(After thought: I could've attached a zip file icon to the "download the zip" link above, but chose not to. After all, I tell you it's a zip already - no icon is really needed.)

Update: Dec 26, 2006

I think my example above regarding the class attribute was ill-chosen, as it is much easier and better supported to target tags by class by simply using tag.classname selection method rather than tag[class="classname"]. (I can't believe I didn't think of that while writing the article.) I guess it shows that, like in mathematics, there is more than one way to reach the answer.

Update: Dec 29, 2006

If you like this article and the effect it describes, you may also like a more recent article I've written about hyperlink cues called Hyperlink Cues with Favicons.

Update: Jan 9, 2007

For this to work in IE7, make sure you specify a the right doctype. (see Aug 23, 2007 updated below).

Update: Jan 21, 2007

If you're looking for more icons to implement, Alex provides a nice start.

Update: Jan 25, 2007

It was pointed out to me that for links that span two or more lines, IE doesn't display these links as intended. Because the background position is set to "no-repeat center right;" it's centering the icon between two lines. Consider putting the icon on the left side and use position of "top left" if you see yourself possibly encounterting multi-line scenarios.

Updated: Aug 23, 2007

Florian has notified me that which doctype you choose is important to IE7. He writes:

This page helped me a lot: http://hsivonen.iki.fi/doctype/

I have now reconfigured my web server to add "http://www.w3.org/TR/html4/strict.dtd" to the doctype and now it works perfectly.

Basically, if FF says from page information that it's in Quirks mode, then IE7 will fail ... so if you look at the doctype table above, then you'll find that any doctype that leads to quirksmode is deathmode for IE7.

Hope this information is helpful for you, too.

Very helpful. Thanks!

December 26, 2006

Wheel of Fortune

(For those of you expecting for a CSS technique called "Wheel of Fortune", you will be disappointed. It does sound like a cool CSS technique name, though.)

I grew up watching America's favorite gameshow, Wheel of Fortune. Within the past couple of years they've introduced something called a Spin ID that anybody in the United States can get. During the show, if they call your Spin ID, you can contact them within 24 hours and win whatever prize they happen to be giving away (the times I watch, it's usually a trip of some sort).

The chances of me winning are next to nothing, and that makes keeping up with this nonsense kind of boring and fruitless.

I thought it would be a lot more fun if I were watching on behalf of a hundred other people, or even a thousand or more. The probability of me seeing someone actually win these things is greatly increased.

So I introduce: Ask the CSS Guy to Watch Wheel of Fortune For You.

For people who don't watch the show and don't care to, this is for you. You can still win their prizes without watching or even thinking about the show. Sign up for a Spin ID, let me know what it is, and forget about it. If they call your ID, I'll notify you.

Unfortunately, getting a Spin ID is not an intuitive process. Here's how to do it.

Good luck. I'll let you know if anyone on my list wins.

December 29, 2006

Hyperlink Cues with Favicons

I wanted to extend the concept of hyperlink cues a little. For links that point to external sites, what if, instead of showing a generic 'external link' icon, we showed that site's favicon?

Instead of this:

or this:

Do this:

The favicon gives the reader something to recognize if they are already familiar with the destination site, and if not familiar, something new to associate with it. It's similar to the way a feed reader, or a bookmark list, might show sites.

The method to do this requires some CSS, but the most of the magic happens with JavaScript.

Note: I'm no JavaScript guy, and I can say with great confidence that there are more efficient and fool-proof ways to accomplish some things I put forth. If you know how the JavaScript mentioned here can be improved, please let me (and everybody) know.

On with the show.

English before JavaScript

First I wrote out what I wanted to happen in English:

  1. Look for links on the page.
  2. If the link points to some other site, grab the favicon off that site.
  3. Place the favicon next to the link.

Considerations

  • Favicons are easy to get. If a favicon exist, I can always count on it being in a predictable spot: it's always right off the root of a domain, like this: http://www.askthecssguy.com/favicon.ico. For this reason, there's no need to store favicons locally.
  • Not all sites have a favicon. Though most of the sites I regularly visit have a favicon, not all do. In those instances, I could either show nothing, or have a generic image to indicate that a link is external.
  • Not all favicons are the same size. Some are 16x16 pixels. Some are bigger. Yet I want all the favicons to have consistent dimensions. For this reason, I don't want to call the image as a CSS background image, since currently-supported CSS doesn't allow for resizing of background images. I'll have to call the image using the img tag, and style it with the dimensions I want.

Examples

View example pages and view source to see code.

  • Faviconize Everything (View Page »)
    The script will scan every link on the page and place favicons after any links that point off site, resulting in:
  • The favilist (View Page »)
    The script will only attach the favicons to links within ul class="favilist", resulting in:
  • The favilist 2 (View Page »)
    Same as above, but showing favicons at 'full-size' 16x16, so bigger text, too, resulting in:
  • Faviconize Divs with Class (View Page »)
    Only works on links within a div tag of a specified class.
  • Faviconize Divs and excluding a domain (View Page »)
    I modified the 'faviconize all' script so that it will overlook a domain name of your chooseing. If you never want to faviconize pages that link to other pages on your own site, but your blog engine always puts absolute urls in your links, this might be helpful.

Room for Improvement

Here are some known problems. If you can help me solve them, please let me know!

  1. Safari doesn't support the javascript onerror event. If a favicon doesn't exist, it's the onerror event that tells the browser to use the standby "external link" image instead. For Safari, I just get a blank spot instead of my standby image.
  2. The regular expression I'm using to grab the domain name out of my link is far from the best one to use. I suck at regular expressions, and after hunting through tutorials with examples, I found one that worked, but it's got all this extra nonsense. It would be best to have one catered to my specific use. I just need to grab the domain from a link, like "www.wikipedia.org" from "http://en.wikipedia.org/wiki/Favicons".
  3. Resized images are not ideal anyway, but they really look like ass in Internet Explorer.

Updates

  • December 30, 2006: Added example for only faviconizing div tags with a specified class.
  • December 30, 2006: I decided to drink my own kool-aid and introduced this effect in my comments. If commenters left a URL, their name becomes a hyperlink to that URL, and the faviconize script should then show the favicon of that URL if one exists.
  • December 31, 2006: I added another example. The new example shows how to modify the javascript so that you can specify a domain that will be ignored during the faviconization. (word?)

Ask the CSS Guy

About this site.

Send questions, including links or code, to askthecssguy@gmail.com.

Subscribe to this blog's feed.

About December 2006

This page contains all entries posted to Ask the CSS Guy in December 2006. They are listed from oldest to newest.

November 2006 is the previous archive.

January 2007 is the next archive.

Many more can be found on the main index page or by looking through the archives.