jQueryなど便利なライブラリもいいですが、軽量でカスタマイズ自由自在なオリジナリティあふれるネイティブJavaScriptを書くのもいいかも。
jQueryなど便利なライブラリもいいですが、軽量でカスタマイズ自由自在なオリジナリティあふれるネイティブJavaScriptを書くのもいいかも。

ポップアップ表示(大画像と小画像は同ファイル。オブジェクト版)

注意
これらの記事は2016年当時の物で結構古いです。モダンブラウザでは不要な記述やJavaScriptでなくともCSSで実現できる機能もあります。 当時の記録として残してありますがあまり参考になるものではありません。
概要
画像クリックで大きな画像をポップアップ表示します。
ポップアップする大画像とサムネイル画像は同ファイルです。
事情により敢えてファイルを1個にしたい場合に使用します。
任意のタイミングで呼び出せるようにカプセル化せずにFlyoutSelf.init()のみアクセス可能にしています。
使用方法
JavaScript内のコメント参照ください。
備考
大画像とサムネイル画像を分けた場合のJavaScriptコードを改変している為、一部無駄な記述があるかと思います。

/**
 * flyout self
 *
 * usage:
 * <img src="image/aaa.gif" class="flyoutself" alt="text">
 * 画像をポップアップ表示する
 *
 * 例えば、原寸800x500の画像をcssで200x125で縮小表示している場合、
 * ポップアップ表示では原寸の800x500で表示される。
 * 大画像とサムネイルで同じ画像ファイルを使用する場合。
 *
 * @author ao-system
 */

