CSSnewbie

About CSSnewbie

Our mission is to help the beginning to intermediate web designer master the subtleties of CSS by offering CSS tutorials, tips, and techniques.

Posts Filed Under ‘Advanced Techniques’

Show/Hide Content with CSS and JavaScript

There are plenty of reasons why you might feel the urge to wax verbose on your website’s front page: to prevent your users from having to click through to a new page to find your information, to avoid having to reload the page, or even to improve your front page’s SEO. But just because your front page is text-heavy doesn’t mean it all needs to be visible at once.

Today’s tutorial will show you how to hide away extra bits of content using CSS and JavaScript, to be revealed at the click of a button. This is a great technique, because displaying the additional content doesn’t require a refresh or navigation to a new page and all your content is still visible to search engine bots that don’t pay any attention to CSS or JavaScript.

We’ll start with structuring our XHTML appropriately:

<p>...This is all visible content...
<a href="#" id="example-show" class="showLink"
onclick="showHide('example');return false;">See more.</a>
</p>
<div id="example" class="more">
	<p>...This content is hidden by default...</p>
	<p><a href="#" id="example-hide" class="hideLink"
	onclick="showHide('example');return false;">Hide this content.</a></p>
</div>

There are three things of importance here: the “show” anchor, the “hide” anchor, and our “hidden” div. Each has been given an ID and a class. The IDs are used by our JavaScript to locate and style the items appropriately. I’m then using the classes to set our “default” CSS. Technically you could just use the IDs the set that CSS as well, but if you wanted more than one hidden section on your page, that could get messy.

You’ll notice in the code above that all of our IDs are fairly similar. This is a trick I’m using to simplify our JavaScript, as you’ll see later on down the road, so I suggest doing something similar. The class names have no relationship to the JavaScript whatsoever, and could really be whatever you wanted them to be.

It’s also important to note that we’re calling our JavaScript using the “onclick” call, and passing it the name of our hidden div. Our JavaScript will use that single variable to do the rest of the work.

Now that we have our XHTML in place, let’s put together our default CSS:

