Fade element out using vanilla javascript and css

Black Sulfur
Black Sulfur used Ask the Experts™
on
Seems like jQuery is way easier to do simple tasks like this but I want to do it with pure javascript instead which seems significantly harder. Anyway, I just want to fade out an element when a button is clicked. I want to use css for the fade but I believe that you cannot transition display: none;

I have tried to first fade out and then totally remove the element but the display:none seems to fire instantly as I don't see the fade out at all.

The css:

.fade-out {
    opacity: 0;
    visibility: hidden;
    transition-property: opacity, visibility;
    transition-duration: 1s, 0s;
    transition-delay: 0s, 1s;
}
.remove-vis {
    display: none;
}

Open in new window


My .then() block:

        .then(response => {
            const pendingLi = deleteBtn.closest('li');
            pendingLi.classList.add('fade-out');
            pendingLi.classList.add('remove-vis');
            btnSet.forEach(query => {
                query.style.visibility = 'visible';
            });
        })

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Zakaria AcharkiAnalyst Developer
Distinguished Expert 2018

Commented:
Here is a sample of pure JS fadeIn/fadeOut with the use of CSS "transition" property.

JAVASCRIPT
function fadeIn(el){
  el.classList.add('show');
  el.classList.remove('hide');  
}

function fadeOut(el){
  el.classList.add('hide');
  el.classList.remove('show');
}

document.body.addEventListener('click', e => {
  const deleteBtn = e.target;
  
  if (deleteBtn.classList.contains("delete")) {
    e.preventDefault();

    fadeOut(deleteBtn.parentNode);
  }
});

Open in new window


CSS
.show {
  opacity: 1;
  transition: opacity 1000ms;
}

.hide {
  opacity: 0;
  transition: opacity 1000ms;
}

Open in new window


Here is a sample :

https://jsfiddle.net/z_acharki/rm0xg7dv/2/

The for the delete we could use the setTimeout() since we know the transition delay, so for the provided example, we could use 1000.

Author

Commented:
I am trying to remove the entire <li>, not just the buttons this time :) And the problem is that with your code there is the nice fade out but there is a huge gap left where the list item was. So, that needs to be removed which I would have done with display:none but of course then you don't get the nice fade effect. I tried adding a height of 0 which sort of works but then I am left with an empty <li> with a class of fade-out which actually still takes up a bit of space.
Analyst Developer
Distinguished Expert 2018
Commented:
So I think it will be better to remove it at all from the DOM after the fadeout like :

function fadeOut(el, callback){
  el.classList.add('hide');
  el.classList.remove('show');
  
  if( callback ){
    setTimeout(function(){
      el.remove();
    }, 1000)
  }
}

document.body.addEventListener('click', e => {
  const deleteBtn = e.target;
  
  if (deleteBtn.classList.contains("delete")) {
    e.preventDefault();

    fadeOut(deleteBtn.closest('li'), 'remove');
  }
});

Open in new window


Sample here :

https://jsfiddle.net/z_acharki/rm0xg7dv/6/
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Author

Commented:
Is it not possible without setTimeout? It will work but not maybe the most elegant solution?
Zakaria AcharkiAnalyst Developer
Distinguished Expert 2018

Commented:
If you perform any request it will be better to remove it in the success callback, but if you don't you could use setTimeout it will be the correct simple way.

Author

Commented:
This is a general question. Why is it so easy with jQuery? It is literally just fadeOut() and that solves all problems. It fades the element out and removes it from the DOM completely. And since jQuery is a javascript library, isn't the code behind fadeOut() pure javascript?
Zakaria AcharkiAnalyst Developer
Distinguished Expert 2018

Commented:
First of all the jQuery fadeOut() just hides the elements and not remove them from the DOM (Official description: Hide the matched elements by fading them to transparent.).

So if we want to remove the element from the DOM we need to specify this in the callback function like :

item.fadeOut('slow', function(){
    item.remove();
})

Open in new window


The callback will be called as we do here after the set of time specified.

Author

Commented:
Do you know how to do this with 'transition'? I am trying that as well to weigh up my options but it won't fade.

function fadeOut(el) {
	var elem = document.querySelector(el);
	elem.style.transition = "opacity 0.5s linear 0s";
	elem.style.opacity = 0;
}

Open in new window



 .then(response => {
            const pendingLi = deleteBtn.closest('li');
            fadeOut('pendingLi');
            btnSet.forEach(query => {
                query.style.visibility = 'visible';
            });
        })

Open in new window

Zakaria AcharkiAnalyst Developer
Distinguished Expert 2018

Commented:
Using classes is more efficient than maintaining the inline style, why you can't use classes like the provided example shows?

Author

Commented:
I have ended up using your method with the classes but I like to learn different things so was just wondering about that. But I prefer the class way, I was just asking, that's all.
Zakaria AcharkiAnalyst Developer
Distinguished Expert 2018

Commented:
Ok I see, the problem in the previous code was that you're trying to pass a string as a selector so the querySelector can't find it when you have already the DOM object instance (pendingLi) so you just to pass it to the fade function and use it, something like :

function fadeOut(el) {
  el.style.transition = "opacity 0.5s linear 0s";
  el.style.opacity = 0;
}

.then(response => {
  const pendingLi = deleteBtn.closest('li');
  fadeOut(pendingLi);
  btnSet.forEach(query => {
      query.style.visibility = 'visible';
  });
})

Open in new window

Author

Commented:
Thank you for your patience!
Zakaria AcharkiAnalyst Developer
Distinguished Expert 2018

Commented:
Welcome anytime, Glad I could help.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial