jQuery Handling of CSS Classes

Though CSS3 transition animation support is still a little wonky, it’s getting better every day.  I’ve decided to pass all animation handling to CSS versus previously using jQuery’s fade functions.   jQuery is now simply the trigger, adding and removing classes.

Example: Fading Modal Box

A “modal window” is the technical term given to those annoying pop-ups in Windows.  It’s synonymous with dialog or alert.   In websites, the same concept is typically used to pop-up a larger version of a smaller image, as in a blog post.  For me, they’re useful as “page” content displays for websites which need to remain static, like in use of maps or dashboards.

jQuery

In the example below, a click listener handles the entire operation:

  • .modal-toggle is assigned to the button calling the action. ie: <a href=”#about” class=”.modal-toggle”>Click for About</a>
  • Of course, prevent default link action.
  • variable target references the href URL of the button or link. #about
  • This URL points to a div ID acting as my .modal. ie: <div id=”about”></div>
  • Next I add my “master” css class called .transitional to the .modal div.  I use a master class for applying CSS transition animations because obviously I don’t want to be adding this CSS to every single class that needs it — which increases browser load.
  • Now I’m using the link itself to judge if we’ve clicked on this before.
    • If the link has class active, then do the opposite first.  I don’t like testing negatives for if/else.
      • Remove class active, and remove class active on the modal.  Note we have to queue a delay to hide() a.k.a display: none because otherwise it won’t wait for the transition to finish. I set it to 500 ms ahead of my 400 ms.  See that hide() has a numeral hide(0) because this notifies jQuery to queue that operation; you could conceivably add more queued operations 1, 2, 3, etc.  This is required or delay does nothing.
    • If the link does not have it, let’s do our magic.
      • Add class active, then on the modal add class active.   Note we have to queue a delay on the addClass because otherwise the div will show() a.k.a. display: block immediately without waiting for the addClass.  The fancier queue function is used here because addClass cannot be queued itself.  So we have to nest it inside the available jQuery queue function.  dequeue() is required to again notify jQuery that addClass is a queued operation.   The delay is shorter, I’m just giving the browser time to separate the actions between show() and the addClass.
      • The animation is triggered by addClass(“active”) for the .modal div.
$(".modal-toggle").on("click", function(e) { 
        e.preventDefault();
	var target = $(this).attr("href");
	$(target).addClass("transitional");
	if ($(this).hasClass("active")) { 
		$(this).removeClass("active");
		$(target).removeClass("active").delay(500).hide(0);
	} else { 
		$(this).addClass("active");
		$(target).show().delay(10).queue(function(){
		    $(this).addClass("active").dequeue();
		});
	}
});

CSS

Simple enough!  The CSS is organized as follows:

  •  .modal creates our main control “layer”.  I’ve offset it from the top, assuming that’s where our main navigation link for .modal-toggle exists.  We don’t want to cover that up or we can’t close it.
  • .modal.active triggers our CSS animation to fade opacity to 100%.  That’s all it needs.
  • .content is an additional div layer nested under .modal because in general you should separate information out.  Also this lets you style the actual visible window as if it was centered on the page.
  • .transitional is my master CSS class.
.modal { 
	position: fixed;
	top: 5%;
	left: 0px;
	z-index: 1000;
	display: none;
	opacity: 0;
	width: 100%;
	height: 95%;
	}

.modal.active { 
	opacity: 1;
	}

.modal .content {
	position: relative;
	z-index: 200; 
	width: 80%; 
	height: 80%;
	margin: 0 auto 0 auto;
	background: #fff;
	padding: 20px;
	}

.transitional { 
    -webkit-transition: all 400ms ease-in;
    -moz-transition: all 400ms ease-in;
    -ms-transition: all 400ms ease-in;
    -o-transition: all 400ms ease-in;
    transition: all 400ms ease-in;
}