By Craig Buckler

The JavaScript-Dependency Backlash: Myth-Busting Progressive Enhancement

By Craig Buckler

In Louis’ recent forum topic, Are we in a scripting-dependency backlash?, he commented:

I think, in some sense, we are in somewhat of a scripting-dependency backlash, and it’s probably a good thing.


  • I agree. So do several others including web gurus PPK (The problem with Angular) and Jeremy Keith (Angular momentum) and Jake Archibald (Progressive enhancement is still important).
  • Relatively few web applications are suited to JavaScript frameworks despite their meteoric rise.
  • Progressive Enhancement remains the best option for solving web development issues such as wide-ranging browser support, maintenance and future-proofing your application.

Let’s define the terms we’re discussing…

What is JavaScript-Dependency?

There has been a rise in the use of client-side frameworks. These provide server-side-like coding patterns such as MVC, template views, reusable components, form validation and more. AngularJS is probably the best known and most popular but it’s not the only solution.

Unlike server-side frameworks, the client-side alternatives must run on a modern JavaScript-enabled browser. Without JavaScript, they fail. TIDAL is a typical case; if JavaScript isn’t available, the user sees a blank page. There is no content, no error and no sign-up form.

While there’s little excuse not to show a message, there are good use cases for JavaScript-dependent apps:

  • Prototypes
    It’s quick to mock-up sites and apps because client-side frameworks provide rich components and shortcuts.
  • Client-side-only applications
    If your app is simple and requires no server interaction other than an initial download, a JavaScript framework may be a good fit (presuming you can remove stuff you don’t need).
  • Internal corporate applications
    Enforcing JavaScript isn’t a problem when you know your audience and the devices they use. Angular was initially designed for enterprise applications.
  • Sophisticated interfaces
    Consider action games, Google Maps and Docs. Developing JavaScript-less alternatives is futile. Google created a basic HTML version of Maps but it was effectively a different application and was dropped in 2010.

There are other cases but the majority of public-facing web sites and applications do not fall into these categories. No one will stop you using a client-side framework but, when you have a hammer, everything looks like a nail. To quote Louis again:

Developers seem to be using flashy new tools just for the sake of it, and not because they are solving an actual problem.

What is Progressive Enhancement?

Progressive Enhancement (PE) is not a technology but a development approach. I wrote several tutorials and examples in 2009 but the concept has been discussed since 2003.

You establish a base level of user experience then add more advanced functionality when the browser supports it. Taking PE to a logical extreme:

  1. You create an HTML-only application where all important processing is done server-side. It would work in any browser; mobile devices, Lynx, IE1.0 or whatever you throw at it.
  2. You enhance the layout with CSS. CSS is PE-ready because browsers ignore properties they don’t understand. You can enhance it further using options such as media queries or @supports rules. The application still works everywhere but offers an improved experience for browsers with modern CSS capabilities.
  3. You enhance the functionality with JavaScript. JavaScript is the most volatile layer since language and API support varies from browser to browser. Presuming it runs, you test facilities are available before using them. For example, you could turn a table of data into a pretty chart when canvas or SVG is supported.

Every browser receives the best application it can handle. It’s possible that no two browsers offer quite the same experience. Mobile-first responsive design and the lesser-used offline-first are examples of Progressive Enhancement techniques.

Let’s examine the criticisms of PE.

MYTH: No One Disables JavaScript

Few people know what JavaScript is. Few browsers allow users to (easily) disable JavaScript.

This is absolutely true.

PE critics then conclude:

those without JavaScript get what they deserve

It’s dangerous to presume JavaScript will be available to everyone, everywhere, every time to the level your app requires. Everyone has JavaScript, right? illustrates the point.

Progressive Enhancement is not about catering for those who disable JavaScript. It’s about enhancing the experience when certain JavaScript features are available. The application may offer a miserable interface when JavaScript is disabled but the user still gets something.

MYTH: No One Uses Old Browsers

