Changing css with jQuery 2.1+ ignores transition property

369 Views Asked by At

I am switching from jQuery 2.0.3 to 2.1.0.

I noticed that in v2.1.0 the css transition property is ignored when setting css properties directly

$('#someElement').css('width','100px');

In v2.0.3 , my element will maintain it's css transition, whereas I lose that in v2.1.0.

I am wondering why this is treated differently, and how I can 'turn on' the transition effect.

With jQuery 2.0.3, the css transition property takes effect

$(function() {
  $('.myClass').css('width', '100px');
});
.myClass {
  height: 50px;
  width: 300px;
  background-color: red;
  transition: width 3s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<div class="myClass"></div>

With jQuery 2.1.0, the css transition property is ignored

$(function() {
  $('.myClass').css('width', '100px');
});
.myClass {
  height: 50px;
  width: 300px;
  background-color: red;
  transition: width 3s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="myClass"></div>

Edit:

I am seeing this odd behavior in Chrome Version 47.0.2526.106 m

In Firefox 42.0, both animate properly

2

There are 2 best solutions below

4
On BEST ANSWER

After searching around, I think this may be related to the changes made for issue #14164 during the v2.1.0 release. As per the title, "Reduce forced layout reflows in init or methods".

I compared the v2.0.3 source code with the v2.1.0 source code, and it looks like some refactoring was done around the .ready() method and how the events are deferred. More specifically, I think it may be related to line(s) 3407-3408 in v2.1.0 where the .ready() method is initially invoked (this wasn't present in v2.0.3):

// Kick off the DOM ready check even if the user does not
jQuery.ready.promise();

As for a workaround, it seems like this transition behavior is inconsistent across browsers. To resolve the issue in Chrome, you could defer the execution of the code and force a redraw.

setTimeout(function () {
  $('.myClass').css('width', '100px');
}, 0);
.myClass {
  height: 50px;
  width: 300px;
  background-color: red;
  transition: width 3s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="myClass"></div>


Alternatively, you could also load jQuery after the DOM elements by moving the script to the bottom of your page. It's still baffling why this makes a difference in Chrome, but doesn't matter in Firefox; it must be related to how the DOM is drawn/painted after events.

$('.myClass').css('width', '100px');
.myClass {
  height: 50px;
  width: 300px;
  background-color: red;
  transition: width 3s;
}
<div class="myClass"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>

0
On

it also seems to work using animate() instead of css()

$('.myClass').animate({'width': '100px'});
.myClass {
  height: 50px;
  width: 300px;
  background-color: red;
  transition: width 3s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="myClass"></div>