Animating a Lightbox with CSS & Javascript

css
Published on February 13, 2017

Use-Cases of this Tutorial

  • You are looking for an animated way to show a lightbox. The lightbox would animate and expand to the size of the screen.

Lightboxes are one of the common things implemented in websites, so animating them is a good idea to impress your visitors.

Demo

Click on the below container box

Inside Text
Close

Step 1 - What Happens When Container is Clicked

On being clicked, the position of the container is set to fixed. The CSS properties animated are width, height, top & left

  1. To show the animation of top & left properties, we need to set the initial top & left properties. This is done using the getBoundingClientRect() method.
  2. Set the position of the container as fixed.
  3. When the position of the container as fixed the elements below it will come up. This does not look nice. To solve this problem, an empty container has to be added in place of the lightbox container. Dimensions of this empty container is the same as the original container.
  4. Animation of container from normal size to full size happens by animating the calculated top & left properties to 0. But when doing the reverse animation, we need to animate the top & left properties from 0 to the original calculated values. To perform this animation we need to add dynamic keyframe CSS rules with Javascript using insertRule() method. To insert dynamic CSS rules we create an empty stylesheet.
  5. Hide the window scrollbar

Step 2 - What Happens When Animation from Normal Size to Full Size is Finished

  1. A close button is shown. A click on this will resize the container to its actual size.

Step 3 - What Happens When Close Button is Clicked

  1. Close button is hidden
  2. Overflow on the body is set to auto, so that the scrollbar comes up
  3. Animaton is done from full size to normal size with the help of dynamic keyframes that were earlier added

Step 4 - What Happens When Animation from Full Size to Normal Size is Finished

  1. All animation rules are removed
  2. fixed position is removed
  3. The empty container that was earlier added is removed
  4. The dynamic keyframe CSS rule that was earlier inserted is removed

There Should be More

When the lightbox goes to full size, there will be more content coming up (to show the actual content of the lightbox). However that is not shown in this tutorial. It is left to the reader to implement it by himself.

Codes

HTML

<div id="container-1">
	<div id="container-inner">Inside Text</div>
	<div id="close">Close</div>
</div>

CSS
Setting height: 100% for html & body is very important.

html {
	height: 100%;
}

body {
	height: 100%;
}

/* Lightbox container */
#container-1 {
	width: 500px;
	height: 200px;
	margin: 40px auto 0 auto;
	background-color: #2980b9;
	color: white;
	text-align: center;
}

#container-inner {
	line-height: 200px;
}

/* Empty container that will replace the original container */
#empty-container {
	width: 500px;
	height: 200px;
	margin: 40px auto 0 auto;
}

#close {
	position: absolute;
	right: 20px;
	top: 20px;
	cursor: pointer;
	display: none;
}

.in-animation {
	animation: inlightbox 0.8s forwards;
	position: fixed !important;
	margin: 0 !important;
}

.out-animation {
	animation: outlightbox 0.8s forwards;
}

@keyframes inlightbox 
{ 
	50% { 
		width: 100%;
		left: 0;
		height: 200px;
	}
	100% {
		height: 100%;
		width: 100%;
		top: 0;
		left: 0;
	}
}

Javascript

/* We need to create dynamic keyframes to show the animation from full-screen to normal. So we create a stylesheet in which we can insert CSS keyframe rules */
$("body").append('<style id="lightbox-animations" type="text/css"></style>');

/* Click on the container */
$("#container-1").on('click', function() {
	/* The position of the container will be set to fixed, so set the top & left properties of the container */ 
	var bounding_box = $("#container-1").get(0).getBoundingClientRect();
	$(this).css({ top: bounding_box.top + 'px', left: bounding_box.left + 'px' });

	/* Set container to fixed position. Add animation */
	$(this).addClass('in-animation');

	/* An empty container has to be added in place of the lightbox container so that the elements below don't come up
	Dimensions of this empty container is the same as the original container */
	$('<div id="empty-container"></div>').insertAfter("#container-1");

	/* To animate the container from full-screen to normal, we need dynamic keyframes */
	var styles = '';
	styles = '@keyframes outlightbox {';
		styles += '0% {'; 
		styles += 'height: 100%;';
		styles += 'width: 100%;';
		styles += 'top: 0px;';
		styles += 'left: 0px;';
		styles += '}';
		styles += '50% {'; 
		styles += 'height: 200px;';
		styles += 'top: ' + bounding_box.y + 'px;';
		styles += '}';
		styles += '100% {';
		styles += 'height: 200px;';
		styles += 'width: 500px;';
		styles += 'top: ' + bounding_box.y + 'px;';
		styles += 'left: ' + bounding_box.x + 'px;';
		styles += '}';
	styles += '}';

	/* Add keyframe to CSS */
	$("#lightbox-animations").get(0).sheet.insertRule(styles, 0);

	/* Hide the window scrollbar */
	$("body").css('overflow', 'hidden');
});

/* Click on close button when full-screen */
$("#close").on('click', function(e) {
	$("#close").hide();

	/* Window scrollbar normal */
	$("body").css('overflow', 'auto');

	/* Show animation */
	$("#container-1").addClass('out-animation');

	e.stopPropagation();
});

/* On animationend : from normal to full screen & full screen to normal */
$("#container-1").on('animationend', function(e) {
	/* On animation end from normal to full-screen */
	if(e.originalEvent.animationName == 'inlightbox') {
		$("#close").show();
	}
	/* On animation end from full-screen to normal */
	else if(e.originalEvent.animationName == 'outlightbox') {
		/* Remove fixed positioning, remove animation rules */
		$("#container-1").removeClass('in-animation').removeClass('out-animation');
		
		/* Remove the empty container that was earlier added */
		$("#empty-container").remove();

		/* Delete the dynamic keyframe rule that was earlier created */
		$("#lightbox-animations").get(0).sheet.deleteRule(0);
	}
});
In this Tutorial