What do we mean by “old”? For most developers, it’s any browser released more than twelve months ago. Not everyone can use the latest and greatest applications:

  • large organizations and government departments
  • people with disabilities
  • people in developing countries
  • less affluent sectors of the community
  • anyone with an iPhone 5.0 or Android 4.0 and below.

These sectors may not be important to you. But will they never be important?

Progressive Enhancement makes no assumptions about your audience. That’s not true for client-side frameworks. Those who can’t use your application will disappear from server logs. It quickly becomes a self-fulfilling prophecy: “no one using our app is on an old browser so we can carry on as-is…”

MYTH: Progressive Enhancement is Anti-JavaScript

Progressive Enhancement embraces the fundamental strengths of the web. It’s possible to develop a site or application which works on any web-capable device anywhere in the world. The better that device, the better the user experience.

Client-side frameworks make JavaScript an absolute dependency. You’re no longer coding for the web. Your application uses the web as a delivery mechanism to specific runtime engines. The browser is your operating system and an update could break your app.

MYTH: Progressive Enhancement Makes Assumptions About Users and Devices

PE is about NOT making assumptions. You don’t presume anything — it’s the core premise of the technique.

JavaScript frameworks lull you into thinking everyone is using a capable browser on a powerful device. We’ve made these presumptions before. Is it any different to assuming everyone’s on broadband? Or that everyone has a 17″ screen at least 960px wide? Or that everyone will use IE6 now and forever more?

MYTH: Progressive Enhancement Means Supporting Archaic Browsers

Progressive Enhancement critics presume you’ll spend all your time dealing with old browsers. In reality, it’s the opposite: you never need to deal with old browsers because appropriate fallbacks are in-place.

Supporting old browsers is a benefit of PE — not an objective. You can support the lowliest of browsers but you can establish whatever baseline you like.

For example, I’m currently working on an application where addEventListener is a requirement for most JavaScript to run. IE8 and below will therefore fail to show functional enhancements. I could fix that but it’s not worth the investment since it’s a corporate app with no oldIE users. However, IE8 users can still use the system and it could be improved if required.

MYTH: JavaScript Framework Apps are Cooler

You can create an identical-looking app using PE techniques. The confusion arises because most JavaScript frameworks provide a range of good-looking pre-developed widgets. Those same widgets could be used in a progressively-enhanced app but, without JS, they’d fallback to basic HTML alternatives.

PE also allows you to use modern HTML, CSS and JavaScript APIs which are yet to appear in any browser. Consider the Fetch API — a modern replacement for XMLHttpRequest. It has minimal support yet I could use it without problems because I can either fallback to XMLHttpRequest or server requests.

JavaScript frameworks are firmly stuck in the present — not the future.

MYTH: Progressive Enhancement Holds Back the Web

Or, more specifically, client-side frameworks are on the cutting edge and pushing the web forward.

Sorry, but this is an illusion. AngularJS-like frameworks implement magical features but, dig below the surface, and you’re still using HTML, CSS, JavaScript and DOM manipulation. At best, it’s an abstraction. At worst, it’s a distraction.

Your client-side framework is only as good as the browsers it was developed for. AngularJS 2.0 is a complete re-write because features such as Object.observe() and Web Components weren’t commonly available when AngularJS 1.x was released. The framework forces you to use older technologies but hides the implementation from you.

PE allows you to use any modern API without breaking your application. Best of luck upgrading from Angular 1…

MYTH: JavaScript Frameworks Make Development Simpler

This is partly true — but only when you’re starting to build your application. You have access to a range of controls which cut the initial development time. But you’re then stuck within the confines of that framework and that can lead to problems later.

Presume your app has been running for a while and the client demands support for BrowserX. It’s used by a major customer and is not particularly old; the Blackberry browser, iPhone 4, Android 3.3 etc. They’re probably expecting a development time of a few days but it could be impossible if your JavaScript framework is incompatible.