.more {
	display: none;
	border-top: 1px solid #666;
	border-bottom: 1px solid #666; }
a.showLink, a.hideLink {
	text-decoration: none;
	color: #36f;
	padding-left: 8px;
	background: transparent url('down.gif') no-repeat left; }
a.hideLink {
	background: transparent url('up.gif') no-repeat left; }
a.showLink:hover, a.hideLink:hover {
	border-bottom: 1px dotted #36f; }

I’m technically doing far more styling than is necessary here, mostly for aesthetic purposes. The only truly important style is the “display: none;” rule on our .more class. This hides our extra content by default. The rest of the CSS simply adds a border to our div (the border is hidden by the display rule, but becomes visible later) and fancied up our show/hide anchors by putting down/up arrows next to them and replacing the standard underline with a dotted border. You could style these yourself however you like, and everything would still work just fine.

Next comes the JavaScript, which looks far more complicated than it is:

function showHide(shID) {
	if (document.getElementById(shID)) {
		if (document.getElementById(shID+'-show').style.display != 'none') {
			document.getElementById(shID+'-show').style.display = 'none';
			document.getElementById(shID).style.display = 'block';
		}
		else {
			document.getElementById(shID+'-show').style.display = 'inline';
			document.getElementById(shID).style.display = 'none';
		}
	}
}

Our JavaScript is doing four things here:

  1. It checks to see if it can find an element with an ID that matches the variable we passed it.
  2. If so, it checks to see if our “show” link is visible (this is where the ID naming convention starts to matter).
  3. If the “show” link is visible, that means our content is still hidden. The JavaScript then hides the link and displays our hidden content.
  4. If the “show” link is hidden, that means our extra content is currently visible. So it just reverses course, displaying our link again and hiding our extra content.

And that’s it! You can see a working example in action here.

Our job has been made much simpler by a few tricksy tricks. First off, we’re using the same function to show and hide our content, which saves us a bit of coding time. Our function simply checks on the state of things: if things are hidden, it shows them, and vice-versa.

Second, by using a defined schema for our element IDs (“example,” “example-show,” and “example-hide,” in our example above), we only need to pass our JavaScript a single variable. It then uses that variable to find all of our other elements and style them appropriately.

And finally, we put our “hide this content” anchor inside the hidden div. This means that we never have to set its display property: it’s hidden when the container is hidden, and visible when the container is. That saves us two lines of JavaScript and at least one line of CSS.

This technique could be used in loads of situations. Say for example that you have a Wordpress blog and the front page shows excerpts instead of the full article. You could use this technique to have the whole article on the front page for the search engines to find, visible to your users at the click of a button. Or maybe you have a complex form that could use some detailed in-page explanation, but you don’t always want the help content visible, eating up real estate when some users already know what to do. Or… well, anything, really. Let me know if you come up with any creative uses!

The CSS-Only Accordion Effect

The Accordion Effect is fast becoming one of the most commonly used (and perhaps abused?) effects of the Web 2.0 world. Most JavaScript frameworks make such an effect fairly easy to pull off – heck, MooTools even built their reputation on it in the early days. So what makes this accordion effect special? It doesn’t require a single line of JavaScript.

First off, what is an “accordion” effect? Generally speaking, the accordion effect takes several larger elements and then compresses them into a small space so that only a small portion (like a heading) of most or all of the elements is visible. Then, when the user interacts with that element — either by clicking on it or maybe only mousing over — the accordion expands so that the element of interest is visible, and the other elements shrink down automatically. When it’s in use, it looks a bit like an accordion expanding and contracting: hence the name.

Our accordion will work exactly the same way: all of the elements will be partially visible when the user loads the page. And then when they mouse over a particular section, it will instantly expand – and the other elements will contract – to make reading more easy.

example of accordion effect before and after the user mouses over it

So how do we accomplish this trick? First, we start with our XHTML, which just consists of a couple of divs with some IDs applied:

<div id="accordion">
	<div id="part1">
		<p>This text is in part 1.</p>
	</div>
	<div id="part2">
		<p>This text is in part 2.</p>
	</div>
	<div id="part3">
		<p>This text is in part 3.</p>
	</div>
	<div id="part4">
		<p>This text is in part 4.</p>
	</div>
</div>

My first div defines where my accordion starts and ends. The divs nested inside are just parts of my accordion – they don’t even technically need IDs unless I want to style them differently. That’s all the XHTML it takes!

So now, let’s start building our accordion. We start by defining the physical limitations of our space:

#accordion {
	width: 500px;
	margin: 100px auto; }

All I’ve done is give my accordion a specific width and centered it in the page for a nice visual effect. Now, I have to create the default state for the divs inside of my accordion:

#accordion div {
	float: left;
	width:25%;
	height: 300px;
	overflow: hidden;}

This snippet floats all of my divs to the left and gives them a specific width and height. I’ve chosen a width of 25% because I have four elements in my accordion, so they all split that width up evenly by default. If I’d had five elements, I would have used 20%, and so on. My height of 300 pixels also becomes the height of my accordion div.

The overflow: hidden part here is also crucially important. This is what prevents my divs from either resizing to fit their content or spilling their content out of the containing div and onto our page. It also creates a nice visual effect… people will wonder what content they’re missing, and will mouse over the area to investigate.

extra text is hidden from the user, inspiring curiosity.

So now that we’ve created our default state, we need to create our hover or “active” state. This requires two CSS rules. The first looks like this:

#accordion:hover div { width: 20px; }

We’re using the :hover pseudo-class here in a pretty creative way – we’re telling all of the divs inside of the div we’re hovering over to change. Specifically, we’re shrinking them all down to 20 pixels to make room for our expanded accordion section. So now we just need to make sure it expands:

#accordion:hover div:hover {
	width: 440px;
	overflow: auto; }

The :hover pseudo-class comes into play here again. Now, we’re applying styles to an element we’re hovering over, inside of an element we’re hovering over. We’re styling this element differently than our others by giving it a specific width – 440 pixels, i.e. 500 pixels minus the 20 pixels taken up by our other three divs – and setting its overflow to “auto.” These two classes cause our active div to expand, and then give it a scroll bar if the content is too long.

