Sinister Beard
Sinister Beard

Reputation: 3680

Hiding a overlay when using modal boxes on a parallax scrolling layout

I'm designing a website that makes use of both parallax scrolling and modal boxes. When you open one of the modal boxes, I'm using jQuery and CSS to add a class to the popup's DIV element so that its opacity goes from 0 to 100; I'm using a transition to make this look pretty. When you close the box, jQuery strips the class out to set the opacity back to 0.

So that the modal boxes are more readable, I've put an overlay behind them (actually a containing DIV) that overlays a transparency over the rest of the screen using a width and height of 100%. I also use the same trick to take the opacity of this from 0 to 100 when the box is opened, and vice versa when it's closed.

The problem lies in that even at opacity 0, the overlay is still "above" some of the screen, rendering links and text viewable but not selectable. I've tried setting the Z-Index to 0 and -1 when the overlay is meant to be hidden, but because the parallax scrolling (I'm using a customised version of the SCRN template, for reference http://rodrigob.com/themes/scrn/) uses Relative, Fixed and Absolute positioning, the Z-Index only applies to some of the site.

As a workaround, styling the overlay with Visibility:Hidden works (as does Display:None, but I want to avoid that for accessibility reasons), but this can't be managed by a transition, so when the modal closes, it just disappears instead of fading out nicely.

Is there any way around this? I thought setting the Visibility to Hidden after the transition from 100 opacity to 0 had happened would work, but I don't know how to do this, if it can even be done at all.

Thanks in advance.

Upvotes: 3

Views: 1518

Answers (6)

patrickskim
patrickskim

Reputation: 183

Setting "opacity: 100" or "visibility: hidden" on the overlay isn't actually removing the overlay. What you want to do is remove the element.

Conceptually speaking the overlay is still there. Its like glass above your content, you can see but you can't touch, the invisible overlay glass is still there. It's like super transparent glass window thats been washed with windex That guy is the user trying to click on those links below the overlay.

What you want to do is either remove the element from the DOM or set it to "display: none" after the transition.

The best solution that is cross browser I would use is to set display: none after the animation.

$(".overlay").animate({"opacity": "0"}, function(){
    $(this).hide();
    // OR REMOVE it
    // $(this).remove();
});

Personally I like to wrap my modals in a container and give it a fixed postion and remove the container along with the modal contents on hide but thats me.

I also like jeffery's fancy css transition end method too, if you want to be fancy with css3 but the caveat is you'd probably have to detect which vendor prefix you have to listen to.

Here are the vendor prefixed transition ends:

var transitionEnd = {
  'WebkitTransition' : 'webkitTransitionEnd'
  ,  'MozTransition'    : 'transitionend'
  ,  'OTransition'      : 'oTransitionEnd'
  ,  'msTransition'     : 'transitionend'
  ,  'transition'       : 'transitionend'
}

You'd have to write something to detect it which one is relevant to the user.

$(".overlay").on(transitionEnd, function() {
    $(this).hide();
    // OR REMOVE it
    // $(this).remove();
}

Upvotes: 1

vals
vals

Reputation: 64164

I think that you CAN use z-index, and you don't need to look for work-arounds. The only thing that you probably need is to put the layout higher in the DOM tree. It's difficult to say without looking at your code, but if you could go to something like

<body>
    <div id="everyting-else">
       ...
    </div>
    <div id="overlay"/>
</body>

and then give #everyting-else a z-index of 2 and #overlay a z-index of 1, that should work whatever the content of "everything-else", because they are in a different stacking context.

It doesn't matter if you use "Relative, Fixed and Absolute positioning" inside the div

Upvotes: 0

Thomas
Thomas

Reputation: 21601

jQuery's function animate accepts a callback function, which executes when the animation is complete. Example:

$('.overlay').animate({
    opacity: 0
}, 300 /* animation duration in ms */, function () {
    // This will execute when the animation is complete
    $(this).css({
        visibility: 'hidden'
    });
});

Upvotes: 0

Ragnarokkr
Ragnarokkr

Reputation: 2328

Working only with opacity put the element in a context that can't be positioned via z-index because the element must be mixed with the other elements into the layout (W3C).

Further consideration is that elements with only opacity or visibility, doesn't come extracted from the layout flow so, even if not visible, they still occupy its position and size, and this will prevent every element underlying the one invisible to be reached (clicks are inhibited, buttons aren't clickable, and so on).

To solve your problem, you need to set display to none. In this way, the element will be invisible and no more occupy space into the layout flow.

Upvotes: 0

Jeffery To
Jeffery To

Reputation: 11936

You can listen for a transition end event to set visibility: hidden after the opacity transition.

Upvotes: 0

newtron
newtron

Reputation: 6114

Use setTimeout to start the animation after the overlay appears, and hide the overlay after the animation is finished

to show overlay:

// show the overlay (in whatever manner you like) BEFORE the animation starts
// opacity is 0
$('#overlay').show();
setTimeout(function() {
  // fade in the opacity AFTER the overlay is there
  $('#overlay').addClass('opaque');
}, 0);

to hide overlay:

// fade out the opacity BEFORE the overlay goes away
$('#overlay').removeClass('opaque');
setTimeout(function() {
  // hide the overlay (in whatever manner you like) AFTER the animation is done
  // opacity is 0
  $('#overlay').hide();
}, 250);

Upvotes: 1

Related Questions