Don’t Fear JavaScript, or why libraries should understand progressive enhancement

I recently redesigned one of our hosted services, and the vendor was afraid of JavaScript. It’s no wonder; for years, developers used JavaScript to build sites that wouldn’t work unless JavaScript was enabled.1 Some of those developers even did nasty things with JavaScript, so it ended up with a bad reputation. But JavaScript isn’t inherently bad. Used as the basis for a philosophy of progressive enhancement, it can be a developer’s best friend. Here’s how to use JavaScript to responsibly enhance your library’s website.

Progressive Enhancement

I start every webpage with semantic HTML. No CSS, no JavaScript, no thought to presentation. I just make it well-structured in HTML. After I have a semantic page, I go back through and write separate CSS. Here I’ll add classes and wrap content in divs to help with presentation, but I never make a change to the structure that doesn’t fit with the semantic nature of the document. After I’m done with the presentation, I go back through and add any interaction JavaScript. I never put JavaScript inline in the HTML document. I include it all in a separate file, so that JavaScript is not required to read the content or interact with the forms. After all, I want each of these layers, semantics, presentation, and interaction, to be separate. As the user’s device supports more features, I progressively enhance the experience.

Example of the Big Stuff: Getting Animated

When I met with our Scholarly Communications team to tart up our institutional repository, it became clear that the IR’s homepage would primarily be a marketing tool to entice faculty and departments to get on board with Open Access2. I suggested a slideshow of images to highlight faculty who are already depositing their work in the IR. Not only would this serve as a great and highly visible marketing tool for the Scholarly Communications, but it would help to break up a text-heavy website that serves as a repository for text-heavy articles.

For the slideshow, I chose jQuery, a powerful JavaScript library, as well as Mat Marquis’ responsive carousel. The script works by taking an unordered list of images and showing one at a time, animating the transitions between images. As you can see, the markup is nice and semantic.

<ul>
    <li><img src="img/image1.jpg" alt="Professor Smith presenting at Awesome Conference 2011" /></li>
    <li><img src="img/image2.jpg" alt="Students being studious" /></li>
    <li><img src="img/image3.jpg" alt="Professor Jones with her nose buried in a book" /></li>
</ul>

There is a downside to this, though. If JavaScript isn’t available, this is what you get:

Images bunched on top of each other when JavaScript isn't available

The unordered list is displayed as just that: a list of images. This creates an incongruous pile-up of images that confuses users. So how can we address this consequence of using JavaScript? Is it by running in fear? No. The answer is JavaScript3.

Since the slideshow will only work when JavaScript is available, why not make the unordered list available only when JavaScript is available? Using jQuery, this is a piece of cake. Instead of hard-coding the list into our homepage, we’ll add an appropriate element for non-JavaScript browsers and then replace it with JavaScript if we can.

I decided to use the first image in our list as the “non-JavaScript” fallback, since semantically a slideshow is just one image at a time and visually the design would be unchanged. This is the markup:

<div id="slideshow-image"><img src="img/image1.jpg" alt="Professor Smith presenting at Awesome Conference 2011" /></div>

<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat...</p>

This is nice, semantic markup, and using CSS, we’ll make it look sharp. But when JavaScript is available, we want to change the markup to work with the slideshow. Using jQuery, we simply need to include the following code in our script:

