Progressive Enhancement with jQuery

Hero image for Progressive Enhancement with jQuery. Image by Tomás Mendes.
Hero image for 'Progressive Enhancement with jQuery.' Image by Tomás Mendes.

Progressive enhancement is not antiJavaScript. It is a way of deciding what JavaScript is allowed to be responsible for.

jQuery makes it very easy to reach for a selector, attach an event, hide a piece of markup, animate something, and call the job done. That ease is useful, but it can also hide a basic question: what happens if the script fails, arrives late, or does not run in the browser at all?

For small marketing sites, campaign pages, brochure sites, and CMS templates, the answer should not be "the page stops working". The core page should still be readable. Links should still go somewhere. Forms should still submit. Navigation should still expose the important pages.

jQuery can sit very nicely on top of that base if it is treated as an enhancement layer rather than the only way into the content.


Start with Usable HTML

The first check is boring, which is usually a good sign.

Open the page with JavaScript disabled and ask whether the user can still do the important thing:

  • read the main content
  • follow the main navigation
  • submit the important forms
  • see validation messages from the server
  • reach content that is hidden in tabs, accordions, or drawers

If a tabbed interface contains content that only exists after an AJAX request, that content has become JavaScriptonly. If the markup contains all of the content and jQuery merely changes how it is displayed, the page has a much better baseline.

That does not mean every enhanced interface has to look identical without JavaScript. A set of tabs might become a stack of headings and sections. A menu might become a simple list of links. Visual parity matters less than keeping the information and actions available.


Use jQuery to Improve Behaviour, Not Replace Structure

Good progressive enhancement usually follows a simple order:

  1. Write semantic HTML that works.
  2. Add CSS that presents it clearly.
  3. Add jQuery that improves interaction.

A link should be a real link before jQuery intercepts it. A form should have a real action and method before AJAX submission is added. A button should be used for an action, not a link with href="#" and a click handler.

The article on handling click events in JavaScript covers the mechanics of event handling. With progressive enhancement, the more important question is whether the event handler is improving something that already exists.

If the handler is the only thing making the page work, it deserves more scrutiny.


Add Classes from JavaScript Deliberately

One useful pattern is to add a class to the document once JavaScript is available.

The default CSS can expose the content in a simple way. Once jQuery runs, it can add a class such as js to the html element. Enhanced CSS can then hide panels, initialise carousels, or collapse navigation only when JavaScript is present.

That approach avoids a common failure: hiding content by default in CSS and relying on JavaScript to reveal it. If the script fails, the content stays hidden. That is not progressive enhancement. It is an accidental blank page.


Keep Event Binding Resilient

jQuery's .on() API supports both direct and delegated event handlers. Delegation is often useful in enhanced interfaces because it works for items added later and avoids binding repeated handlers to every child element.

The official jQuery `.on()` documentation is worth reading carefully because it explains the difference between direct and delegated handlers. The distinction matters when a CMS template repeats the same component several times or when an AJAX response adds new rows, cards, or messages.

Resilient jQuery code also checks for the elements it needs. The article on checking whether an element exists with and without jQuery shows the basic pattern. Initialisation should quietly skip a component that is not present, rather than throwing an error that prevents every later enhancement from running.


One of the easiest ways to weaken a page is to use fake links everywhere:

  • href="#"
  • href="javascript:void(0)"
  • links that depend entirely on return false
  • clickable div elements with no fallback

Those patterns create unnecessary problems for keyboard users, search engines, bookmarking, copying links, and anyone browsing with scripts unavailable.

If a control opens a menu, use a button. If it navigates, use a link. If the enhanced behaviour loads content inline, make the link point to a real page as the fallback. jQuery can intercept the click and improve the experience, but the browser still has something sensible to do without it.


Test Failure, Not Just Success

Progressive enhancement is easiest to talk about and easiest to forget. Add it to the testing routine:

  • disable JavaScript and browse the page
  • block the main JavaScript file in dev tools
  • test with a slow connection
  • submit forms with clientside validation disabled
  • follow links that normally open panels or overlays

Do not try to support every browser feature equally. Keep the content and task available when one layer fails.

The same discipline is useful when moving away from jQuery too. Writing JavaScript that still works without jQuery takes the same baseline idea into smaller browsernative scripts, while when jQuery plugins became frontend debt looks back at what happened when enhancement code became the only implementation path.


Wrapping Up

jQuery is a useful enhancement tool precisely because it removes a lot of browser awkwardness. That does not mean it should become the foundation of the page.

Start with HTML that can stand up on its own. Use CSS for presentation. Then use jQuery to improve the interaction, reduce friction, and make the interface feel better. If the enhancement fails, the page should degrade into something simpler, not something unusable.

Key Takeaways

  • Progressive enhancement lets jQuery improve a page without making it depend entirely on JavaScript.
  • Links, forms, navigation, and important content should work before scripts run.
  • Add JavaScriptonly classes after scripts load, not before.
  • Delegated event handlers can make repeated or dynamic interfaces more resilient.
  • Testing with JavaScript disabled is still one of the quickest ways to catch fragile frontend work.

Postscript

This article is part of an archive restored from a previous version of my website on 27 May 2026. The original publication date is accurate. The article has since been restored and lightly edited for formatting, imagery, broken links, and current internal references.


Planning a platform change?

I help teams make difficult platform work clearer, from architecture decisions and migrations to launch recovery, performance, and search visibility.