Archive for March, 2008

Using CSS3 :target selectors

Friday, March 14th, 2008

This is a quick post to present a JavaScript that provides CSS3 :target pseudo selector like functionality for browsers that do not provide native :target support.

function() {
    var cssClass = 'target';

    // Initialise targeted fragments if any.
    var target = document.getElementById(window.location.hash.slice(1));
    if (target) {
        target.className += ' ' + cssClass;
    }

    // Click event handler function generator. This is passed a "frag" argument
    //   that is a reference to the target element.
    var reCSS = new RegExp("\\b" + cssClass + "\\b");
    function newTargetClickHandler(frag) {
        return function() {
            if (target) {
                target.className = target.className.replace(reCSS, '');
            }
            target = frag;
            target.className += ' ' + cssClass;
        }
    }

    // Run thru <a> elements and add an onclick handler to those that reference
    //   document fragments within the current page.
    var reURI = new RegExp('^' + window.location.href.match(/^[^#]+/)[0] + '#([^#]+)$');
    var elems = document.getElementsByTagName('a');
    for (var i=0; i<elems.length; i++) {
        if (elems[i].href && elems[i].href.match(reURI)) {
            elems[i].onclick = newTargetClickHandler(document.getElementById(RegExp.$1));
        }
    }
};

When the user clicks on a link that points to a fragment within the current page, this code will add a CSS class of “target” to the targeted element, and will remove the same “target” class from any previously targeted element.

Originally I was using the CSS3 :target pseudo selector and the .target class selector together in the same rule set, but I found that Opera (9.26) would not apply the rules presumably because it considered it invalid.

/* THIS DOES NOT WORK! */
h2:target,
h2.target {
    color: red;
}

I’m not sure if this is correct behavior, but regardless of cause, I found I had to use a duplicate set of CSS rules; one for both modes of selection.

h2:target {
    color: red;
}
h2.target {
    color: red;
}

And basically… that’s it! You can see it in action on this test page, and I hope to add a follow up post soon…. time allowing.

You download the the JavaScript here:
Full-fat script with white-space and comments [1621 bytes]
Minified script [1101 bytes]