27

I have div with id='mainmenu'. I'm adding CSS3 transition to it by JavaScript after button click (by adding 'transition' to #mainmenu and by creating class .fadein and .fadeout that will be added to the div element). Code:

<div id='mainmenu'></div>
<button id="btn1">Click me1</button>
<button id="btn2">Click me2</button>

#mainmenu {
    width:100px; 
    height:100px; 
    background:#eee; 
    -webkit-transition: opacity 1s; 
    -moz-transition: opacity 1s; 
    transition: opacity 1s; 
}

.fadeout {
    opacity:0;
}
.fadein {
    opacity:1;
}


var menu = document.getElementById('mainmenu'),
    btn1 = document.getElementById('btn1'),
    btn2 = document.getElementById('btn2');

btn1.addEventListener('click', function() {
    menu.className = 'fadeout';
}
btn2.addEventListener('click', function() {
    menu.className = 'fadein';
}

The problem is that now I want to add display none and block to fadeout and fadein option. So after the fadeout animation div should get display none, and after fadein display block:

btn1.addEventListener('click', function() {
    menu.className = 'fadeout';
    menu.style.display = 'none';
}
btn2.addEventListener('click', function() {
    menu.className = 'fadein';
    menu.style.display = 'block';
}

Unfortunately, the display none and block executes with the animation, so the animation isn't working (element gets display none, without the opacity animation). I want first the animation with opacity, and after that display none/block for the element. Is there any way to do it? I can use only pure JavaScript (no jQuery etc.).

1
  • 1
    Could you please add a fiddle.js with the code.? Commented Sep 3, 2013 at 21:19

4 Answers 4

17

You need to use setTimeout() with menu.style.display = "none"; in order to let fade do it's job before you trigger style.display.

btn1.addEventListener('click', function() {
    menu.className = 'fadeout';
    setTimeout(function() {
        $(menu).css('display', 'none');
    }, 1000);
}
btn2.addEventListener('click', function() {
    menu.className = 'fadein';
    setTimeout(function() {
        $(menu).css('display', 'block');
    }, 1000);
}
Sign up to request clarification or add additional context in comments.

5 Comments

There is a small problem - when you have 'menu' in setTimeout(function(menu){}), the console shows 'Cannot read property 'style' of undefined'. Removing 'menu' from function will fix that problem. Thank you for help.
of course, hesitated about whether to include that for a sec the first time and made a mistake
Curious about which browser supports .hide()/.show() - In chrome you would get Uncaught TypeError: Object #<HTMLDivElement> has no method 'hide'
dc5 - in your case, it's probably a problem of jQuery library not being included, or a conflict with another library. If you use other libraries, try using "jQuery" instead of "$". Another possibility is that you are passing the wrong object. There is an example here : api.jquery.com/hide , which works on my chrome.
@JevgeniBogatyrjov: The problem was the answer code using the same variable name ('menu') for both the DOM Node ('menu.className') and jQuery ('menu.hide'). Fixed :)
13

Although this is an old post, for future visitor's sake, you can use the transitionend event. You can use:

/*For when object has fully faded*/
menu.addEventListener("transitionend", function() {
  if (this.className == "fadeout") {
    this.style.display = "none";
  }
}.bind(menu));

/*Show before animation starts*/
menu.addEventListener("click", function() {
  this.style.display = "block";
}.bind(menu));

Comments

10

I could be wrong here, however i believe you need to add a transition-end trigger that does the display:block / display:none change.

see: CSS3 transition events

1 Comment

You cannot have CSS transition event "display"
8

I use height 0 instead of display none for some cases but It may or may not apply for what you need. Anyway here's the code:

1) Using transitions (looks like jQuerys fadeOut):

.fadeOut{
  opacity : 0;
  height : 0;
  transition : opacity 800ms, height 0 800ms;
}

if you want you can add width 0 too.

.fadeOut{
  opacity : 0;
  width : 0;
  height : 0;
  transition : opacity 800ms, height 0 800ms, width 0 800ms;
}

2) Using animations (it works but transitions is better):

.fadeOut{
  animation : fadeout 800ms linear forwards;
}
@keyframes fadeout{
  99%{
    opacity : 0;
    height : initial;
  }
  100%{
    opacity : 0;
    height : 0;
  }
}

3 Comments

Oooh! That's super smart to use height: 0 so you can keep the logic with the CSS where it belongs. I'm usin' this!
Note that this could be an accessibility issue. The content would still be available to assistive technology when using height: 0 instead of display: none

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.