0

This is frustrating me to no end. Before I post the code, here's a summary:

The goal, in simple terms: when I double click X, I want it to fade out; when I click Y, I want X to fade in.

The method: I'm using CSS to create the actual fade-in and fade-out "animations." I'm using JavaScript to apply the classes when necessary using a little trickery.

The problem: the fade-in transition doesn't work -- the element just appears instantly. What is driving me insane is the fact that the fade-in, when instantly added back onto a faded-out object, works perfectly. I'll explain this better as a comment in the JS code.

(Yes, I've added opacity: 1 and transition: opacity onto the base elements. It had no effect at all.)

The code:

CSS

*.fade-out {
    opacity: 0;
    transition: opacity 400ms;
}
*.fade-in {
    opacity: 1;
    transition: opacity 400ms;
}
*.hide {
    display: none;
    visibility: hidden;
}

JavaScript

$( '#ArtistEmblem' ).on( 'dblclick', function() {
    fadeOut($( '#ArtistEmblem' ));
    fadeIn($( '#btnShowLogo' ));
});
$( '#btnShowLogo' ).on( 'click', function() {
    fadeOut($( '#btnShowLogo' ));
    fadeIn($( '#ArtistEmblem' ));
});

function fadeOut(element) {
    element.addClass( 'fade-out' );

    setTimeout( function () {
        element.addClass( 'hide' );

        /*
        * I tried immediately adding the 'fade-in' class here
        * and it worked -- as soon as the element faded out, it faded
        * back in (using the CSS transition). However, outside of this,
        * it REFUSES to work; everything appears instantly
        */

        console.log('timer triggered');
    }, 400);
}

function fadeIn(element) {
    element.removeClass( 'hide' );
    element.removeClass( 'fade-out' );
    element.addClass( 'fade-in' );
}

Relevant HTML

<div id="ArtistEmblem">
    <img src="img/logo_artist_2.png" />
</div>

<div id="PopMenu" class="collapse">
    <article>
        <header>
            <b>Debug Menu</b>
        </header>
        <section>
            <button id="btnOpenOverlay">Open Overlay</button>
            <button id="btnShowLogo" class="hide">Show Logo</button>
            <button id="btnClose">Close Menu</button>
        </section>
    </article>
</div>

I apologize if this is something obvious but I've wasted far too much time trying to solve it. I am also open to better, faster, or more efficient solutions if that would be the best answer. Thanks in advance!

1
  • 1
    add complete code along with the html that is used in your problem try creating the code snippet so that anyone can help. Commented Nov 12, 2017 at 3:47

3 Answers 3

1

The problem is that the initial opacity of "hidden" element is 1 by default. You just need to set it to 0. And also remove display: none

*.hide {
    opacity: 0;
}

Also I would do a little refactoring and remove setTimeout:

$('#ArtistEmblem').on('click', function() {
    fade($('#btnShowLogo'), $(this));
});
$('#btnShowLogo').on('click', function() {
    fade($('#ArtistEmblem'), $(this));
});

function fade(inElement, outElement) {
    inElement.removeClass('hide');
    inElement.addClass('fade-in');

    outElement.removeClass('fade-in');
    outElement.addClass('fade-out');
}

If you don't want the hidden element to occupy space and you want it to be displayed-none, then you need to set display: block before starting the fadeOut.

Sign up to request clarification or add additional context in comments.

5 Comments

That was my original solution (long before I worked in any JavaScript), but doesn't opacity: 0 still render the element? Also, it wouldn't explain why instantly adding the fade-in code (within the function) worked perfectly -- and that was without the initial opacity being changed. It makes no sense :\
@aprovokedkiwi I added a little update to make the procedure work smoother, I also removed setTimeout. Do you want the element to be faded out right in the place of the element which is being faded in? If yes, then z-index should be involved.
I'm actually not 100% certain of the full behavior, I was just hoping to get the fade-in and fade-out working regularly -- such that it could be applied to anything, at any time, to seamlessly fade in and out elements on the page. I'll see what I can do given your input, thank you!
One thing I'm still struggling with is why it works exactly as I want it to when I immediately remove the .hide class and re-add .fade-in within the same function -- and it works without altering the base elements in any way. This is what is frustrating me the most. Even if your answer solves my problem (I'm still working on that), I'd still like to figure that out, because it technically shouldn't work.. as far as I know. Is it maybe resolving the function before rendering the element, so that 'hide' never gets added because I immediately re-remove it? ... ugh I think that's it.
@aprovokedkiwi I agree, that's strange. I posted the question, let's see what the community will say.
1

I know you're asking for a JS heavy answer, but I highly recommend toggling a class of "active", "open" or something similar and using CSS with the transition. Less is more here.

Here's an example fiddle of something I've transitions not only the opacity, but also the z-index. That's the key with these transitions if you intend on having any elements below such as buttons that require hovering, clicking, etc.

JS Fiddle

Key parts:

.container {
  z-index: -1;
  opacity: 0;
  transition: z-index .01s 1s, opacity 1s;
}

.container.active {
  transition: z-index 0s, opacity 1s;
  z-index: 500;
  opacity: 1;
}

EDIT

I was just messing around with this type of thing for my own project, and observing how beautiful Stripe handles their navigation bar. Something so simple changes everything, and that's pointer-events. If you're okay with its support, (notable no ie. 10) this is infinitely easier to integrate. Here's another fiddle of the simulation in a nav bar.

The key part is pointer-events: none, as it ignores click events if set to none, almost as if it wasn't there, yet visibly it is. I highly recommend this.

https://jsfiddle.net/joshmoxey/dd2sts7d/1/

3 Comments

Believe me, I didn't want this to be JS heavy at all, but this particular "feature" was just something that mostly worked right off the bat, required a little tweaking, and turned into the mess above. If your JS Fiddle translates as well as I hope, it should be the perfect solution; I've just been operating under the assumption that display: none is the only method of hiding that "removes" the element from the page, so to speak -- as in, not just hidden, just not there.
What's the use case, and the reasoning for having it as display: none? I hope you find your solution with either mine or the other answers here. :)
Btw, if my fiddle does end up working for you, please for the love of god give me a green checkmark ;) I'm finally trying to earn some reputation on here.
0

Here is an example using Javascript Animate API. Animate API is not supported in IE/Edge though.

var element = document.getElementById("fade-in-out")

var button = document.getElementById("x")

button.addEventListener("click", function(event) {
  element.animate([{opacity: 1, visibility: "visible"},{opacity: 0, visibility: "hidden"}], {duration: 2000})
  
  setTimeout(function() { element.remove() }, 2000)
})

button.addEventListener("dblclick", function(event) {
  element && element.animate([{opacity: 0}, {opacity: 1}], {duration: 2000})
})
<input id="x" type="button" value="Click here" />
<div id="fade-in-out"> FADE ME </div>

Comments