Expand A Container With jQuery and a URL hash

A while back I was trying to devise a way to make a section of a page expand or “reveal” without having to direct users to an individual page for each piece of information I was delivering. I was unable to find a definitive method for doing this in a simple way, so I consulted with my trusty sidekick jQuery. What I ended up with was a simple, elegant way of revealing portions of page content when the user went to a URL appended with the hash ID of the element to be revealed.

Before we get started

Before anything else, we need to hide the definition descriptions (dd) from the user. We can do this with one fell swoop. All that is required is some simple jQuery.

$('dd').hide();

Grabbing the URL

This small string of code will traverse the current URL of the open page and find only the hash at the end. The hash is what matches to the ID of the container you want to reveal. We’re going to make a var out of it since we will be using it more than once:

var url = self.document.location.hash.substring(1);

Using the URL

Now that we’ve grabbed the URL’s hash, this is going to be what makes the whole thing function. Since the URL also represents the ID of the container we want to reveal, we’re going to map it to some jQuery effects–primarily slideDown and addClass. The advantage of this is that a little extra work and experimentation allows you to use various effects and DOM manipulations. I decided to keep it simple:

The slideDown effect — This will go to the immediate dd after its corresponding dt. Using a definition list proves most effective since a definition term is always accompanied by its definition description immediately after.

$('dt[id=' + url + ']').next('dd').slideDown('fast');

Now we add the class “active” (optional but has a cool effect and helps the end user).

$('dt[id=' + url + ']').addClass('active');

Now we’ve got the major functions out of the way. The next step is to make the dt elements clickable so that the end user can expand and collapse each corresponding dd as they see fit:

$('dt').click(function () {
	$(this).toggleClass('active');
	$(this).next('dd').slideToggle('fast');
});

The toggleClass will do exactly what it suggests. It will add and remove the specified class on the corresponding element when it is clicked or interacted with. This is one single effect, as opposed to doing something like removing the class on mouseout and adding it on mouseover. The .next() will apply the slideToggle effect to the dd immediately after the corresponding dt. Simple and effective. If you aren’t keen on using a definition list, you can always use div containers or whatever else.

Now we’re going to add some extra controls just because we can (and because it’s super easy). The first one will collapse all dd within the definition list. First, we need to have an href tag that has the class hideall. I used classes for these in case we want to have some controls at the top and bottom (good idea if you have a lot of content blocks that you want to apply this functionality to).

<a class="hideall" href="#">Collapse All</a>

And this is the jQuery function that makes it work.

$('.hideall').click(function () {
	$('dd').slideUp('fast');
	$('dt').removeClass('active');
});

Now we have our expand control.

<a class="showall" href="#">Expand All</a>

And the function that makes it work.

$('.showall').click(function () {
	$('dd').slideDown('fast');
	$('dt').addClass('active');
});

Simple enough. These last two controls are completely optional but also helpful. If the end user expands a bunch of the expandable boxes and they don’t want to close them each individually, they can hit the “Collapse All” button and they’re all set. Here is what our finished javascript looks like.

$(document).ready(function(){
	// get the URL hash
	var url = self.document.location.hash.substring(1);

	// hide all dd on initial page load
	$('dd').hide();

	// expand id via url hash
	$('dt[id=' + url + ']').next('dd').slideDown('fast');
	$('dt[id=' + url + ']').addClass('active');

	// make items expandable and collapsible on click
	$('dt').click(function () {
		$(this).toggleClass('active');
		$(this).next('dd').slideToggle('fast');
	});

	// hide all
	$('.hideall').click(function () {
		$('dd').slideUp('fast');
		$('dt').removeClass('active');
	});

	// show all
	$('.showall').click(function () {
		$('dd').slideDown('fast');
		$('dt').addClass('active');
	});
});

If you want to see this in action, check out my demo.

This method is really easy to manipulate and can be repurposed to do a lot of things. I’ve had this tool in my back pocket for quite a while and have been meaning to share it. I hope you find it useful and let me know what you come up with.

URL Hash Reveal v1.0

The tutorial files for my jQuery URL hash content revealer.

Download

5 Responses to “Expand A Container With jQuery and a URL hash”

  1. Geoffrey

    Safari 5 doesn’t pass the hash, apparently. The browser stubbornly refuses to display “/#one” etc in the URL field, and renders the links to each item non-functional. The toggleClass on dt click works fine though. Just and FYI. Using Safari 5.0.5, same problem observed in 5.0.3.

    Just an FYI.

    Reply

    • Daryn

      Thanks for the heads up, Geoffrey. I hadn’t even tested it in Safari yet but it works properly in Chrome and Firefox. Maybe there’s some kind of workaround that I can devise for Safari.

      Reply

  2. Matti

    Is it possible for this script to open the dd from the URL. Eg if I put the URL to the hash into the address bar could it open this dd?

    Reply

    • Daryn

      @Matti — I’ve found that if I’m currently on the page and I type in the hash myself, it doesn’t go to the associated container, nor does it work when you click on the URL (this is new to me. I think I had it working before). This is something I have on my todo list. If you type in the hash at the end of the URL and then refresh the page, it seems to work. So it’s only working on the initial page load.

      Currently I have it setup so that if the user clicks on the URL with the appended hash, via a page elsewhere, while they’re on the page they can just click on the dt to collapse the corresponding dd. This worked well for my implementations but it’s kind of incomplete.

      Reply

Leave a Reply