คำตอบสั้น ๆ
ใช้ CSS นี้:
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
รวมทั้ง JS นี้ (ไม่มี 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
หรือ JS นี้ด้วย jQuery ...
$someElement.addClass('notransition'); // Disable transitions
doWhateverCssChangesYouWant($someElement);
$someElement[0].offsetHeight; // Trigger a reflow, flushing the CSS changes
$someElement.removeClass('notransition'); // Re-enable transitions
... หรือรหัสเทียบเท่าโดยใช้ไลบรารีหรือกรอบงานอื่นที่คุณกำลังทำงานด้วย
คำอธิบาย
นี่เป็นปัญหาที่ค่อนข้างบอบบาง
ขึ้นเป็นครั้งแรกคุณอาจต้องการที่จะสร้าง 'notransition' class ที่คุณสามารถนำไปใช้กับองค์ประกอบในการตั้งค่าของพวกเขา*-transition
คุณลักษณะ CSS none
เพื่อ ตัวอย่างเช่น
.notransition {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
(แยกออกจากกัน - โปรดสังเกตว่าไม่มี-ms-transition
ในนั้นคุณไม่จำเป็นต้องใช้ Internet Explorer รุ่นแรกเพื่อรองรับการเปลี่ยนเลยคือ IE 10 ซึ่งรองรับพวกเขาไม่ได้เตรียมการไว้ล่วงหน้า)
แต่นั่นเป็นเพียงรูปแบบและเป็นบิตง่าย เมื่อคุณลองและใช้คลาสนี้คุณจะพบกับดัก กับดักคือรหัสเช่นนี้จะไม่ทำงานอย่างที่คุณคาดหวัง:
// 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')
อย่างไร้เดียงสาคุณอาจคิดว่าการเปลี่ยนแปลงความสูงจะไม่เคลื่อนไหวเพราะมันเกิดขึ้นในขณะที่มีการใช้คลาส 'notransition' ในความเป็นจริงแม้ว่ามันจะเป็นภาพเคลื่อนไหวอย่างน้อยในเบราว์เซอร์ที่ทันสมัยทั้งหมดที่ฉันได้ลอง ปัญหาคือเบราว์เซอร์กำลังแคชการเปลี่ยนแปลงในสไตล์ที่จำเป็นต้องใช้จนกว่า JavaScript จะเสร็จสิ้นการเรียกใช้งานจากนั้นทำการเปลี่ยนแปลงทั้งหมดในการ reflow ครั้งเดียว เป็นผลให้มันทำการ reflow ที่ไม่มีการเปลี่ยนแปลงสุทธิว่าเปิดใช้งานการเปลี่ยนหรือไม่ แต่มีการเปลี่ยนแปลงสุทธิกับความสูง ดังนั้นมันจะเคลื่อนไหวการเปลี่ยนแปลงความสูง
คุณอาจคิดว่าวิธีที่สมเหตุสมผลและสะอาดตาในการหลีกเลี่ยงสิ่งนี้คือการลบการกำจัด 'notransition' ในเวลา 1 มิลลิวินาทีเช่นนี้
// 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);
แต่มันก็ไม่ได้ผลเหมือนกัน ฉันไม่สามารถทำลายโค้ดข้างต้นในเบราว์เซอร์ WebKit ได้ แต่ใน Firefox (ทั้งบนเครื่องที่ช้าและเร็ว) บางครั้งคุณจะ (ดูเหมือนจะสุ่ม) จะมีพฤติกรรมเหมือนกับการใช้วิธีการที่ไร้เดียงสา ฉันเดาว่านี่คือสาเหตุที่เป็นไปได้ที่การเรียกใช้ JavaScript จะช้าพอที่ฟังก์ชันการหมดเวลาจะรอดำเนินการตามเวลาที่เบราว์เซอร์ไม่ได้ทำงานและจะคิดเกี่ยวกับการทำ reflow แบบฉวยโอกาสและหากเกิดเหตุการณ์ขึ้น Firefox ดำเนินการฟังก์ชันที่อยู่ในคิวก่อนที่จะทำการ reflow
ทางออกเดียวที่ฉันพบปัญหาคือการบังคับให้ reflow ขององค์ประกอบล้างการเปลี่ยนแปลง CSS ที่ทำกับมันก่อนที่จะลบชั้น 'notransition' มีหลายวิธีในการทำเช่นนี้ - ดูที่นี่สำหรับบางคน สิ่งที่ใกล้เคียงที่สุดคือวิธี 'มาตรฐาน' ในการทำเช่นนี้คือการอ่านoffsetHeight
คุณสมบัติขององค์ประกอบ
ทางออกหนึ่งที่ใช้งานได้จริงคือ
someElement.classList.add('notransition'); // Disable transitions
doWhateverCssChangesYouWant(someElement);
someElement.offsetHeight; // Trigger a reflow, flushing the CSS changes
someElement.classList.remove('notransition'); // Re-enable transitions
นี่เป็นซอ JS ที่แสดงให้เห็นถึงสามวิธีที่เป็นไปได้ที่ผมได้อธิบายไว้ที่นี่ (ทั้งวิธีการที่ประสบความสำเร็จหนึ่งและสองคนไม่ประสบความสำเร็จ):
http://jsfiddle.net/2uVAA/131/