Câu trả lời ngắn
Sử dụng CSS này:
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
Cộng với mã này (không có jQuery) ...
someElement.classList.add('notransition'); // Disable transitions
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight; // Trigger a reflow, flushing the CSS changes
someElement.classList.remove('notransition'); // Re-enable transitions
Hoặc JS này với jQuery ...
$someElement.addClass('notransition'); // Disable transitions
doWhateverCssChangesYouWant($someElement);
$someElement[0].offsetHeight; // Trigger a reflow, flushing the CSS changes
$someElement.removeClass('notransition'); // Re-enable transitions
... hoặc mã tương đương bằng cách sử dụng bất kỳ thư viện hoặc khung nào khác mà bạn đang làm việc.
Giải trình
Đây thực sự là một vấn đề khá tinh tế.
Trước tiên, bạn có thể muốn tạo một lớp 'notransition' mà bạn có thể áp dụng cho các phần tử để đặt các *-transition
thuộc tính CSS của chúng thành none
. Ví dụ:
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
(Bỏ qua một bên - lưu ý thiếu một cái -ms-transition
ở đó. Bạn không cần nó. Phiên bản đầu tiên của Internet Explorer để hỗ trợ chuyển đổi hoàn toàn là IE 10, hỗ trợ chúng không được trộn lẫn.)
Nhưng đó chỉ là phong cách, và là một chút dễ dàng. Khi bạn đến để thử và sử dụng lớp này, bạn sẽ gặp một cái bẫy. Cái bẫy là mã như thế này sẽ không hoạt động theo cách bạn có thể mong đợi một cách ngây thơ:
// Don't do things this way! It doesn't work!
someElement.classList.add('notransition')
someElement.style.height = '50px' // just an example; could be any CSS change
someElement.classList.remove('notransition')
Ngây thơ, bạn có thể nghĩ rằng sự thay đổi về chiều cao sẽ không phải là hoạt hình, bởi vì điều đó xảy ra trong khi lớp 'notransition' được áp dụng. Tuy nhiên, trong thực tế, nó sẽ là hoạt hình, ít nhất là trong tất cả các trình duyệt hiện đại mà tôi đã thử. Vấn đề là trình duyệt đang lưu trữ các thay đổi về kiểu dáng mà nó cần thực hiện cho đến khi JavaScript thực hiện xong, và sau đó thực hiện tất cả các thay đổi trong một dòng lại. Kết quả là, nó thực hiện một dòng chảy lại trong đó không có thay đổi thuần về việc chuyển đổi có được bật hay không, nhưng có một thay đổi thuần về chiều cao. Do đó, nó hoạt hình thay đổi chiều cao.
Bạn có thể nghĩ rằng một cách hợp lý và rõ ràng để giải quyết vấn đề này sẽ là kết thúc việc loại bỏ lớp 'thông báo' trong thời gian chờ 1ms, như thế này:
// Don't do things this way! It STILL doesn't work!
someElement.classList.add('notransition')
someElement.style.height = '50px' // just an example; could be any CSS change
setTimeout(function () {someElement.classList.remove('notransition')}, 1);
nhưng điều này cũng không đáng tin cậy làm việc. Tôi không thể làm cho đoạn mã trên bị phá vỡ trong các trình duyệt WebKit, nhưng trên Firefox (trên cả máy chậm và nhanh) đôi khi bạn (dường như ngẫu nhiên) sẽ có hành vi tương tự như sử dụng phương pháp ngây thơ. Tôi đoán lý do cho điều này là vì có thể thực thi JavaScript đủ chậm để chức năng hết thời gian chờ đợi để thực thi khi trình duyệt không hoạt động và nếu không thì sẽ nghĩ đến việc thực hiện phản xạ cơ hội và nếu kịch bản đó xảy ra, Firefox thực thi chức năng xếp hàng trước khi chỉnh lại dòng.
Giải pháp duy nhất mà tôi đã tìm thấy cho vấn đề là buộc chỉnh lại phần tử, xóa các thay đổi CSS được thực hiện cho nó, trước khi xóa lớp 'notransition'. Có nhiều cách khác nhau để làm điều này - xem ở đây cho một số. Cách gần nhất có một cách 'tiêu chuẩn' để làm điều này là đọc thuộc offsetHeight
tính của phần tử.
Một giải pháp thực sự hiệu quả, sau đó, là
someElement.classList.add('notransition'); // Disable transitions
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight; // Trigger a reflow, flushing the CSS changes
someElement.classList.remove('notransition'); // Re-enable transitions
Dưới đây là một câu đố về JS minh họa ba cách tiếp cận có thể tôi đã mô tả ở đây (cả hai cách tiếp cận thành công và hai cách tiếp cận không thành công):
http://jsfiddle.net/2uVAA/131/