Introducing MBN DuoTone Headings

One thing that JavaScript is absolutely great for is enhancing the average browsing experience for your user. On the other hand, requiring the presence of JavaScript compatibility can be an utter disaster. In my opinion, JavaScript is great for visual or functional enhancements, but those features should not be necessary to make proper use of any particular document. If a user doesn’t arrive equipped with the ability to run JavaScript, they shouldn’t know they’re missing out on anything.

MBN DuoTone Headings Demo

If you were to take a close look at the example heading in a browser supporting both JavaScript and CSS, not only would you realize it’s actually comprised of two colors, you would see that it isn’t using any images to create the effect. Further inspection would show you that the following code was used to insert the heading:

<h2 class="monday">To Make an Example</h2>

So what is creating the heading above? To put it simply; that line of HTML, a bit of CSS, and some manipulation of the DOM using JavaScript.

How does it work?

One of the major benefits to DOM scripting is the fact that it will degrade gracefully and allow a user without JavaScript the ability to continue proper use of the document he or she is viewing. When it comes to the MBN DuoTone Headings, a user without a JavaScript compatible browser isn’t going to know they’re missing out on a two colored heading. As stated above, this technique is purely for the visual enhancement of the average browsing experience.

If you’re able to see the DuoTone Heading above, it means that a script was able to scan through the markup of this document looking for headings given a certain class. The script searches for the class because when it comes to headings, a designer or developer will often want to use the same style repeatedly. Using the id would restrict use of the effect. When the script finds any heading with this particular class, duplicates the original content with an additional span. This change is made by manipulating the DOM, so those viewers who are browsing without JavaScript support will only see the original heading markup. This is ideal because if the additional markup was present no matter what, viewers without JavaScript would see duplicate content for each header which would be very confusing.

Once the script has run its course, the style sheet is applied to the document and you are left with MBN DuoTone Headings. A lot can be done with this technique as far as the CSS is concerned. You can see a few other implementations by looking at the MBN DuoTone Headings Example Page.

Under the Hood

To implement MBN DuoTone Headings, a small piece of JavaScript will be needed. The first challenge was to insert a function that would locate each instance of a certain class within the markup. Basic DOM scripting provides a method to find an instance of an element based on its id, but not by its class. Luckily, Dustin Diaz, JavaScript connoisseur that he is, had written getElementsByClass and Jonathan Snook had written one too. Thanks to the function and a slight modification, we have the location of each heading with a class of “monday” using the following code:

/* Credit Where Credit is Due

getElementsByClass Written By: Dustin Diaz
      http://www.dustindiaz.com/getelementsbyclass/

Slight minor modification by: Jon Christopher
      http://www.MondayByNoon.com                   */

function getElementsByClass(node,searchClass,tag) {
    var classElements = new Array();
    var els = node.getElementsByTagName(tag); // use "*" for all elements
    var elsLen = els.length;
    var pattern = new RegExp("\\b"+searchClass+"\\b");
    for (i = 0, j = 0; i < elsLen; i++) {
         if ( pattern.test(els[i].className) ) {
             classElements[j] = els[i];
             j++;
         }
    }
    return classElements;
}


function showSpans() {
if(document.getElementsByTagName && document.createElement){
    for (var l=1;l<=6;l++){
    var headingArray = getElementsByClass(document,'monday','h'+l);
        for ( var i=0, len=headingArray.length; i<len; ++i ){
             var heading = headingArray[i];
                 var hString = headingArray[i].firstChild.nodeValue;
                 var span = document.createElement('span');
                 heading.appendChild(span);
                 span.innerHTML = hString;
        }
    }
    }
}

window.onload=showSpans;

This particular piece of JavaScript is using window.onload so if you plan on implementing MBN DuoTone Headings on your own site, make sure it won't be interfering with other scripts you may have running.

The script will loop through every heading found and insert a span just after the heading content. Within the span, a duplicate copy of the content is inserted. That's the only purpose this script serves and it's all we need it to do, the rest is up to the CSS.

The Style Sheet

Giving any heading level a class of "monday" in the original markup will trigger the effect. As stated before, a span with duplicate content is inserted next to the original heading content. The following styles are then applied:

.monday {
    color:#369;
    position:relative; }

.monday span {
    color:#497eb2;
    height:0.55em;
    display:block;
    position:absolute;
    top:0; left:0;
    overflow:hidden; }

The heading itself is given a position:relative which acts as a reference point for the span. The span is styled with position:absolute, positioned to the top left of the heading and given a height of 0.55em. Using em will render as half of the parent elements font size, which is essential for the technique. Setting display:block and overflow:hidden allows us to cut the span in height to create the DuoTone effect. Setting a different color to the span and its parent heading finishes the technique.

There are more effects you can generate by changing up the CSS a bit, some of which you can see on the MBN DuoTone Headings Example Page. You can download a zipped version of the example page below:

Download MBN DuoTone Headings

Hasn't this Been Done Already?

At the time of thinking up the idea for developing this script into something useful, I wasn't aware that Stu Nicholls had beat me to the punch by quite some time and showed off his own technique for two-color headings. While disappointed I wasn't the first to come up with the idea, I felt it was still a worthy subject to touch upon. Unfortunately, Stu Nicholls' two color headings reduce to a one color heading in Internet Explorer 6 using the star hack. My testing so far has shown me that MBN DuoTone Headings render correctly in IE6. I have also tested in Firefox, Opera and Safari and things seem to render correctly. If anybody finds otherwise, please post your findings below.

Semantics of this Technique

As always, semantics come first when it comes to enhanced effects using JavaScript, CSS, or any other technology. As I had stated above, the semantics in this example weren't compromised. Manipulating the DOM allows us to only insert the extra markup if support is available. One pitfall to the technique would be if the user had JavaScript support, but no support for CSS. Although uncommon, it is a certain possibility and should be taken into account.

If you were to browse this example page using a text based browser such as Lynx you're faced with the following:

Viewport of MBN DuoTone Headings using Lynx

The extra markup is not included if support isn't present. A user viewing your document with a screen reader isn't going to have to deal with hearing each heading twice before moving on and you would be faced with the same result had you been navigating the document without JavaScript support.