jQuery 3.0 Final Released!

Posted on by

jQuery 3.0 is now released! This version has been in the works since October 2014. We set out to create a slimmer, faster version of jQuery (with backwards compatibility in mind). We’ve removed all of the old IE workarounds and taken advantage of some of the more modern web APIs where it made sense. It is a continuation of the 2.x branch, but with a few breaking changes that we felt were long overdue. While the 1.12 and 2.2 branches will continue to receive critical support patches for a time, they will not get any new features or major revisions. jQuery 3.0 is the future of jQuery. If you need IE6-8 support, you can continue to use the latest 1.12 release.

Despite the 3.0 version number, we anticipate that these releases shouldn’t be too much trouble when it comes to upgrading existing code. Yes, there are a few “breaking changes” that justified the major version bump, but we’re hopeful the breakage doesn’t actually affect that many people.

To assist with upgrading, we have a brand new 3.0 Upgrade Guide. And the jQuery Migrate 3.0 plugin will help you to identify compatibility issues in your code. Your feedback on the changes will help us greatly, so please try it out on your existing code and plugins!

You can get the files from the jQuery CDN, or link to them directly:



You can also get the release from npm:

npm install jquery@3.0.0

In addition, we’ve got the release for jQuery Migrate 3.0. We highly recommend using this to address any issues with breaking changes in jQuery 3.0. You can get those files here:



npm install jquery-migrate@3.0.0

For more information about upgrading your jQuery 1.x and 2.x pages to jQuery 3.0 with the help of jQuery Migrate, see the jQuery Migrate 1.4.1 blog post.

Slim build

Finally, we’ve added something new to this release. Sometimes you don’t need ajax, or you prefer to use one of the many standalone libraries that focus on ajax requests. And often it is simpler to use a combination of CSS and class manipulation for all your web animations. Along with the regular version of jQuery that includes the ajax and effects modules, we’re releasing a “slim” version that excludes these modules. All in all, it excludes ajax, effects, and currently deprecated code. The size of jQuery is very rarely a load performance concern these days, but the slim build is about 6k gzipped bytes smaller than the regular version – 23.6k vs 30k. These files are also available in the npm package and on the CDN:



This build was created with our custom build API, which allows you to exclude or include any modules you like. For more information, have a look at the jQuery README.

Compatibility with jQuery UI and jQuery Mobile

While most things will work, there are a few issues that jQuery UI and jQuery Mobile will be addressing in upcoming releases. If you find an issue, keep in mind that it may already be addressed upstream and using the jQuery Migrate 3.0 plugin should fix it. Expect releases soon.


Major changes

Below are just the highlights of the major new features, improvements, and bug fixes in these releases, you can dig into more detail on the 3.0 Upgrade Guide. A complete list of issues fixed is available on our GitHub bug tracker. If you read the blog post for 3.0.0-rc1, the below features are the same.

jQuery.Deferred is now Promises/A+ compatible

