Cách sạch nhất để tạm thời vô hiệu hóa các hiệu ứng chuyển tiếp CSS là gì?


209

Tôi có một phần tử DOM với một số / tất cả các hiệu ứng sau được áp dụng:

#elem {
  -webkit-transition: height 0.4s ease;
  -moz-transition: height 0.4s ease;
  -o-transition: height 0.4s ease;
  transition: height 0.4s ease;
}

Tôi đang viết một plugin jQuery đang thay đổi kích thước phần tử này, tôi cần tạm thời tắt các hiệu ứng này để tôi có thể thay đổi kích thước của nó một cách trơn tru.

Cách tạm thời nhất để vô hiệu hóa các hiệu ứng này (và sau đó kích hoạt lại chúng), với điều kiện chúng có thể được áp dụng từ cha mẹ hoặc có thể không được áp dụng.


1
Điều này có vẻ đầy hứa hẹn: ricostacruz.com/jquery.transit . Nó được MIT cấp phép, vì vậy bạn có thể kết hợp nó hoặc nghiên cứu nó để xem anh ấy làm như thế nào.
Robert Harvey

Tất cả các câu trả lời thêm một .notransitionlớp. Sẽ hợp lý hơn nếu làm theo cách khác, tức là nhắm mục tiêu #elem.yestransitionvới css của bạn và loại bỏ lớp này. Điều đó loại bỏ có *s khó chịu trong css của bạn.
marcellothearcane

Câu trả lời:


484

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 *-transitionthuộ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 offsetHeighttí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/


8
Câu trả lời Excelente. Tốt công việc, và đánh giá cao kể từ khi tôi đưa ra cùng một vấn đề. Nếu tôi chỉ muốn xóa một loại chuyển đổi thì sao?
rafaelmorais

2
Giải pháp của bạn là đúng, nhưng đối với những người tìm kiếm thêm thông tin cơ bản: stackoverflow.com/a/31862081/1026
Nickolay

2
Nhỏ nhỏ sang một bên, IE10 là người đầu tiên ổn định phiên bản của IE để tàu với các chuyển động không tiền tố. Các phiên bản tiền phát hành, ngoại trừ Bản xem trước phát hành, yêu cầu tiền tố -ms- cho các hiệu ứng chuyển tiếp, cùng với hàng loạt thứ khác. Điều đó, tôi nghi ngờ, là một trong những lý do tiền tố -ms- xuất hiện ngày hôm nay. Lý do khác, rất có thể, tất nhiên, là sự sùng bái hàng hóa thông thường mà tất cả chúng ta đều biết và yêu thích về tiền tố của nhà cung cấp.
BoltClock

1
Điều thú vị là chỉ cần kiểm tra chiều cao bù của phần tử sẽ kích hoạt một dòng lại. Ước gì tôi biết điều này một năm trước khi tôi đập đầu vào tường với cùng một vấn đề. Đây có còn được coi là cách lý tưởng nhất để xử lý việc này?
Brett84c

2
Thủ thuật chỉnh lại dòng dường như không hoạt động khi hoạt ảnh các phần tử SVG không có thuộc tính offsetHeight; setTimout hoạt động.
piotr_cz

19

Thêm một lớp CSS bổ sung để chặn quá trình chuyển đổi, và sau đó loại bỏ nó để trở về trạng thái trước đó. Điều này làm cho cả mã CSS và JQuery ngắn, đơn giản và dễ hiểu.

CSS :

.notransition {
  -webkit-transition: none !important;
  -moz-transition: none !important;
  -o-transition: none !important;
  -ms-transition: none !important;
  transition: none !important;
}

!important đã được thêm vào để chắc chắn rằng quy tắc này sẽ có "trọng số" hơn, bởi vì ID thường cụ thể hơn so với lớp.

JQuery :

$('#elem').addClass('notransition'); // to remove transition
$('#elem').removeClass('notransition'); // to return to previouse transition

5
-1 vì điều này không đủ để giải quyết vấn đề cho tôi trong Chrome hoặc Firefox - nếu tôi có Javascript có thêm lớp, thực hiện các thay đổi và xóa lớp, đôi khi các thay đổi vẫn còn hoạt động. Tôi đã dành một hoặc hai giờ để nghiên cứu vấn đề này một cách chi tiết và sẽ đăng câu trả lời sau với những câu đố cho thấy các trường hợp cách tiếp cận ngây thơ không thành công, cộng với một bản hack gọn gàng khắc phục giải pháp ở đây bằng cách buộc chỉnh lại giữa thực hiện thay đổi và xóa lớp 'notransition'.
Đánh dấu Amery

18

Tôi sẽ ủng hộ việc vô hiệu hóa hoạt hình theo đề xuất của DaneSoul, nhưng làm cho việc chuyển đổi thành toàn cầu:

/*kill the transitions on any descendant elements of .notransition*/
.notransition * { 
  -webkit-transition: none !important; 
  -moz-transition: none !important; 
  -o-transition: none !important; 
  -ms-transition: none !important; 
  transition: none !important; 
} 

.notransitionsau đó có thể được áp dụng cho bodyphần tử, ghi đè hiệu quả bất kỳ hoạt hình chuyển tiếp nào trên trang:

$('body').toggleClass('notransition');

2
Trên thực tế đây là lựa chọn hoàn hảo imo. Đặc biệt là * giúp rất nhiều, đảm bảo rằng không có hoạt ảnh phụ nào được kích hoạt. Cảm ơn, nâng cao.
SchizoDuckie

Đây là câu trả lời đúng cho các tình huống mà bạn chỉ muốn làm tất cả cùng một lúc. Chẳng hạn, tôi muốn tắt chuyển đổi trong khi xoay trên thiết bị di động và điều này là hoàn hảo cho điều đó.
Ben Lachman

Tôi đã kết thúc việc sử dụng nó trong angularjs, trong một kịch bản hơi phức tạp, nhưng trời ơi, điều này rất hữu ích sau nhiều ngày đập đầu tôi.
MP Aditya

2
Hiệu suất khôn ngoan Tôi không thể mong đợi đây sẽ là một ý tưởng tốt. "Ồ, chỉ cần áp dụng điều này cho MỌI THỨ trên trang, điều đó giúp mọi việc dễ dàng hơn!"
Lodewijk

1
Có lẽ nên chọn cả ".notransition" và ".notransition *" để có hiệu quả đầy đủ.
Nathan

9

Đối với một giải pháp JS tinh khiết (không có lớp CSS), chỉ cần thiết lập transitionđể 'none'. Để khôi phục quá trình chuyển đổi như được chỉ định trong CSS, hãy đặt transitionchuỗi thành chuỗi trống.

// Remove the transition
elem.style.transition = 'none';

// Restore the transition
elem.style.transition = '';

Nếu bạn đang sử dụng tiền tố của nhà cung cấp, bạn cũng cần phải đặt các tiền tố đó.

elem.style.webkitTransition = 'none'

8

Bạn có thể vô hiệu hóa hình ảnh động, chuyển tiếp, trasforms cho tất cả các yếu tố trong trang với mã css này

var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = '* {' +
'/*CSS transitions*/' +
' -o-transition-property: none !important;' +
' -moz-transition-property: none !important;' +
' -ms-transition-property: none !important;' +
' -webkit-transition-property: none !important;' +
'  transition-property: none !important;' +
'/*CSS transforms*/' +
'  -o-transform: none !important;' +
' -moz-transform: none !important;' +
'   -ms-transform: none !important;' +
'  -webkit-transform: none !important;' +
'   transform: none !important;' +
'  /*CSS animations*/' +
'   -webkit-animation: none !important;' +
'   -moz-animation: none !important;' +
'   -o-animation: none !important;' +
'   -ms-animation: none !important;' +
'   animation: none !important;}';
   document.getElementsByTagName('head')[0].appendChild(style);

