Introducing MBN DuoTone Headings

Posted: July 15, 2006 Comments(13)

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

Slight minor modification by: Jon Christopher                   */

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];
    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');
                 span.innerHTML = hString;


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 {
    position:relative; }

.monday span {
    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.

Get my newsletter

Receive periodic updates right in the mail!

  • This field is for validation purposes and should be left unchanged.


  1. I realize that this article was posted a couple days early — allow me to explain.

    I spent most of the day error checking my email reminder plugin and performing some tests on it to make sure things were working properly. I had a bit of trouble with spammers using the email address input to include actual spam emails and sending thousands of emails on behalf of my Web host. I didn’t like that very much so it has been disabled for some time.

    Today I was able to fix the glitch and after doing that finished writing up this weeks article. I had it completed a bit early this week so I figured I’d give myself Sunday night off and go ahead and publish a couple days early this week.

    So all in all, the article is posted early and the email reminder plugin seems to be working just fine — I hope you enjoy the read!

  2. Great job and a very interesting idea. I shudder with great intensity at the thought of how this will be abused, but that is obviously not your fault. 🙂

    Nice work.

  3. @P.J.: I definitely understand your concern, and have to agree with it. On the other hand, it could be used really effectively and responsibly for some client sites that are asking for a little something extra, you know?

  4. I’m actually not quite sure about this. Sure, it’s a very nice effect and all, but still, the reason why the CSS+(X)HTML/XML+DOM-scripting combo is so good and powerful is because you separate the Content(Markup), Presentation(CSS) and the Behaviour(DOM-Scripting). This is presentational, so shouldn’t it go into the css?

    I know lots of people frown upon excessive markup, but I often feel that more markup (divs/spans ARE logical separators, so if you feel that there is some logic behind giving each pixel on your site its own DIV then you arent really doing anything wrong, except for creating a tag-soup) to be able to control the presentation via the CSS is far better than using DOM-Scripting for it.

    Take for example all rounded corners javascripts out there, they are using the Behaviour-layer to add presentational information – I just think it’s wrong when you have a language for that already. It’s not CSS’ fault that browesers havent catched up with the specs. (ok css3 isnt finished yet but w/e, my point is still valid).

    I like your explaination of DOM-scripting though, I’m definatley going to learn some more when I have the time.

  5. @Fredrik: You know, you bring up a really great point and I hadn’t really thought about it exactly like that. While not directly effecting the presentation of the document, the script’s only purpose is to support styling in the next step. I’m not sure that it’s a bad use of the technology, but it isn’t clear cut. The script isn’t effecting the presentation per se, it’s modifying the document so that the CSS can apply the effect. Thanks for the input I hope everyone that comes across this article takes it as advice.

  6. Great article Jon. I will agree with you that since you are not actually adding style to the document, just a class, you don’t mix behaviour with style. That last addition not to add the markup if it isn’t supported is a great addition and something many would forget about.

    (By the way, mind making the comment text a bit darker? It’s very hard to read it with this littel contrast against the background (especially in the textarea when writing a comment))

  7. @Emil: I’m glad to see you decided to stop by the site! Regarding the comment color — consider it changed. Thanks for taking the time to mention something like that.

  8. This is an area I have had some interest in for some time, but haven’t yet tested it.
    I have a few questions:
    1. Is this sIFR, as talked about over mikeindustries .com?
    2. Can the JS be referenced externally, like we do with CSS? ie, @import(etc…
    3. Is what you are describing similiar to whats being used as
    This is an amazing area that certainally allows designers to use more fonts than the web-standards.

  9. @P.J.: Thanks for the compliment — much appreciated.

    @stephen: No, this isn’t sIFR, and you can’t use non-standard Web fonts. sIFR is a much more complex and advanced technique — this is simply an effect to be placed upon site text. Yes, the JS is referenced externally, just to clear things up. I checked out iiNet’s site and I’m not sure which part you’re referring to — mind replying with which page?

  10. @moose: I’m really glad you brough that up. A solution to the print problem would be to use a print stylesheet and set the span to display:none. I’m not too sure that there’s a way around the copy and paste problem, though. Thanks for commenting!

Leave a Reply

Your email address will not be published. Required fields are marked *