最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - CSS3 replacement for jQuery.fadeIn and fadeOut - Stack Overflow

programmeradmin5浏览0评论

I have written a small amount of code to try and replicate jQuery's .fadeIn() and .fadeOut() functions using CSS transitions to look better on touch devices.

Ideally I'd like to avoid using a library so that I can write exactly what I want, and as a learning exercise.

fadeOut works well.

The idea for fadeIn is to use CSS3 transitions to adjust the opacity of an element, after which the element will be set to display:block; (using is-hidden class) to ensure it's not still clickable or covering something beneath it.

fadeIn is not working though. I think it is due to adding the is-animating class at the same time as removing the is-hiding class. The transitionEnd event never fires because a transition does not occur:

function fadeIn (elem, fn) {
  var $elem = $(elem);

  $elem.addClass('is-animating');
  $elem.removeClass('is-hidden');
  $elem.removeClass('is-hiding');

  $elem.on(transitionEndEvent, function () {

    $elem.removeClass('is-animating');

    if (typeof fn === 'function') {
      fn(); 
    }
  });
}; 

And the CSS

.is-animating {
  @include transition(all 2000ms);
}

.is-hiding {
  // Will transition
  @include opacity(0);
}

.is-hidden {
  // Won't transition
  display: none;
}

Here's the code: CodePen link

Update: I have found what I'd describe as a hack, but that works very well: CSS3 replacement for jQuery.fadeIn and fadeOut

Working code after this fix: Fixed

A solution without setTimeout would be very valuable though.

I have written a small amount of code to try and replicate jQuery's .fadeIn() and .fadeOut() functions using CSS transitions to look better on touch devices.

Ideally I'd like to avoid using a library so that I can write exactly what I want, and as a learning exercise.

fadeOut works well.

The idea for fadeIn is to use CSS3 transitions to adjust the opacity of an element, after which the element will be set to display:block; (using is-hidden class) to ensure it's not still clickable or covering something beneath it.

fadeIn is not working though. I think it is due to adding the is-animating class at the same time as removing the is-hiding class. The transitionEnd event never fires because a transition does not occur:

function fadeIn (elem, fn) {
  var $elem = $(elem);

  $elem.addClass('is-animating');
  $elem.removeClass('is-hidden');
  $elem.removeClass('is-hiding');

  $elem.on(transitionEndEvent, function () {

    $elem.removeClass('is-animating');

    if (typeof fn === 'function') {
      fn(); 
    }
  });
}; 

And the CSS

.is-animating {
  @include transition(all 2000ms);
}

.is-hiding {
  // Will transition
  @include opacity(0);
}

.is-hidden {
  // Won't transition
  display: none;
}

Here's the code: CodePen link

Update: I have found what I'd describe as a hack, but that works very well: CSS3 replacement for jQuery.fadeIn and fadeOut

Working code after this fix: Fixed

A solution without setTimeout would be very valuable though.

Share Improve this question edited May 23, 2017 at 12:21 CommunityBot 11 silver badge asked Nov 28, 2013 at 10:53 AlexAlex 8,6829 gold badges47 silver badges58 bronze badges 0
Add a ment  | 

4 Answers 4

Reset to default 1

i don't know what you really wanna achieve but if your using css3 your using a modern browser. in that case pure css & javascript is a better solution.

it's all about how you write the css transition.

here is the js code

var div=document.getElementsByTagName('div')[0],
    btn=document.getElementsByTagName('button')[0];
div.addEventListener('click',function(){
 this.classList.add('hide');
},false);
div.addEventListener('webkitTransitionEnd',function(e){
 console.log(e.propertyName);
},false);
btn.addEventListener('click',function(e){
 div.classList.toggle('hide');
},false);

css code

div{
 width:200px;height:200px;
 opacity:1;
 overflow:hidden;
 line-height:200px;
 text-align:center;
 background-color:green;
    -webkit-transition:opacity 700ms ease 300ms,height 300ms ease ;
}
div.hide{
 height:0px;
 opacity:0;
    -webkit-transition:opacity 700ms ease,height 300ms ease 700ms;
 /*add the various -moz -ms .. prefixes for more support*/
}

and the html

some text 
<div>click here</div>
some text
<button>toggle</button>

here is an example.

http://jsfiddle/qQM5F/1/

Alternative solution using Keyframes

js

var div=document.getElementsByTagName('div')[0],
    btn=document.getElementsByTagName('button')[0];

div.addEventListener('webkitAnimationEnd',function(e){
 div.style.display=div.classList.contains('hide')?'none':'';
},false);

btn.addEventListener('click',function(e){
 div.style.display='';
 div.classList.toggle('hide');
},false);

css3

div{
 background-color:green;
 -webkit-animation:x 700ms ease 0ms 1 normal running;/*normal*/
 opacity:1;
}
div.hide{
 -webkit-animation:x 700ms ease 0ms 1 reverse running;/*reverse*/
 opacity:0;
}
@-webkit-keyframes x{
 0%{opacity:0;}
 100%{opacity:1;}
}

example

http://jsfiddle/qQM5F/8/


here is a prototype

Object.defineProperty(HTMLElement.prototype,'toggleOpacity',{value:function(){
 function check(e){
  this.style.display=this.classList.contains('hide')?'none':'';
  this.removeEventListener('webkitAnimationEnd',check,false);// clean up
 }
 this.addEventListener('webkitAnimationEnd',check,false);
 this.style.display='';
 this.classList.toggle('hide');
},writable:false,enumerable:false});

css

.fade{
 -webkit-animation:x 700ms ease 0 1 normal;
 opacity:1;
}
.fade.hide{
 -webkit-animation:x 700ms ease 0 1 reverse;
 opacity:0;
}
@-webkit-keyframes x{
 0%{opacity:0}
 100%{opacity:1}
}

usage

the element you need to fade needs a class fade then toggle it with

element.toggleOpacity();

example

http://jsfiddle/qQM5F/9/

You may want to consider a couple of plugins that might take care of what you want:

  • jQuery.transition.js retrofits the existing jQuery animation methods to use CSS transitions in browsers that support them.

  • Transit adds a transition function you can use to define your own transitions. It uses jQuery's effect queue, so you can queue up the changed display value to run after opacity has finished transitioning.

I have managed to fix this by doing something that feels unnatural and hacky:

function fadeIn (elem, fn) {
  var $elem = $(elem);

  $elem.addClass('is-animating');
  $elem.removeClass('is-hidden');

  // Smelly, setTimeout fix
  setTimeout(function () {
    $elem.removeClass('is-hiding');
  }, 0);

  $elem.on(transitionEndEvent, function () {

    $elem.removeClass('is-animating');

    if (typeof fn === 'function') {
      fn(); 
    }
  });
}; 

Adding the setTimeout function to the class that contains the transition-able property fixes the issue.

Working code here: Codepen fixed code

发布评论

评论列表(0)

  1. 暂无评论