$(document).ready(function() {
    $("#slideshow-image").html('
        <ul class="slidewrap">
            <li class="slide"><img src="img/image1.jpg" alt="Professor Smith presenting at Awesome Conference 2011" /></li>
            <li class="slide"><img src="img/image2.jpg" alt="Students being studious" /></li>
            <li class="slide"><img src="img/image3.jpg" alt="Professor Jones with her nose buried in a book" /></li>
        </ul>');
});

Now the content of the slideshow-image div will be replaced with the HTML above4. Add in the code to animate the slideshow, and we have a seamless enhancement for users who have JavaScript-enabled browsers. It’s a win on the semantic level, a win on the presentation level, and a win on the interaction level. Everyone gets a version of the page most appropriate to their browser’s abilities. It’s like the Web version of a Montessori school.

The “Small” Stuff: Accessibility

This method of layering JavaScript over semantic HTML is used throughout our site. We use it for high-impact things like slideshows and our drastically simplified link resolver, but we also use it for small things that make accessability a priority while not shackling great presentation. One example of the latter is our Summon search bar, present at the top of every library webpage.

Summon Search Box at Grand Valley State University Libraries

To be semantically correct and accessible, this input field needs a label, but visually, we want to use placeholder text to replicate the label. So we used progressive enhancement to solve these seemingly conflicting needs. I see four scenarios I needed to account for:

  1. Browser with native placeholder and JavaScript support
  2. Browser with JavaScript support but no placeholder support
  3. Browser with neither JavaScript nor placeholder support
  4. Browser with placeholder support but no JavaScript support

First, we started with semantic HTML:

<div id="summon-search-box">
    <label for="search" id="summon-label">Find Books, Articles, and more</label><br />
    <input name="search" placeholder="Find Books, Articles, and more" type="text" />
</div>

Here is what we need to do in each scenario:

  1. Hide the label, since placeholder support will show the text the way I want it.
  2. Hide the label and use JavaScript to patch placeholder support.
  3. Nothing. The label will be visible and will remain semantic.

In the last scenario, there isn’t much we can do. We’ll have both a label and a placeholder visible. In our case, this rarely ever happens, so I didn’t worry about it. In any case, the form is still functional, there is just label redundancy. I decided I could live with it. So the presentation and interaction work needed to focus on the first two scenarios.

In both of the scenarios when JavaScript is available, we need to hide the label. So I started with this jQuery:

$("#summon-search-box").find("label").hide();

That takes care of the first scenario. For the second scenario, I detected placeholder support with the JavaScript library Modernizr. If placeholder was not supported, I used a script to look for placeholder text and swap it out to the value until the input is focused on. This duplicates the functionality of the native placeholder text. The code I used was written by Nico Hagenburger, and it works great. The full code is below:

if(!Modernizr.input.placeholder){ 

    $('[placeholder]').focus(function() {
      var input = $(this);
      if (input.val() == input.attr('placeholder')) {
        input.val('');
        input.removeClass('placeholder');
      }
    }).blur(function() {
      var input = $(this);
      if (input.val() == '' || input.val() == input.attr('placeholder')) {
        input.addClass('placeholder');
        input.val(input.attr('placeholder'));
      }
    }).blur();
    $('[placeholder]').parents('form').submit(function() {
      $(this).find('[placeholder]').each(function() {
        var input = $(this);
        if (input.val() == input.attr('placeholder')) {
          input.val('');
        }
      })
    });
}   

So we can give our users engaging, rich experiences on the Web without breaking our sites for people with less-capable browsers (including many mobile phones). We just have to get over that irrational fear.


  1. Summon, I’m looking at you. 
  2. Most of our IR traffic comes from Google directly to the PDF stored in the repository. Of the rest, I suspect a significant portion are “vanity searches,” with GVSU faculty searching for either their own work or for the work of colleagues. 
  3. Sadly, the vendor was too afraid of JavaScript to let me use any of the code I wrote, so were stuck with a crummy, ugly slideshow that doesn’t have a semantic HTML fallback for non-JavaScript users. (I’m not sure how that is better, but after 4 months of arguing with them, I gave up. You pick your battles. 
  4. I know jQuery has replaceWith, which would allow me to eliminate the div, have the id on the img tag, and then just swap out the HTML, but support for replaceWith is spotty in IE7 and below. And we’re in academia, where IE7 sometimes seems like the cutting edge. Oi vey. 

There is a Serbo-Croatian translation of this article, thanks to Anja Skrba