var FlyoutSelf = {
	init: function() {
		var _openSpeed = 1000;	//調整可能
		var _closeSpeed = 400;	//調整可能
		var _shown = false;			//work
		var _animating = false;		//work
		var _nowLoading = false;	//work
		var _thumbElm;				//work
		var _wrapElm;				//work
		var _largeElm;				//work
		var _headerText;			//work
		var _footerText;			//work
		var _largeAdjustWidth;		//work
		var _largeAdjustHeight;		//work
		initial();

		function initial() {
			var imgs = document.getElementsByTagName('img');
			for (var i = 0; i < imgs.length; i++) {
				if (imgs[i].getAttribute('class')) {
					var classes = imgs[i].getAttribute('class').split(' ');
					for (var j = 0; j < classes.length; j++) {
						if (classes[j] == 'flyoutself') {
							(function(elm){
								elm.addEventListener('click',function(){clickImg(elm);},false);	//サムネイルをクリック
								elm.style.cursor = 'pointer';
							})(imgs[i]);
						}
					}
				}
			}
		}
		function clickImg(elm) {
			if (_animating == true) {
				return;
			}
			if (_shown) {
				putAway(elm);
			} else {
				flyOutImage(elm);
			}
		}
		function scrolltop() {
			var bdy = document.body;
		    var d = document.documentElement;
		    if (bdy && bdy.scrollTop) {
				return bdy.scrollTop;
			}
		    if (d && d.scrollTop) {
				return d.scrollTop;
			}
		    if (window.pageYOffset) {
				return window.pageYOffset;
			}
		    return 0;
		}
		function cumulativeOffset(elm) {
			var ofsTop = 0;
			var ofsLeft = 0;
			do {
				ofsTop  += elm.offsetTop  || 0;
				ofsLeft += elm.offsetLeft || 0;
				elm = elm.offsetParent;
			} while (elm);
			return {
				ofsTop: ofsTop
				,ofsLeft: ofsLeft
			}
		}
		function flyOutImage(elm) {
			_animating = true;
			_shown = true;
			_thumbElm = elm;
			_wrapElm = document.createElement('div');
			_wrapElm.style.position = 'absolute';
			var ofs = cumulativeOffset(_thumbElm);
			_wrapElm.style.left = ofs.ofsLeft + 'px';
			_wrapElm.style.top = ofs.ofsTop + 'px';
			_wrapElm.style.backgroundColor = '#eee';
			_wrapElm.style.cursor = '';
			_largeElm = new Image();
			_largeElm.onload = function(){
				_nowLoading = false;
				loadLargeImage();
			};
			_largeElm.src = _thumbElm.src;
			_nowLoading = true;
			loading(false);
		}
		function loading(flag) {
			if (_nowLoading == false) {
				_thumbElm.style.opacity = '';
				return;
			}
			if (flag) {
				_thumbElm.style.opacity = '';
				setTimeout(function(){loading(false);},250);
			} else {
				_thumbElm.style.opacity = '0.5';
				setTimeout(function(){loading(true);},250);
			}
		}
		function loadLargeImage() {
			_largeElm.style.width = _thumbElm.width + 'px';
			_largeElm.style.height = _thumbElm.height + 'px';
			_largeElm.style.margin = '0px';
			_wrapElm.style.width = _thumbElm.width + 'px';
			_wrapElm.style.height = _thumbElm.height + 'px';
			_wrapElm.style.transition = 'all ' + (_openSpeed / 1000) + 's';
			_largeElm.style.transition = 'all ' + (_openSpeed / 1000) + 's';
			_wrapElm.style.opacity = '0.0';
			_wrapElm.appendChild(_largeElm);
			document.body.appendChild(_wrapElm);
			setTimeout(function(){loadLargeImageAnimate();},50);
			setTimeout(function(){
				if (_thumbElm.getAttribute('alt')) {
					altText(_thumbElm.getAttribute('alt'));
				}
				closeText();
				_wrapElm.style.cursor = 'pointer';
				_animating = false;
			},_openSpeed);
		}
		function altText(str) {
			_headerText = document.createElement('div');
			_headerText.innerHTML = str;
			_headerText.style.position = 'absolute';
			_headerText.style.width = (_largeAdjustWidth + 80) + 'px';
			_headerText.style.textAlign = 'center';
			_headerText.style.top = '6px';
			_headerText.style.color = '#fff';
			_headerText.style.fontSize = '20px';
			_wrapElm.appendChild(_headerText);
		}
		function closeText() {
			_footerText = document.createElement('div');
			_footerText.innerHTML = 'CLOSE';
			_footerText.style.position = 'absolute';
			_footerText.style.width = (_largeAdjustWidth + 80) + 'px';
			_footerText.style.textAlign = 'center';
			_footerText.style.top = (_largeAdjustHeight + 49) + 'px';
			_footerText.style.color = '#888';
			_footerText.style.fontSize = '16px';
			_wrapElm.appendChild(_footerText);
		}
		function loadLargeImageAnimate() {
			_largeAdjustWidth = _largeElm.naturalWidth;
			_largeAdjustHeight = _largeElm.naturalHeight;
			if (_largeAdjustWidth > (window.innerWidth - 80 - 20)) {
				_largeAdjustWidth = window.innerWidth - 80 - 20;
				_largeAdjustHeight = Math.floor((window.innerWidth - 80 - 20) * _largeElm.naturalHeight / _largeElm.naturalWidth);
			}
			if (_largeAdjustHeight > (window.innerHeight - 80 - 20)) {
				_largeAdjustHeight = window.innerHeight - 80 - 20;
				_largeAdjustWidth = Math.floor((window.innerHeight - 80 - 20) * _largeElm.naturalWidth / _largeElm.naturalHeight);
			}
			_largeElm.style.width = _largeAdjustWidth + 'px';
			_largeElm.style.height = _largeAdjustHeight + 'px';
			_largeElm.style.margin = '40px';
			_wrapElm.style.width = (_largeAdjustWidth + 80) + 'px';
			_wrapElm.style.height = (_largeAdjustHeight + 80) + 'px';
			_wrapElm.style.left = Math.floor((window.innerWidth - _largeAdjustWidth) / 2 - 40) + 'px';
			_wrapElm.style.top = Math.floor(((window.innerHeight - _largeAdjustHeight) / 2 - 40) + scrolltop()) + 'px';
			_wrapElm.style.opacity = '1.0';
			_wrapElm.addEventListener('click',function(){clickImg(_largeElm);},false);	//開いている大きな画像をクリック
		}
		function putAway(nextElm) {
			if (_animating == true || _shown == false) {
				return;
			}
			if (_shown) {
				_animating = true;
				setTimeout(function(){
					_wrapElm.style.transition = 'all ' + (_closeSpeed / 1000) + 's';
					_largeElm.style.transition = 'all ' + (_closeSpeed / 1000) + 's';
					_largeElm.style.width = _thumbElm.width + 'px';
					_largeElm.style.height = _thumbElm.height + 'px';
					_largeElm.style.margin = '0px';
					_wrapElm.style.width = _thumbElm.width + 'px';
					_wrapElm.style.height = _thumbElm.height + 'px';
					var ofs = cumulativeOffset(_thumbElm);
					_wrapElm.style.left = ofs.ofsLeft + 'px';
					_wrapElm.style.top = ofs.ofsTop + 'px';
					_wrapElm.style.opacity = '0.1';
					if (_headerText) {
						_wrapElm.removeChild(_headerText);
					}
					_wrapElm.removeChild(_footerText);
				},50);
				setTimeout(function(){
					document.body.removeChild(_wrapElm);
					_animating = false;
					_shown = false;
					if (nextElm != _largeElm) {	//大きな画像をクリックした場合はfalse
						if (nextElm != _thumbElm) {	//直前のサムネイル画像をクリックした場合はfalse
							clickImg(nextElm);
						}
					}
				},_closeSpeed);
			}
		}
	}
};
FlyoutSelf.init();