O'Reilly

MooTools Overlay Plugin

By on  

Overlays have become a big part of modern websites; we can probably attribute that to the numerous lightboxes that use them. I've found a ton of overlay code snippets out there but none of them satisfy my taste in code. Many of them are bloated, inflexible, or nonfunctional. The only way to make myself happy was to create one of my own.

The MooTools JavaScript

var Overlay = new Class({
	
	Implements: [Options,Events],
	
	options:  {
		id: 'overlay',
		color: '#000',
		duration: 500,
		opacity: 0.5,
		zIndex: 5000/*,
		onClick: $empty,
		onClose: $empty,
		onHide: $empty,
		onOpen: $empty,
		onShow: $empty
		*/
	},
	
	initialize: function(container,options) {
		this.setOptions(options);
		this.container = document.id(container);
		this.overlay = new Element('div',{
			id: this.options.id,
			opacity: 0,
			styles: {
				position: 'absolute',
				background: this.options.color,
				left: 0,
				top: 0,
				'z-index': this.options.zIndex
			},
			events: {
				click: function() {
					this.fireEvent('click');
				}.bind(this)
			}
		}).inject(this.container);
		this.tween = new Fx.Tween(this.overlay,{ 
			duration: this.options.duration,
			link: 'cancel',
			property: 'opacity',
			onStart: function() {
				var size = this.container.getScrollSize();
				this.overlay.setStyles({
					width: size.x,
					height: size.y
				});
			}.bind(this),
			onComplete: function() {
				this.fireEvent(this.overlay.get('opacity') == this.options.opacity ? 'show' : 'hide');
			}.bind(this)
		});
	},
	open: function() {
		this.fireEvent('open');
		this.tween.start(this.options.opacity);
	},
	close: function() {
		this.fireEvent('close');
		this.tween.start(0);
	}
});

Arguments for Overlay include:

  • container: The container of that will host the overlay.
  • options: The class' options.

Options for Overlay include:

  • id: (defaults to 'overlay') The ID of the overlay to be created.
  • color: (defaults to '#000') The background color of the overlay.
  • duration: (defaults to 500) The open/close duration of the overlay.
  • opacity: (defaults to 0.5) The destination opacity level of the overlay.
  • zIndex: (defaults to 5000) The z-index of the overlay.

Events for Overlay include:

  • onClick: Executes when the overlay is clicked
  • onClose: Executes when the close directive has been given
  • onHide: Executes when the overlay is completely hidden
  • onOpen: Executes when open directive is given
  • onShow: Executes when overlay has faded into view

The Usage

var overlay = new Overlay(document.body,{
	id: 'overlay',
	color: '#000',
	duration: 300,
	opacity: 0.4,
	onClick: function() {
		this.close();
	},
	onShow: function() {
		//make ajax call while the overlay is happening...?
		//var Request = new Request()....
	}
});

As simple as it gets. Be sure to set the "id" option if you plan on using more than one overlay in the page (boooo).

Overlay Guidelines

A few notes about overlays:

  • Please, please, please use the click event above to hide the overlay:
    onClick: function() {
    	this.close();
    }
    
    Nothing bugs me more than clicking on an overlay and nothing happening.
  • Use the same background color for your overlays -- consistency is key.
  • Try to stick to using/re-using the same overlay -- creating a bunch of them only pollutes the DOM.

Now your body can easily get overlaid! Sweet!

Track.js Error Reporting

Recent Features

  • Chris Coyier’s Favorite CodePen Demos

    David asked me if I'd be up for a guest post picking out some of my favorite Pens from CodePen. A daunting task! There are so many! I managed to pick a few though that have blown me away over the past few months. If you...

  • Camera and Video Control with HTML5

    Client-side APIs on mobile and desktop devices are quickly providing the same APIs.  Of course our mobile devices got access to some of these APIs first, but those APIs are slowly making their way to the desktop.  One of those APIs is the getUserMedia API,...

Incredible Demos

  • MooTools Accordion: Mouseover Style

    Everyone loves the MooTools Accordion plugin but I get a lot of requests from readers asking me how to make each accordion item open when the user hovers over the item instead of making the user click. You have two options: hack the original plugin...

  • Rotate Elements with CSS Transformations

    I've gone on a million rants about the lack of progress with CSS and how I'm happy that both JavaScript and browser-specific CSS have tried to push web design forward. One of those browser-specific CSS properties we love is CSS transformations. CSS transformations...