And that’s all there is to creating a CSS-only accordion box! If you’d like to see it in action, click here. The only change I’ve made to the full version is I’ve added a few background styles and some interior padding to each of the accordion sections to make them stand out and look a little more attractive.

This example creates a horizontal accordion box. But it’s just as easy to create a vertically oriented accordion. All we really need to do is eliminate the floats on our nested divs and turn most of our width tags into height tags. Here is the markup:

#accordion {
	width: 500px;
	height: 400px;
	margin: 20% auto; }
#accordion div {
	height:25%;
	overflow: hidden;}
#accordion:hover div {
	height: 20px; }
#accordion:hover div:hover {
	height: 340px;
	overflow: auto; }

And you can see it in action here.

As with any trick this cool, there are some caveats. Most significantly: this technique does not work in IE6, because IE6 doesn’t support hover states on anything other than anchors. Therefore, you can make it work if you’re willing to make a sacrifice: if you wrap all of your divs in anchor tags, and then apply the hover state to those anchors instead of your divs, the technique should work the same (I haven’t tried it, though). However, that wouldn’t be particularly semantic or valid, so I’m not showing it here.

Also, if you apply any padding or borders to your #accordion div, that can cause some problems. The border and padding are part of your div, and therefore part of your :hover class. However, if you’re hovering over the containing div’s padding, you aren’t hovering over one of the sections of your accordion – meaning all of your interior divs will shrink down to their smallest size, and none will grow to fill the space. It took me half an hour of debugging to figure this one out. :)

So there you have it. Use it, share it, love it. And let me know in the comments if you come up with a particularly interesting or attractive implementation – mine is obviously pretty simple!

Perma-Closing Message Boxes with JavaScript + CSS

message box

Earlier this week I talked a bit about message boxes – how to style them and position them on your page to get them noticed. But a message that pops up every single time your website is loaded could get annoying. It’d be useful to give your users the ability to close those messages. For that, we’ll turn to our friend JavaScript.

We’ll start by building our message box in XHTML. Mine looks like this:

<div id="message-1" class="msgbox">
	<a href="#" id="close" title="Close This">X</a>
	<p>My uber-important message goes here!</p>
</div>

I’ve made a div with both an ID and a class. This will come in handy later when we need to reference our object in our JavaScript. Inside, I put an anchor tag with a class of “close.” This will become my close button later. And then I simply added a paragraph to hold my message.

Next up, we’ll want to style that message box. You can make it look pretty much however you want, and Woork has a nice article on styling message boxes, if you’re interested in discovering alternative styles. For my message box, I wrote this:

.msgbox {
	position: absolute;
	top: 15px;
	right: 20px;
	width: 20em;
	background-color: #b00;
	border: 1px solid #333;
	color: #fff;
	font-weight: bold; }
.msgbox p {
	margin: 0;
	padding: 5px 10px; }
.msgbox a.close {
	float: right;
	text-decoration: none;
	font-weight: bold;
	color: #333;
	background-color: #fff;
	border-left: 1px solid #333;
	border-bottom: 1px solid #333;
	padding: 0 4px;
	margin-left: 5px; }

Three rules are at play here. First, I’m styling the message box itself, using the class I gave it. I’m absolutely positioning the element and giving it a width. I’m also giving it a red background, bolding the text inside and turning it white, and applying a border. Then I’m applying a bit of styling to the paragraph inside to push it away from the side of the box.

Why didn’t I apply that padding to the message box itself? Because of the “close” link. I wanted to be able to float it to the right of the box and give it some styles to make it look more like a “close” button. After all of that CSS, this is what I have:

example message box

But so far, we just have a message box. That close button doesn’t do much of anything. For the rest, we’ll turn to JavaScript. All we need is a little function like this:

function closeBox(toClose) {
	document.getElementById(toClose).style.display = "none";
}

This function takes a single argument (toClose) which tells it the ID of the element we want to make disappear. We supply argument when we call the JavaScript. In this case, because we want it to happen when someone clicks our close box, we’d add it to our XHTML like this:

<a href="#" class="close"
onclick="closeBox('message-1'); return false;"
title="Close This">X</a>