The question may never arise for an app developed using PE techniques; you’re possibly supporting that browser already. Further enhancements can be added without a major re-write.

MYTH: Progressive Enhancement is Twice the Effort

This is the favorite quote of the critics. The only people who say PE is too much effort are those who’ve never tried it or somehow failed in the attempt.

PE will only take twice as long if you didn’t consider it from the start. Trying to retro-fit PE into an existing application is doomed — that’s especially true for one which depends on JavaScript.

Let’s consider a simple example such as a paged list of results from a search query. The first page load returns all the HTML. It’s fast and there’s nothing for JavaScript to do. Behind the scenes, we’re using a database query and slotting the results into an HTML template. You could quickly adapt the same service to return the results as JSON data or results HTML without the header and footer. When the user clicks “page 2”, the second page of results is shown:

  • With JavaScript, we can intercept the click and use Ajax techniques to fetch that page of results. HTML data can be slotted into the page using innerHTML. Alternatively, we could use page 1 as a template for returned JSON data.
  • If JavaScript, XMLHttpRequest or Fetch isn’t available — or the Ajax call fails — we can request a second full page of HTML.

It’s a little more work but it’s certainly not double the effort. We have the benefit of a cross-browser fault-tolerant solution.

MYTH: Progressive Enhancement is Pointless — Websites Evolve or Die

The logic behind this argument is that websites eventually become obsolete. Therefore, you can use a framework which targets specific technologies at a specific point in time.

I wish. If your code’s good, it’ll be used far longer than you expected. Bad code lives even longer because no one wants to touch it.

But again, use Progressive Enhancement and you’re not making any presumptions other than the web will continue as a client/server-based HTML-based system. The web would need to fundamentally change for your app to fail — it would no longer be the web!

MYTH: Progressive Enhancement is an Old Technique Recommended by Old Timers

To quote Oddz:

The proliferation of client side JavaScript frameworks puts you in the minority along with the rest of the “old timers”.

Yeah, thanks!

The JavaScript backlash is led by people who’ve been developing for the web for a considerable period. Are we all Luddites failing to move with the times? Perhaps. Or perhaps it’s because we learned something from our many, many historical mistakes?

JavaScript frameworks raise familiar issues:

  • Some intermingle HTML and functionality like we used to do with onclick handlers, e.g.
    <form ng-submit="doSomething()">
  • They target specific browsers. There has been a resurgence of “best viewed in…” messages and <noscript> tags.
  • They make presumptions about today’s web — such as JavaScript works everywhere and 2MB per page is reasonable.
  • They do not plan for the future.

JavaScript frameworks mostly benefit the developer — not users. They can offer a short-term gain but the cost is fewer visitors and painful long-term maintenance.

And let’s not forget SEO. Google indexes JavaScript pages but following every logic branch won’t necessarily be possible. It can also be difficult to link back to a specific URL unless you’ve coded carefully.

Progressive Enhancement compliments the strengths of the web:

  • it separates content, layout and functionality for easier maintenance
  • you’re writing defensive, fault-tolerant, device-agnostic code for the web — not browsers
  • you can support a wide range of devices
  • your testing burden is reduced because your app remains operative on failure
  • SEO and accessibility are baked-in (or require less effort)
  • sites and apps will work on browsers released today, yesterday and tomorrow
  • no one has disproved the benefits of Progressive Enhancement or proposed a better technique.

There’s only one downside: it’s evident many developers still don’t trust or understand Progressive Enhancement.

