case study

Hot and graceful jQuery dropcaps

Dropcaps are a staple of magazine and newspaper design, but aren’t always the easiest to implement on the web. Using this little jQuery and CSS tutorial, you can easily add hot little dropcaps to your web articles without bothering your developers. This method will also let you sleep at night knowing your caps will degrade gracefully, displaying just fine in browsers without CSS or JavaScript enabled.

Please note, this tutorial is for those who are familiar with jQuery and CSS. No basics taught here. Also nerd alert.

Here we have a flippin’ sweet dropcap on an article page for the new Combating Pornography website we’re building (launching early 2009).

Tadd recently noted that he’s been using some nice CSS 2 selectors in the new General Conference design. In his example, he’s styling the initial character of the article with CSS typography. Noble indeed.

However, I am more of a type snob and wanted my dropcap to be set in Caecilia, matching some other type found throughout this new site.

(Yes, this means saving 26 images of dropcaps in Photoshop. Luckily this took me all of 10 mins. As for translated sites, more on that below.)

So our task is to style the initial character with a background image, with hand-adjustable pixel spacing around each individual letter, and in a way that degrades as gracefully as Audrey Hepburn if she were a nerded-out website.

I also don’t want to bother the developers (who read this blog – hi Mindie!) to put a <span> around the initial character, and I really don’t want to beg them to throw a different class on that span depending on which letter of the alphabet that character is.

Sound like a daunting task? It’s not.

HTML it up

First let’s make sure the HTML is set up nice and easy:

Here we have the initial paragraph from Michael Gardner’s article on Hope, Healing, and Dealing with Addiction (here is the full comp so you have some context). No spans, no special classes. Easy fo’sheezy on the developers.

jQuery action

Next we hook up our page with some jQuery, and start the show.

<head>

<script src="scripts/jquery.js" type="text/javascript"></script>

<script type="text/javascript" charset="utf-8">
$(document).ready(function(){ 

});
</script>
</head>

Inside our jQuery block, we’ll first grab the first paragraph in our article (in my case, inside my “body” div), and add a class of “dropcap” so we can remove the indent and refer to it later:

$(document).ready(function(){ 
    p1= $("#body p:first");
    p1.addClass("dropcap");
});

Next, we need to grab the text from the first paragraph. We do this by taking the actual paragraph element from our p1 object, and asking it for its content using a standard JavaScript function, “textContent.” We also want to strip out any leading spaces or quotes, using some regular expression magic:

$(document).ready(function(){ 
    p1= $("#body p:first");
    p1.addClass("dropcap");
    p= p1[0].textContent.replace(/^\s+/, "").replace(/^"/, "").replace(/^'/, "");
});

Next we need the initial character from that paragraph (whic we know is alpha-numeric), using the standard function “charAt.”

$(document).ready(function(){ 
    p1= $("#body p:first");
    p1.addClass("dropcap");
    p= p1[0].textContent.replace(/^\s+/, "").replace(/^"/, "").replace(/^'/, "");
    c= p.charAt(0);
});

Now comes the money. In one statement, we will replace the html inside our jQuery object (p1) with a new block of code that wraps the initial character in a span, adds a class of “dropcap-” + the initial letter (don’t forget the lowercase), and adds a style with a background image for that specific letter. Check it.

$(document).ready(function(){ 
    p1= $("#body p:first");
    p1.addClass("dropcap");
    p= p1[0].textContent.replace(/^\s+/, "").replace(/^"/, "").replace(/^'/, "");
    c= p.charAt(0);
    p1.html('<span class="dropcap-' 
        + c.toLowerCase() 
        + '" style="background-image: url(images/drop-' 
        + c.toLowerCase() 
        + '.jpg)">' 
        + c 
        + '</span>' 
        + p.substring(1, p.length));
});

Beautiful. The resulting HTML:

CSS magic

The code above adds a specific class and (gasp!) an element-level style for one reason: keep it simple for the developers (and me).

By giving each letter its own unique class, I can adjust the pixel padding as I see fit. By defining the background image on the element level, I don’t need dozens of lines of code in my CSS file to define each letter class and each letter background. jQuery does it for me.

In our CSS file, I have the following block of code to manage the paragraph:

/* dropcaps */
#body .dropcap{
    text-indent: 0;
}
.dropcap-a, 
.dropcap-b, 
.dropcap-c, 
.dropcap-d, 
.dropcap-e, 
.dropcap-f, 
.dropcap-g, 
.dropcap-h, 
.dropcap-i, 
.dropcap-j, 
.dropcap-k, 
.dropcap-l, 
.dropcap-m, 
.dropcap-n, 
.dropcap-o, 
.dropcap-p, 
.dropcap-q, 
.dropcap-r, 
.dropcap-s, 
.dropcap-t, 
.dropcap-u, 
.dropcap-v, 
.dropcap-w, 
.dropcap-x, 
.dropcap-y, 
.dropcap-z {
    width: 75px;
    height: 80px;
    display: block;
    text-indent: -5000px;
    float: left;
    margin-top: 5px;
    background: transparent top center no-repeat;
}

.dropcap-a{ width: 95px;}
.dropcap-d{ width: 85px;}
.dropcap-h{ width: 85px;}
.dropcap-i{ width: 56px;}
.dropcap-j{ width: 56px; height: 85px;}
.dropcap-k{ width: 85px;}
.dropcap-m{ width: 100px;}
.dropcap-n{ width: 85px;}
.dropcap-q{ width: 85px; height: 90px;}
.dropcap-u{ width: 85px;}
.dropcap-v{ width: 85px;}
.dropcap-w{ width: 120px;}
.dropcap-x{ width: 85px;}
.dropcap-y{ width: 85px;}

I’ve removed the text-indent on this first paragraph, and defined the basic styles for each dropcap, including custom pixel widths for a few.

This method ensures that for anything not defined, like a Chinese or Spanish character, the styles won’t apply and you still have a perfectly fine-looking page no matter what your first letter is. It also means that if you were so inclined, you can define styles and images for any character (as long as your server / target browser supports those characters):

Not only is this saving me hassle, this is saving a decent amount of Java (or Ruby or PHP) code for our developers, and enables me to hand over an even more complete prototype.

Big ups to Pete Lasko, who nerded out with me and helped with some of the code.

posted by Jason Lynes on Tuesday, Dec 02, 2008
tagged with code, programming, css, html, jquery, javascript