We’ve added the “onclick” attribute to our “close” link tomake it fire a bit of JavaScript when the element is clicked. We’re telling it to call our closeBox function that we just wrote, and we’re giving it the ID of the message box we want to close. The “return false” part basically tells it to stop (that is, not to actually go to our specified href afterwards).

That’s all we need to create a message box that closes! However, if your users close the box and then refresh the page, the message box comes right back. What if we want it to close permanently? For that, we’ll need some more fancy JavaScript, because we’ll need to make use of cookies.

The cookie will act as a check that we can refer back to. When the user closes the message box, we’ll set a cookie. Then, when they come back to the page, we’ll check to see if the cookie is set. If there’s no cookie, we’ll show them the message. If there is a cookie, we’ll keep the message box hidden.

First, we’ll make a small change to our CSS:

.msgbox {
	display: none; /* Start out hidden. */
	position: absolute;
	top: 15px;
	right: 20px;
	width: 20em;
	background-color: #b00;
	border: 1px solid #333;
	color: #fff;
	font-weight: bold; }

All we’re doing is adding a “display: none” to the top of the element. By default, we don’t want our message box to show up. Instead, we’ll use JavaScript to display it if we want to see it. Why? It’s a usability thing: this way, if a user doesn’t have JavaScript enabled, they don’t see the message box. That may seem like a bad thing, but consider the alternative: if we didn’t set this rule, then anyone without JavaScript couldn’t get rid of your message box. And depending on its placement, that could be a big usability problem.

So now we need two extra functions in our JavaScript: one to set the cookie when we close the box, and another to check to see if the cookie exists when the user comes back. Our JavaScript now looks like this:

function closeBox(toClose) {
	document.getElementById(toClose).style.display = "none";
	setCookie(toClose, "closed", 365);
}
function setCookie(cName, value, expiredays) {
	var expDate = new Date();
	expDate.setDate(expDate.getDate()+expiredays);
	document.cookie=cName + "=" + escape(value) +
	";expires=" + expDate.toGMTString();
}
function loadMsg(msgClass) {
	msg = document.getElementsByTagName("div");
	for (i=0; i<msg.length; i++) {
		if(msg[i].className == msgClass) {
			if(document.cookie.indexOf(msg[i].id) == -1) {
				msg[i].style.display = "block";
			}
		}
	}
}

First off, we modified our closeBox() function to make a call to the setCookie() function after it’s hidden the message box.

Next comes the setCookie() function. It takes three arguments: the name of the cookie, the value to be set, and how long the cookie should last before it expires (in days). We could have hard-coded some of this stuff to save time and space, but this way you can reuse this same function to set cookies all over your site – not just for this purpose.

Also, note that we’re using the toClose variable for our cookie name in setCookie()… which you might also remember is the ID of the message box itself. This is a useful trick, because this means you could theoretically have multiple message boxes with different IDs (all with the same .msgbox class) on your page, and you could open and close them separately, because each of their states would be set in a unique cookie.

Next comes the loadMsg() function. It takes one argument: msgClass. This variable represents the class you’ve set on all your message boxes. Our loadMsg() function cycles through all the <div> tags on your website and checks to see if they have the “msgClass” class set (whatever that happens to be… in my document, that was “msgbox”). If it finds such a div, it checks to see if it can find a cookie with a name that matches the ID set on that div – in our example it would be looking for “message-1.” If it doesn’t find a match (meaning the user hasn’t closed the box), then it sets that div to “display: block,” meaning it will show up normally. Otherwise, the message box stays hidden.

Now, all we need to do is ensure the loadMsg() function runs when the page first loads. To do that, I just modified my body tag like so:

<body onload="loadMsg('msgbox');">

The “onload” attribute fires when the page has finished loading, and it will call the loadMsg() function for us, displaying our message boxes as needed. And that’s all there is to it! You can see a functioning example here.

