[javascript] CSS 전환 효과를 일시적으로 비활성화하는 가장 깨끗한 방법은 무엇입니까?

다음 효과 중 일부 / 모두가 적용된 DOM 요소가 있습니다.

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

이 요소의 크기를 조정하는 jQuery 플러그인을 작성 중입니다.이 효과를 일시적으로 비활성화해야 부드럽게 크기를 조정할 수 있습니다.

이러한 영향을 일시적으로 비활성화 한 다음 다시 활성화하는 가장 우아한 방법은 부모로부터 적용되거나 전혀 적용되지 않을 수 있다는 점입니다.



답변

짧은 답변

이 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

또는 jQuery가있는이 JS는 …

$someElement.addClass('notransition'); // Disable transitions
doWhateverCssChangesYouWant($someElement);
$someElement[0].offsetHeight; // Trigger a reflow, flushing the CSS changes
$someElement.removeClass('notransition'); // Re-enable transitions

… 또는 다른 라이브러리 또는 프레임 워크를 사용하는 동등한 코드.

설명

이것은 실제로 상당히 미묘한 문제입니다.

먼저 *-transitionCSS 속성을 로 설정하기 위해 요소에 적용 할 수있는 ‘notransition’클래스를 만들고 싶을 것입니다 none. 예를 들어 :

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

(사소한 일이 있습니다-in의 부족에주의하십시오 -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')

순전히, 당신은 높이 변화가 애니메이션화되지 않을 것이라고 생각할 수 있습니다. 왜냐하면 ‘전이 없음’클래스가 적용되는 동안 발생하기 때문입니다. 현실에서는, 그러나, 그것은 것입니다 내가 해봤 모든 최신 브라우저에 적어도 애니메이션. 문제는 브라우저가 JavaScript 실행이 완료 될 때까지 필요한 스타일 변경 사항을 캐싱 한 다음 모든 변경 사항을 단일 리플 로우로 작성한다는 것입니다. 결과적으로 전환의 활성화 여부에 대한 순 변경은 없지만 높이에 대한 순 변경은 리플 로우를 수행합니다. 결과적으로 높이 변화에 애니메이션을 적용합니다.

이 문제를 해결하는 합리적이고 깨끗한 방법은 다음과 같이 1ms 시간 초과로 ‘전환 없음’클래스 제거를 래핑하는 것입니다.

// 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 실행 속도가 느려질 수 있기 때문입니다. Firefox는 리플 로우 전에 대기중인 기능을 실행합니다.

나는이 문제를 발견 한 유일한 해결책은 것입니다 강제 ‘notransition’클래스를 제거하기 전에, 그것을 만든 CSS 변경을 세척, 요소의 리플 로우. 이를 수행하는 방법은 여러 가지가 있습니다 . 여기 를 참조 하십시오 . 이를 수행하는 ‘표준’방법에 가장 가까운 것은 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/


답변

DaneSoul이 제안한대로 애니메이션 비활성화를 옹호하지만 스위치를 전역으로 만듭니다.

/*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;
} 

.notransition그런 다음 body요소에 적용 하여 페이지의 전환 애니메이션을 효과적으로 재정 의 할 수 있습니다 .

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


답변

전환을 차단하는 추가 CSS 클래스를 추가 한 다음 제거하여 이전 상태로 돌아갑니다. 이것은 CSS와 JQuery 코드를 짧고 간단하며 이해하기 쉽게 만듭니다.

CSS :

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

!important ID는 일반적으로 클래스보다 더 구체적이기 때문에이 규칙에 더 많은 “가중치”가 부여되도록 추가되었습니다.

JQuery :

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


답변

순수 JS 솔루션 (아무 CSS 클래스)의 경우, 단지를 설정 transition합니다 'none'. CSS에 지정된대로 전환을 복원하려면를 transition빈 문자열로 설정하십시오 .

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

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

공급 업체 접두사를 사용하는 경우 접두사도 설정해야합니다.

elem.style.webkitTransition = 'none'


답변

이 CSS 코드로 페이지의 모든 요소에 대해 애니메이션, 전환, 변형을 비활성화 할 수 있습니다

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);


답변

다음과 같은 경우에 사용할 수있는 별도의 CSS 클래스를 만들 수 있다고 생각합니다.

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

그런 다음 jQuery에서 다음과 같이 클래스를 토글합니다.

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


답변

모든 전환을 방지하기 위해 간단한 jquery없는 솔루션을 원할 경우 :

  1. 이 CSS를 추가하십시오 :
body.no-transition * {
  transition: none !important;
}
  1. 그리고 당신의 js에서 :
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)