Long live the JavaScript-Dependency backlash!

  • Sam Bernard

    Progressive enhancement is important to reach the widest possible audience- but you don’t have to give up frontend frameworks to do so.

    ReactJS with fluxible is the best of both worlds- an isomorphic JavaScript framework that can render all your content both in the browser and on the server without having to duplicate code.

    Several projects in and I’m sold- the combination of accessible content and rich JavaScript enhancements make it an easy choice.

    • Craig Buckler

      Exactly. In theory, it would be possible to use any JS framework as a progressively-enhanced interface to your application – although some would be considerably more work than others.

  • Sean Hogan

    Nice intro.

    A minor quibble: “HTML then CSS then Javascript” is too simplistic a summary of PE because:
    i. JS can load and install additional HTML (and CSS)
    ii. JS can modify whether a set of CSS rules apply / stop applying.

    More significantly:
    While PE is potentially more robust than JS-required frameworks, advocates usually gloss over the point that a failed enhancement could break an otherwise working page. Even using feature detection you can’t guarantee your enhancements succeed on every browser / device / network (browsers lie; your code isn’t perfect; networks block; power-users customize) but if your PE has an opt-in/out then at least the end-user can guarantee it doesn’t start.

    I guess my point is that opt-in/out should be part of the PE discussion. For starters I would suggest the extreme PE sequence should be:
    i. Plain-Old-Semantic-HTML – primary content plus minimal auxiliary content but no layout markup
    ii. Simple CSS – preferably single column

    iii. Does the browser support the base level of features, e.g. history.pushState? If not then abandon.
    iv. Has the user opted in/out of PE? If “out” then abandon.

    v. Javascript takes over to install a device-appropriate UI – layout / stylesheets / auxiliary content. This includes potentially transforming the primary content.
    vi. Navigation is handled with a PJAX approach (for same-site navigation)

    Steps iii) and iv) allow the site or the end-user to immediately switch off the enhanced UI for a browser, while still retaining a fully functional site.

    (Admittedly disabling JS provides an opt-out to the end-user, but that’s a sledge-hammer approach)

    • Craig Buckler

      Thanks Sean.

      There are many options with PE. You’ll almost certainly want to apply specific styles based on a JS widget working, e.g. hide a table and show an animated canvas chart generated from that data.

      PE opt-in is a new one on me! I’ve not encountered a situation where that’s ever been required? Would users understand it? It sounds a little over-engineered.

      I’ve seen browsers do something differently or fail to run some code but it doesn’t normally break the application. Serious JavaScript errors stop all code running which isn’t a problem if you gracefully fallback to server-side methods.

      PE is not an alternative to rigorous browser testing – that will always be necessary. But at least you know catastrophic failure is unlikely in the event of a specific component failing.

      • Sean Hogan

        So what happens if your JS breaks between hiding the table and showing the canvas chart?

        Gmail has a “Load Basic HTML” link while loading. Browsers nudge a range of notifications into the top or bottom of the window. PE opt-in/out doesn’t need to be more complicated than that.

        • Craig Buckler

          Your JS could break any time but, if it’s passed all tests and got that far, it’s considerably less likely. Again, PE is not a substitute for testing!

          GMail’s basic HTML is a completely different application – not PE. While I understand you want to cover absolutely every eventuality, the majority of applications need never go that far.

          Keep it simple. Many things can be done without JS and, when it is necessary, you can ensure one component failing does not affect all others.

  • Nicolas Hoffmann

    Thanks a LOT for this writing !

    Another example (for the myth of developping twice and anti-JS), I’m using PE to develop accessible plugins (example a carrousel ), it is just transforming a simple list of hx with content into a carrousel.

    It is not taking twice time to develop, I’m just starting from basic HTML and improving it a lot with JS, so JS is really a good friend for PE, if it is well used of course. :)

  • Craig Buckler

    Thanks Nicolas.

    That’s the key: start with Plain Old Semantic HTML and enhance.

  • Christopher Sanders

    Sorry but many people and companies simply dont have the resources to cater to browsers that werent designed for the features you want to build. Why shoe horn them in? Sometimes you have to cut the ambilical cords. Why disrupt old business to generate new business. I think the one size fits all PE approach is a mistake. Why cut featuresor degrade performance for 80% of your users because 20% cant do it. Doesnt seem like a good trade off in this day an age of mostly ad supported websites.

    • Craig Buckler

      PE is not about degrading performance or a one-size-fits-all approach. It’s exactly the opposite. I think you need to read this again…

      • Christopher Sanders

        Read what I said again. You have to add a ton of bloatware simply to cater to pre-evergreen browsers. That has a direct impact on performace. Lets not and simply keep them on the experience that has served them well up until this point. If they want new features or a current experience they can use an evergreen browser. They are free. They cost nothing other than the five minutes it takes to download and install them.

        • If you work for a corporation your browser options are probably limited unless you have admin rights. Also, nearly all of the “check for non evergreen browsers” checks don’t need to be loaded on evergreen browsers, so there is not an impact on performance.

          • Christopher Sanders

            Ive worked for several big corporations and most if not everyone working at the corporation had more than one browser installed on their machines at least one of which was an evergreen. The old corporate infrastructure used to be a reasonable excuse. I dont think this holds anymore.

          • If you don’t have admin rights you can’t install another browser.

        • Craig Buckler

          You appear to have misunderstood what is meant by progressive enhancement. Refer back to “MYTH: Progressive Enhancement Means Supporting Archaic Browsers”.

          You are also presuming there are two types of browser: old and new. The situation is far more complex. A feature in Chrome today may not have existed yesterday and may disappear tomorrow. A feature supported by most browsers now is not yet in Safari.

          You’re not adding any bloat to do this. On the contrary, you’re removing it where possible. If a specific feature fails, it simply falls back to a lesser experience – perhaps ultimately to the basic HTML you already have in your page.

          But, going by your own figures, let’s presume 20% of people aren’t on the very latest browsers and you decide to ignore them. If your site earns $8K per year, you’ve lost $2K – no big deal. But what if it earns $100K? Or $1 million? The argument for supporting a wide range of devices and browsers becomes considerably more imperative.

        • Basia

          “Why cater to someone who cant afford to download a free browser?”

          Don’t you think, you insult a lot of people? If new “free” version means new system and new machine? And if I just do not want more bloatware?

          I have to say, I am getting mad, when I think about my new bank, which after swallowing my old bank, after some months has scrapped old web banking application which just worked on every, even 10 yesrs old box. Now, I have to use new browser on new system on stronger box. And is it faster? No, it takes more time to load all idiotisms, it takes time to install new system on new box. Bank’s helpdesk people have informed me about improved user experience because of new system based on modern Java Script applications and there is no return to old system..

          Why cater to someone who cant afford to download a free browser?
          Well, I know – I have to move my money away, not to finance it, just as principle. I can afford it. There is still enough banks in Poland


  • All your users have JavaScript disabled until the first script is loaded and runs

  • Say you have a threaded forum that allows users to expand or collapse subthreads or upvote or downvote posts. What’s a good way to give users the ability to do this without having to resend all 100 comments in the current view every time the user does something? Or is a collapsing tree view part of what the article calls “sophisticated interfaces”?

    • Craig Buckler

      Pagination would work fine fine.

      You send the most recent comments and have a “see more” button at the bottom. In basic browsers, that would cause a full page refresh and show the page again with additional comments, a second set, or perhaps a separate page with all comments depending on the number you want to show. Of course that means more to load but HTML payloads are rarely problematic.

      In more modern devices, you can load sections into place on request or as the user scrolls down. Those users get a slicker, enhanced experience but everyone can view it regardless of the browser.

      • How well would pagination interact with someone posting a comment to a particular thread in a discussion and thereby causing the thread to be bumped to the top because it has just become the thread with “the most recent comment[]”? That would push other comments onto later pages, confusing the user because the user sees a thread twice: once when viewing the first page before a thread on the second page has been bumped, and once when viewing the second page after said thread has been bumped to the first page.

        • Craig Buckler

          There are ways around any problem you envisage. For example, you could note the ID of the top/bottom comment and start from there – it wouldn’t matter how many are loaded before or after the current point.

          It’s certainly not a reason to ignore Progressive Enhancement.

Get the latest in JavaScript, once a week, for free.