Discussion

  1. Not bad. I have a custom class I’ve set up which does the same thing. It shows a veil over the page with a ‘Loading’ status at the top left.

    I use mine whenever I am doing an Ajax request, to prevent users from doing anything to page.

    Mine has the following methods:
    Loading [+ 1 to loading queue, brings up veil if needed]
    loaded [-1 to loading queue, hides veil if queue is empty]
    toggle [if no veil, calls loading. if veil, calls loaded]
    lock [+1 to lock queue, keeps veil up even if loaded]
    unlock [-1 to lock queue, hides veil if no locks or loads]
    toggleLock [if locked, calls unlock. if not locked, calls lock]
    lightsOff [makes veil mostly opaque]
    lightsOn [back to default transparency]
    toggleLights [toggles lightsOn / lightsOff]
    forceOff [clears queues, hides veil]
    timeless [no timeout on veil]
    timed [back to default, where veil calls forceOff after 90 seconds]
    toggleTimed [toggles timed / timeless]

    Also, when loading the veil has a z-index of 20. When locked it has a z-index of 10. These can be overridden in the options.

    I do use a small amount of HTML in the footer, since I have a loading image next to ‘Loading.’ You could avoid this by not using the image and injecting the elements via DOM on init.

  2. Very nice! Thanks for the post.

  3. EmEhRKay

    Nice. I love the perceived simplicity of the code, but it is full-featured — it does one thing and does it well.

    To reuse the same instance I would do a window.Overlay = new Overlay(..) in a dom ready call and just call window.Overlay.show/hide when I needed to cover the whole window.

    Good stuff

  4. @Timothy: please give a link to your class…

  5. Why not do more of this in css?

    All of my overlays are just css.

    	background: black;
    	position: fixed;
    	top: 0;
    	left: 0;
    	width: 100%;
    	height: 100%;
    	z-index: 1000;
    

    Even the transparency can be done in css.

    Granted position:fixed may not work 100% in IE6, but come on… it’s IE 6.

    I like this better because it works better when resizing the window. (JS is too slow in IE and FF … IMO)

    For the fade in I just do something like:
    fade(‘hide’);
    fade(‘in’);

  6. Great stuff indeed! :D

  7. olivier

    isn’t there already a class for this in mootools’ More?

  8. Nikolaj

    @ olivier & Marc Fowler
    You can in a way say that More already does have such class – though there’s differences between them.

    A short comparison of the two versions:

    Mask version:
    – No support for Fx
    – Size is calculated by .getSize()
    – Ability to add a mask over a specific Element through .mask()
    – IframeShim-support, to fix IE6’s issue with selectboxes, flash etc

    David’s version:
    – Support for Fx, giving ability to use fade-in/out
    – Size is calculated by .getScrollSize()
    – Much more simplified, does exactly what it’s supposed to

    Since Mask uses .getSize(), it gives issues if the user manages to scroll down the page. Both versions have a small issue if switching between normal and fullscreen-view though, where the size of the mask aren’t updated like it probably should (if mask is put inside the document.body).

  9. hi , very nice posting, please post more like this

  10. Maybe you should add an window.resize function to it so your overlay is always the correct size!

    But nice plugin, I just needed this!

  11. @Crispijn: Seems like an edge case.

  12. Yeah… I thought: Small tweak, and more effort but it isn’t necessary indeed.

  13. @Crispijn: Not so much about effort as it is about adding extra code. I may extend the class in the future to do more advanced things.

  14. theodore

    Hi, very nice! I just used it to generate a greeting card for my home page (see below) and it works very well except one minor issue…the new image element created upon ‘onShow’ was also faded out (even if a z-index had been set for the image to >5000). How to make the image remains original? Thanks and happy new year!

    	window.addEvent('domready',function() {
    		new Overlay(document.body, { 
    			duration: 400,
    			opacity: 0.5,
    			onShow: function() {
    				new Element('img', {
    					'id': 'greetingcard',
    					'src': '2010.jpg',
    					'width': 800,
    					'height': 400,
    					'styles': {
    						'position': 'absolute',
    						'top': 100,
    						'left': 200
    					}
    				}).inject(document.body);			
    			},
    			onClick: function() {  
    				$('card').destroy();
    				this.close(); 
    			}
    		}).open();				
    	});
    
  15. John

    Hello i have problem, i want to use the overlay by calling of a funtion:

     	window.addEvent('domready',function() {
    				var olay = new Overlay(document.body, { 
    				duration: 400,
    				onClick: function() {  this.close();	 }
    		});
    		});
    
    	//Change DIV tab
    function showDiv(t){
    if(t==1){
      document.getElementById('Div').style.display='block';
      olay.open();
    }
    if(t==0){
      document.getElementById('Div').style.display='none';
      olay.close();
    }
    }
    

    But i give a error:

    olay is not defined: olay.open();

    Please help me.

    Thanks

  16. @John: Your “olay” variable has lost scope. You need to give the olay variable global scope for your stuff to work, although I don’t advise it.

  17. Hello, I’m in the same camp with theodore up there…
    Can’t figure out how to have non-trasparent elements inside the overlay…

    Any hint will be very appreciated :)

    Bau,
    Wiz

  18. Thorsten

    After hiding the overlay again and resizing the window it causes nasty scrollbars as the hidden overlay is keeping the old window width. (tested on mac -> FF and safari)

    Anyone here with a workaround to fix this?

  19. Is there any way to use the overlay without an animation?
    I’d like to have overlay.set() on ‘domready’ and use overlay.start() on ‘load’.

    This is what I’ve tried, somehow this.tween.set() just doesn’t work:

    Overlay.implement({
    set: function() {
    this.fireEvent(‘set’);
    this.tween.set(this.options.opacity);
    }
    });

  20. Paddy

    Hi,
    how i can set the opacity of my content box “text” to 100%?

    var test = new Element('div', {
        'styles': {
              'background-color': '#FFF',
                'width': 300,
    'height': 200,
    'position': 'absolute',
    'top': 10,
    'left': 200
        },
    'html': 'test'
    });
    
    $('overlay').grab(test);
    

    thanks

  21. Sky

    It has a bug in it –

    on high resolution screens (above 1440×900) the dark area on your Demo does not cover entire page. There can be a huge gap on right.

  22. Crispijn

    @Sky: does this appear after you’ve changed the window size? This is correct. You can change this by adding a onResize event to the class.

  23. Han Solo

    Hi there,

    is there any possibility to fix the content of the first div layer while this overlay is open (and scrollable), and make it scrollable again when the overlay is closed?

    I’m a absolute beginner in terms of HTML, JS and CSS. But what I did so far is set up a HTML file with linked images. This page is scrollable. When I click on a image I use your Overlay script to fade-in a dark background make a hidden div visible. This div contains either text, several images or flash video. I use onShow document.getElementById(“overlaycontent”).style.display = ‘block'; onClose I use document.getElementById(“overlaycontent”).style.display = ‘none’. This works so far.

    But how can I make the lower content div unscrollable while the overlay is scrollable and on close the other way round? I tried to use document.getElementById(“content”).style.position = ‘fixed’. But than the background jumps to the first position. It should be fixed at the current scroll position. Any idea?

    I hope you got me :)

  24. false

    @Crispijn: Hi, did you tried to add a ‘onResize’ event to your overlay class ? If yes, what did you do in this event ? Because i have this issue and i would like to solved it :/ but fail

    ty :)

  25. aschemel

    how can i embed a html in the overlay, i want the overlay to carry a form, so i can edit some text fields? I new in web developing =D

  26. bobgodwin

    How do I change “shower” to a class instead of an id. I’d like to use it on several links.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!