Now, I did want to mention a couple of things before you try this on your own:

  • I’ve built this example specifically to make it work with multiple message boxes. Otherwise, it would have been easier and faster to reference our message box by its ID in our loadMsg() function.
  • This obviously only works if your users have JavaScript and cookies enabled. If they have JavaScript turned off, they won’t see a message box. If they have cookies turned off, they won’t be able to get rid of your message box. And I don’t know of a good way around this usability problem. That’s just the way the cookie crumbles.
  • You could achieve this same functionality in about half the space using a JavaScript framework. I have nothing against frameworks generally, but I do have something against forcing your users to download 50KB+ of JavaScript if you’re only going to use 1KB (or less) of it. For some things, frameworks make sense. For others, it’s better to just write it by hand.

But enough from me… I want to hear what you have to say about this technique. Leave me a comment!

Harnessing CSS Positioning: Part 1

racehorse in mid-run

Earlier this week, I explained the basics of CSS positioning: what it is and what your options are. Now I’d like to take some time and explain a couple of tricks for using positioning in the real world… stuff that really harnesses the true power of CSS positioning.

Absolute Positioning Inside Relative Positioning

One of the coolest and simplest ways to harness the power of positioning is to use a combination of relative and absolute positioning. Specifically, to absolute position an object inside of a relatively positioned object. Why is this so cool? Because of one of the under-understood rules of positioning.

Any time an element is absolutely positioned, it’s actually being positioned according to the boundaries of its containing block. By default, with no other objects positioned on the page, the containing block is the <body> tag. However, if you position any element further down in the hierarchy (like a containing div, for example), that positioned element becomes your new containing block. What’s that mean in practice? It means you can have some XTHML that looks like this:

<div id="wrap">
	<p>This stuff is in the wrapper</p>
	<div id="sidebar">
		<p>Sidebar information is cool</p>
	</div>
</div>

Then, you can size and relatively position your wrapper div, like so:

#wrap {
	width: 500px;
	margin: 0 auto;
	position: relative;
}

Here, all we’re doing is giving it a width, centering it with an auto margin trick, and then setting a relative position. But we’re not actually moving the div anywhere! Setting a relative position, but then not setting a top, bottom, left or right property means the element doesn’t move anywhere. But, because it has a “position” set, it becomes our new containing block. Now, we can specify styles on our sidebar that look something like this:

#sidebar {
	position: absolute;
	top: 0;
	right: 0;
}

As we learned last week, setting our top and right properties to zero, with an absolute position, should move our sidebar to the top-right of the page. However, because our wrapper div became our new containing block through use of the relative position, the sidebar is actually just moved to the top-right corner of the wrapper div. This can be extremely useful when you have a fixed-width and centered web page: you may want to absolutely position elements according to your “page,” but not according to the browser window. This is how that’s done. You can see a slightly more involved example here.

Fixed-Position Navigation

If you have a website that tends to be a bit on the wordy/lengthy side (like, erm… this one?), it could be useful to ensure that the site’s navigation is always at the top of the page, no matter how far down your users scroll. For that, fixed positioning can really come in handy.

For this trick, all you need to do is develop a navigation bar of some sort (covered in more detail here), and then “fix” it to the top of your website. You’d start out with some XHTML like this:

<div id="wrap">
	<ul id="nav">
		<li>Home</li>
		<li>Contact</>
		<li>Etc</li>
	</ul>
	<h1>Page Title</h1>
	<p>This page is cooler than it looks.</p>
</div>

Next, you’d want to pull your “fix” your navbar to the top of the page:

#nav {
	position: fixed;
	top: 0;
}

And really, that’s the meat of your code. The fixed position tells the browser to pull the navbar out of the normal document flow, and then affix it to the top of the page. Of course, because it has been taken out of your document flow, the navbar might be overlapping your text, which will move up the page to fill the space that the navbar has vacated. To ensure that doesn’t happen, you’d want to add some space to the top of your website. Something like this would do the trick:

#wrap {
	/* Your padding should be the height
	of your navigation bar, plus the
	space you want between the navbar
	and the top of your page. */
	padding-top: 50px;
}

As the comment above states, you’ll want to add enough padding to compensate for the height of your navbar, as well as any extra spacing you want between your navbar and the content below. So if your navbar were 30 pixels tall, and you wanted 20 pixels of space before you got to your header, you’d want 30 + 20 = 50 pixels of space at the top.