jQuery.Deferred objects have been updated for compatibility with Promises/A+ and ES2015 Promises, verified with the Promises/A+ Compliance Test Suite. This meant we needed some major changes to the .then() method. Legacy behavior can be restored by replacing any use of .then() with the now-deprecated .pipe() method (which has an identical signature).

  1. An exception thrown in a .then() callback now becomes a rejection value. Previously, exceptions bubbled all the way up, aborting callback execution. Any deferreds relying on the resolution of the deferred that threw an exception would never have resolved.

  2. Example: uncaught exceptions vs. rejection values

    var deferred = jQuery.Deferred();
    deferred.then(function() {
      console.log("first callback");
      throw new Error("error in callback");
    .then(function() {
      console.log("second callback");
    }, function(err) {
      console.log("rejection callback", err instanceof Error);

    Previously, “first callback” was logged and the error was thrown. All execution was stopped. Neither “second callback” nor “rejection callback” would have been logged. The new, standards-compliant behavior is that you’ll now see “rejection callback” and true logged. err is the rejection value from the first callback.

  3. The resolution state of a Deferred created by .then() is now controlled by its callbacks—exceptions become rejection values and non-thenable returns become fulfillment values. Previously, returns from rejection handlers became rejection values.

  4. Example: returns from rejection callbacks

    var deferred = jQuery.Deferred();
    deferred.then(null, function(value) {
      console.log("rejection callback 1", value);
      return "value2";
    .then(function(value) {
      console.log("success callback 2", value);
      throw new Error("exception value");
    }, function(value) {
      console.log("rejection callback 2", value);
    .then(null, function(value) {
      console.log("rejection callback 3", value);

    Previously, this would log “rejection callback 1 value1”, “rejection callback 2 value2”, and “rejection callback 3 undefined”.

    The new, standards-compliant behavior is that this will log “rejection callback 1 value1”, “success callback 2 value2″, and “rejection callback 3 [object Error]”.

  5. Callbacks are always invoked asynchronously, even if a Deferred has already been resolved. Previously, these callbacks were executed synchronously upon binding.

  6. Example: async vs sync

    var deferred = jQuery.Deferred();
    deferred.then(function() {
      console.log("success callback");
    console.log("after binding");

    Previously, this would log “success callback” then “after binding”. Now, it will log “after binding” and then “success callback”.

Important: while caught exceptions had advantages for in-browser debugging, it is far more declarative (i.e. explicit) to handle them with rejection callbacks. Keep in mind that this places the responsibility on you to always add at least one rejection callback when working with promises. Otherwise, some errors might go unnoticed.

We’ve built a plugin to help in debugging Promises/A+ compatible Deferreds. If you are not seeing enough information about an error on the console to determine its source, check out the jQuery Deferred Reporter Plugin.

jQuery.when has also been updated to accept any thenable object, which includes native Promise objects.


Added .catch() to Deferreds

The catch() method was added to promise objects as an alias for .then(null, fn).


Error cases don’t silently fail

Perhaps in a profound moment you’ve wondered, “What is the offset of a window?” Then you probably realized that is a crazy question – how can a window even have an offset?

In the past, jQuery has sometimes tried to make cases like this return something rather than having them throw errors. In this particular case of asking for the offset of a window, the answer up to now has been { top: 0, left: 0 } With jQuery 3.0, such cases will throw errors so that crazy requests aren’t silently ignored. Please try out this release and see if there is any code out there depending on jQuery to mask problems with invalid inputs.


Removed deprecated event aliases

.load, .unload, and .error, deprecated since jQuery 1.8, are no more. Use .on() to register listeners.


Animations now use requestAnimationFrame

On platforms that support the requestAnimationFrame API, which is pretty much everywhere but IE9 and Android<4.4, jQuery will now use that API when performing animations. This should result in animations that are smoother and use less CPU time – and save battery as well on mobile devices.

jQuery tried using requestAnimationFrame a few years back but there were serious compatibility issues with existing code so we had to back it out. We think we’ve beaten most of those issues by suspending animations while a browser tab is out of view. Still, any code that depends on animations to always run in nearly real-time is making an unrealistic assumption.

Massive speedups for some jQuery custom selectors

Thanks to some detective work by Paul Irish at Google, we identified some cases where we could skip a bunch of extra work when custom selectors like :visible are used many times in the same document. That particular case is up to 17 times faster now!

Keep in mind that even with this improvement, selectors like :visible and :hidden can be expensive because they depend on the browser to determine whether elements are actually displaying on the page. That may require, in the worst case, a complete recalculation of CSS styles and page layout! While we don’t discourage their use in most cases, we recommend testing your pages to determine if these selectors are causing performance issues.

This change actually made it into 1.12/2.2, but we wanted to reiterate it for jQuery 3.0.


As mentioned above, the Upgrade Guide is now available for anyone ready to try out this release. Aside from being helpful in upgrading, it also lists more of the notable changes.



Thank you to everyone who helped with this release through code contributions, issue reports, and more, including but not limited to Jason Bedard, Fredrik Blomqvist, Leonardo Braga, Ralin Chimev, Jon Dufresne, Oleg Gaidarenko, Richard Gibson, Michał Gołębiowski, Scott González, Zack Hall, Alexander K, Martijn W. van der Lee, Alexander Lisianoi, Steve Mao, Dave Methvin, Jha Naman, Jae Sung Park, Todor Prikumov, William Robinet, Felipe Sateler, Damian Senn, Josh Soref, Jun Sun, Christophe Tafani-Dereeper, Vitaliy Terziev, Joe Trumbull, Bernhard M. Wiedemann, Devin Wilson, and Henry Wong.




  • Golf away 21 bytes (eaa3e9f)
  • Preserve URL hash on requests (#1732, e077ffb)
  • Execute jQuery#load callback with correct context (#3035, 5d20a3c)
  • Ensure ajaxSettings.traditional is still honored (#3023, df2051c)
  • Remove unnecessary use of jQuery.trim (0bd98b1)


  • Avoid infinite recursion on non-lowercase attribute getters (#3133, e06fda6)
  • Add a support comment & fix a link @ tabIndex hook (9cb89bf)
  • Strip/collapse whitespace for set values on selects (#2978, 7052698)
  • Remove redundant parent check (b43a368)
  • Fix setting selected on an option in IE<=11 (#2732, 780cac8)


  • Don’t workaround the IE 11 iframe-in-fullscreen sizing issues (#3041, ff1a082)
  • Toggle detached elements as visible unless they have display: none (#2863, 755e7cc)
  • Make sure elem.ownerDocument.defaultView is not null (#2866, 35c3148)
  • Add animation-iteration-count to cssNumber (#2792, df822ca)
  • Restore cascade-override behavior in .show (#2654, #2308, dba93f7)
  • Stop Firefox from treating disconnected elements as cascade-hidden (#2833, fe05cf3)



  • Separate the two paths in jQuery.when (#3029, 356a3bc)
  • Provide explicit undefined context for jQuery.when raw casts (#3082, 7f1e593)
  • Remove default callback context (#3060, 7608437)
  • Warn on exceptions that are likely programming errors (#2736, 36a7cf9)
  • Propagate progress correctly from unwrapped promises (#3062, d5dae25)
  • Make jQuery.when synchronous when possible (#3100, de71e97)
  • Remove undocumented progress notifications in $.when (#2710, bdf1b8f)
  • Give better stack diagnostics on exceptions (07c11c0)


  • Add tests for negative borders & paddings (f00dd0f)


  • Fix various spelling errors (aae4411)
  • Update support comments related to IE (693f1b5)
  • Fix an incorrect comment in the attributes module (5430c54)
  • Updated links to https where they are supported. (b0b280c)
  • Update support comments to follow the new syntax (6072d15)
  • Use https where possible (1de8346)
  • Use HTTPS URLs for jsfiddle & jsbin (63a303f)
  • Add FAQ to reduce noise in issues (dbdc4b7)
  • Add a note about loading source with AMD (#2714, e0c25ab)
  • Add note about code organization with AMD (#2750, dbc4608)
  • Reference new feature guidelines and API tenets (#2320, 6054139)



  • Allow constructing a jQuery.Event without a target (#3139, 2df590e)
  • Add touch event properties, eliminates need for a plugin (#3104, f595808)
  • Add the most commonly used pointer event properties (7d21f02)
  • Remove fixHooks, propHooks; switch to ES5 getter with addProp (#3103, #1746, e61fccb)
  • Make event dispatch optimizable by JavaScript engines (9f268ca)
  • Evaluate delegate selectors at add time (#3071, 7fd36ea)
  • Cover invalid delegation selector edge cases (e8825a5)
  • Fix chaining .on() with null handlers (#2846, 17f0e26)
  • Remove pageX/pageY fill for event object (#3092, 931f45f)


  • Don’t execute native stop(Immediate)Propagation from simulation (#3111, 94efb79)



  • Resolve strict mode ClientRect “no setter” exception (3befe59)



  • Treat literal and function-returned null/undefined the same (#3005, 9fdbdd3)
  • Reduce size (91850ec)



  • Take Safari 9.1 into account (234a2d8)
  • Limit selection to #qunit-fixture in attributes.js (ddb2c06)
  • Set Edge’s expected support for clearCloneStyle to true (28f0329)
  • Fix Deferred tests in Android 5.0’s stock Chrome browser & Yandex.Browser (5c01cb1)
  • Add additional test for jQuery.isPlainObject (728ea2f)
  • Build: update QUnit and fix incorrect test (b97c8d3)
  • Fix manipulation tests in Android 4.4 (0b0d4c6)
  • Remove side-effects of one attributes test (f9ea869)
  • Account for new offset tests (f52fa81)
  • Make iframe tests wait after checking isReady (08d73d7)
  • Refactor testIframe() to make it DRYer and more consistent (e5ffcb0)
  • Weaken sync-assumption from jQuery.when to jQuery.ready.then (f496182)
  • Test element position outside view (#2909, a2f63ff)
  • Make the regex catching Safari 9.0/9.1 more resilient (7f2ebd2)


  • .not/.filter consistency with non-elements (#2808, 0e2f8f9)
  • Never let .closest() match positional selectors (#2796, a268f52)
  • Restore jQuery push behavior in .find (#2370, 4d3050b)

Comments are closed.