1
Đầu tiên, điều này thật tuyệt vời, cảm ơn bạn! Thứ hai, cũng có một số thuộc tính khác sẽ được thiết lập; xem github.com/japgolly/test-state/blob/master/util/ Shared
src / test / ám

@Golly Những thuộc tính khác có thể ảnh hưởng đến thiết kế cuối cùng
jonperl

0

Tôi nghĩ bạn có thể tạo một lớp css riêng mà bạn có thể sử dụng trong những trường hợp sau:

.disable-transition {
  -webkit-transition: none;
  -moz-transition: none;
  -o-transition: color 0 ease-in;
  -ms-transition: none;
  transition: none;
}

Sau đó, trong jQuery bạn sẽ chuyển đổi lớp như vậy:

$('#<your-element>').addClass('disable-transition');

vâng tôi nghĩ rằng đây là cách tiếp cận tốt nhất, trên thực tế, plugin có thể đưa khối css đó vào trang
Sam Saffron

3
Bạn có chắc chắn không có! Thước đo LỚP quan trọng sẽ ghi đè ID một?
DaneSoul

0

Nếu bạn muốn một giải pháp không cần thiết đơn giản để ngăn chặn tất cả các chuyển đổi:

  1. Thêm CSS này:
body.no-transition * {
  transition: none !important;
}
  1. Và sau đó trong js của bạn:
document.body.classList.add("no-transition");

// do your work, and then either immediately remove the class:

document.body.classList.remove("no-transition");

// or, if browser rendering takes longer and you need to wait until a paint or two:

setTimeout(() => document.body.classList.remove("no-transition"), 1);

// (try changing 1 to a larger value if the transition is still applying)

-1

Nếu bạn muốn xóa chuyển đổi, chuyển đổi và hoạt ảnh CSS khỏi trang web hiện tại, bạn có thể thực hiện đoạn script nhỏ này tôi đã viết (bên trong bảng điều khiển trình duyệt của bạn):

let filePath = "https://dl.dropboxusercontent.com/s/ep1nzckmvgjq7jr/remove_transitions_from_page.css";
let html = `<link rel="stylesheet" type="text/css" href="${filePath}">`;
document.querySelector("html > head").insertAdjacentHTML("beforeend", html);

Nó sử dụng vanillaJS để tải tập tin css này . Đây cũng là một repo github trong trường hợp bạn muốn sử dụng cái này trong ngữ cảnh của một cái cạp (Ruby-Selenium): remove-CSS-animations-repo


-3

làm

$('#elem').css('-webkit-transition','none !important'); 

trong js của bạn giết nó?

rõ ràng lặp lại cho mỗi.


1
sau đó bạn cần phải thiết lập lại nó sau khi thực tế, vì vậy bạn cần lưu trữ nó, điều này sẽ dẫn đến một số lượng lớn nồi hơi
Sam Saffron

-4

Tôi muốn có một lớp trong CSS của bạn như thế này:

.no-transition { 
  -webkit-transition: none;
  -moz-transition: none;
  -o-transition: none;
  -ms-transition: none;
  transition: none;
}

và sau đó trong jQuery của bạn:

$('#elem').addClass('no-transition'); //will disable it
$('#elem').removeClass('no-transition'); //will enable it

1
Bạn có chắc chắn không có! Thước đo LỚP quan trọng sẽ ghi đè ID một?
DaneSoul

1
Có, điều đó sẽ xảy ra bởi vì hiện tại bạn đang nhắm mục tiêu # elem.no-quá trình chuyển đổi, cụ thể hơn là chỉ id
Moin Zaman

3
@MoinZaman Erm, nhưng bạn chưa nhắm mục tiêu #elem.no-transitiontrong CSS của mình, bạn vừa nhắm mục tiêu .no-transition. Có lẽ bạn muốn viết #elem.no-transitionCSS của bạn?
Đánh dấu Amery
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.