And voila! You now have a navigation bar perma-fixed to the top of your browser window. No matter how far down your page your users scroll, your navigation will never be more than a few pixels away. You can see it in action here.

These are just two ways in which the position property can really make your life easier, your websites cooler, and your wife more satisfied. Stay tuned, because next week I’ll show you a couple of other neat positioning tricks: one for creating big visual impact with absolute positioning, and another for making subtle (but useful!) text changes using relative positioning.

Create a Microsoft Word-Style Outline with CSS

Sample outline created in HTML and CSS

One of the most useful properties of both unordered lists (which we fancied up earlier this week) and ordered lists is their ability to nest — that is, to contain lists within lists. And one of the most common examples of a nested ordered list in the real world (or at least, in my world) is an outline, be it a resume, a research paper, or something else entirely. But by default, the web doesn’t lend itself to really attractive or useful outlines… they tend to look something like this:

  1. First item

    1. Indented item
    2. Another indented item
      1. Indented triple!
  2. Not indented as much

As you can see, the browser doesn’t bother to vary the indentation style much, or change the list type from roman numerals to alphabetical characters and so on… all the things we’re so used to seeing because Microsoft Word and other writing programs do them by default. So let’s use a bit of CSS ingenuity to make a Microsoft Word-styled outline using ordered lists!

Before I started crafting this tutorial, I first took a look at what a default outline looks like when built in Microsoft Word 2003. Here’s a screenshot of that sample outline. This, my friends, is our goal.

The first step to building this outline in CSS is to properly nest your unordered list. It should look something like this:

<ol>
	<li>First Things First
		<ol>
			<li>Firstborn Children</li>
			<li>First Place Finishes</li>
		</ol>
	</li>
</ol>

As you can see from the code above, in order to properly nest lists, you need to place the sub-list inside of the list item you want it to be a subset of. So we’ve started an ordered list, opened our first list item, and then added an entirely complete ordered list to the mix before we close that list item.

Now that we know how to build the list, all we need is the CSS. For this, we’ll be using the list-style property along with a set of increasingly specific selectors for our rules. Our first rules look like this:

ol {
	list-style: upper-roman;
	margin-left: 2.25em;
	padding: 0; }
li {
	padding-left: 2em; }

These rules do a few things. The list-style property tells all of our ordered lists to use roman numerals instead of numbers. The margin and padding on the “ol” tag indents our list a respectable amount: specifically setting both margin and padding makes IE behave just like the other browsers, because IE indents lists using padding by default while all other browsers use margins. And last but not least, our padding-left on the list item adds some space between our roman numeral and the text, just like in our example outline from MS Word.

However, this CSS gets applied to all of our unordered lists, not just the first one. So we’ll need to use a set of increasingly specific selectors in our CSS to create the appropriate look. Here’s the full CSS for a complete four-level outline:

ol {
	list-style: upper-roman;
	margin-left: 2.25em;
	padding: 0; }
ol ol {
	list-style: lower-alpha;
	margin-left: 1.25em;}
ol ol ol {
	list-style: lower-roman;
	margin-left: 2.5em; }
ol ol ol ol {
	list-style: decimal; }
li {
	padding-left: 2em; }
li li {
	padding-left: .4em; }
li li li {
	padding-left: 0; }

Here, the “ol ol” rule means “only apply this style to ordered lists within ordered lists,” and “ol ol ol” does the same for third-level lists, and so on. As you can see, we’re setting the list style to lowercase alphabet on the 2nd level, lowercase roman numerals on the 3rd, and regular numbers on the 4th. We’re also adjusting the margin on the 2nd-4th levels of the list (and 2nd – 3rd levels of the list items) to make them more consistent with Word’s display. If you wanted to adjust them to something different, it’s a simple matter of changing the number of ems in the margins or padding.

After the 5th level, Microsoft Word simply cycles back through the same styles starting at the 2nd level, so if you wanted an outline more than four levels deep, you could just do something like this to save bytes and effort:

ol ol, ol ol ol ol ol {
	list-style: lower-alpha;
	margin-left: 1.25em;}

And that’s all there is to it! Here’s our completed example, complete with a little extra styling just for kicks to make it look more like Microsoft Word’s print layout (my editing layout of choice). If you’re interested, here’s the CSS I used for creating the print layout look:

body {
	background-color: #9099ae; }
#wrap {
	background-color: #fff;
	margin: 0 auto;
	width: 33em;
	border: 1px solid #000;
	border-right-width: 3px;
	border-bottom-width: 3px;
	padding: 5em 6em;
	font-family: "Times New Roman", Times, serif; }

And the best bit? This styling works pretty much everywhere: Firefox, Opera, Netscape, Safari, and even Internet Explorer 5.5 and up all behave themselves! (IE 5.5 ignores our “auto” margin in the print layout view, but it still gets the outline part right)

So now you can go out into the world, head held high, confident in your abilities to organize the myriad lists of the web into visually appealing outlines with wild, voracious abandon. You know… if that’s your sort of thing.

Book-style Chapter Introductions Using Pure CSS

Do you remember all those wonderful hand-me-down children’s books from your childhood, or perhaps those dusty old tomes you’ve leafed through at a used bookstore recently? I still like looking through old books of Days Gone By. Their typefaces, in particular, give me a warm fuzzy feeling in the far reaches of my tummy. The scripty drop-caps at the beginnings of chapters, and the first line of small caps leading into the first full paragraph, in particular, fill me with all sorts of nostalgia.


So today’s tutorial will show you how easy it is to create book-style chapter (article, whatever) introductions using nothing but pure CSS — no XHTML was harmed in the making of this tutorial. We’ll use two types of selectors which I haven’t talked about yet here: adjacent sibling selectors and pseudo-element selectors. I’ll explain each type briefly before we get started.

Adjacent Sibling Selectors are a way of styling an element that appears directly adjacent to another element. So, for example, if you knew that the first paragraph to follow an image in your XHTML was always going to be a caption, and you wanted that styled differently, you could write something like this:

img + p {
	color: #999;
	font-style: italic;
} 

This would turn the paragraph immediately following the image gray and italicize it, all without any extra code in your XHTML.

Pseudo-Element Selectors refer to parts of your XHTML that aren’t technically elements of their own right, but can be easily distinguished from the surrounding code due to their nature. The most common two pseudo-elements (and the two we’re using here) are :first-letter and :first-line.

Creating a Book-Style Introductory Line

So what we need to do to create our book-style line is create a drop-cap of the first letter, and the rest of the first line in small caps. And we want to do it without having to resort to classes or IDs to get it done. What we’re assuming in this exercise is that your XHTML is already well-formed – your articles or chapters always start with a heading tag (I’m using <h4> tags), and you’re using paragraph tags instead of (shudder) line breaks. So here’s how we do it:

You’ll start with some fairly simple XHTML that looks something like this:

<h4>Article Titles for Fun and Profit</h4>
<p>This is our first paragraph. Don’t you think
the first line should stand out?</p>
<p>Our second paragraph doesn’t need such
fancy-pants styling.</p>

And then we’ll use CSS to style the first line of the first paragraph following our 4th level heading:

h4 + p:first-line {
	font-variant: small-caps;
	font-size: 1.1em;
}

This gives us a small-capped line that is slightly larger than the rest of the surrounding text. Now, all we need to do is create our drop cap:

h4 + p:first-letter {
	float: left;
	font-size: 2.5em;
	font-weight: bold;
	font-family: "Monotype Corsiva",
	"Apple Chancery", fantasy;
	margin: 5px 5px 5px 0;
} 

Here, I’ve floated the letter to the left (which causes the rest of the text to flow around it), increased its size, made it boldface, set it in a scripty font (you could chose any font here, but I was going for a bookish look), and added a bit of a margin to make sure there isn’t any overlap.

We’ve managed to create an introductory line without a single byte of XHTML.

And that’s all there is to it! You can see a finished example here. We’ve managed to create an old-school book-style introductory line without adding a single byte of XHTML. This is a quick and easy way to add some visual appeal to your articles. It could even make for an interesting addition to a print style sheet, adding a bit of classic authenticity.

Now, I have one caveat: this does not work in IE6. But the text simply degrades nicely into an otherwise unaffected first line. No harm, no foul.