Recently on David Walsh Blog

  • Serve a Directory via Python

    Sometimes I'm working with a test HTML file and some JavaScript but need to work off of a served space.  In that case, I sometimes need to swap out folders within MAMP Stack which leads to a maintenance nightmare.  Bleh. I recently found out that you can...

  • OSCON Portland:  Conference  Discount!

    O'Reilly puts on the best web industry conferences in the world.  These conferences include Fluent Conference, Velocity Conference, and the upcoming OSCON in Portland, Oregon from July 20-24.  Open Source Convention (OSCON) is a conference that focuses specifically on open source developers and the tools and possibilities...

  • Follow Redirects with cURL

    I love playing around with cURL. There's something about loading websites via command line that makes me feel like some type of smug hacker, just like tweeting from command line does. I recently cURL'd the Google homepage and saw the following: I found it weird that Google...

  • Developers Have WordPress, Amateurs Have Squarespace, Professional Designers Have the NEW Webydo!

    Web design platforms have traditionally come in one of two varieties. There are the solutions like WordPress and Drupal that are incredibly powerful, but an understanding of web development and coding is required to be able to use those platforms effectively. On the other side of the...

  • Chris Coyierâs Favorite CodePen Demos II

    Hey everyone! Before we get started, I just want to say it’s damn hard to pick this few favorites on CodePen. Not because, as a co-founder of CodePen, I feel like a dad picking which kid he likes best (RUDE). But because there is just so...