diff --git a/css/reveal.css b/css/reveal.css
index 35a048fa9e8754e17f440dc9c352a57fb94a0885..2e18ade50d79cf6f1ac16ad2fec3e1c7ec6ddc49 100644
--- a/css/reveal.css
+++ b/css/reveal.css
@@ -624,63 +624,6 @@ body {
   -webkit-transition: none;
           transition: none; }
 
-/*********************************************
- * OVERVIEW
- *********************************************/
-.reveal.overview {
-  -webkit-perspective-origin: 50% 50%;
-          perspective-origin: 50% 50%;
-  -webkit-perspective: 700px;
-          perspective: 700px; }
-
-.reveal.overview .slides section {
-  height: 700px;
-  overflow: hidden;
-  opacity: 1 !important;
-  visibility: visible !important;
-  cursor: pointer;
-  background: rgba(0, 0, 0, 0.1);
-  -moz-box-sizing: border-box;
-       box-sizing: border-box; }
-
-.reveal.overview .slides section, .reveal.overview-deactivating .slides section {
-  -webkit-transition: none !important;
-          transition: none !important; }
-
-.reveal.overview .slides section .fragment {
-  opacity: 1; }
-
-.reveal.overview .slides section:after, .reveal.overview .slides section:before {
-  display: none !important; }
-
-.reveal.overview .slides section > section {
-  opacity: 1;
-  cursor: pointer; }
-
-.reveal.overview .slides section:hover {
-  background: rgba(0, 0, 0, 0.3); }
-
-.reveal.overview .slides section.present {
-  background: rgba(0, 0, 0, 0.3); }
-
-.reveal.overview .slides > section.stack {
-  padding: 0;
-  top: 0 !important;
-  background: none;
-  overflow: visible; }
-
-.reveal.overview .backgrounds {
-  -webkit-perspective: inherit;
-          perspective: inherit; }
-
-.reveal.overview .backgrounds .slide-background {
-  opacity: 1;
-  visibility: visible; }
-
-.reveal.overview .backgrounds .slide-background, .reveal.overview-deactivating .backgrounds .slide-background {
-  -webkit-transition: none !important;
-          transition: none !important; }
-
 /*********************************************
  * PAUSED MODE
  *********************************************/
@@ -901,6 +844,58 @@ body {
   -webkit-transition-duration: 1200ms;
           transition-duration: 1200ms; }
 
+/*********************************************
+ * OVERVIEW
+ *********************************************/
+.reveal.overview {
+  -webkit-perspective-origin: 50% 50%;
+          perspective-origin: 50% 50%;
+  -webkit-perspective: 700px;
+          perspective: 700px; }
+  .reveal.overview .slides section {
+    height: 700px;
+    opacity: 1 !important;
+    overflow: hidden;
+    visibility: visible !important;
+    cursor: pointer;
+    -moz-box-sizing: border-box;
+         box-sizing: border-box; }
+  .reveal.overview .slides section:hover, .reveal.overview .slides section.present {
+    outline: 10px solid rgba(150, 150, 150, 0.4);
+    outline-offset: 10px; }
+  .reveal.overview .slides section .fragment {
+    opacity: 1;
+    -webkit-transition: none;
+            transition: none; }
+  .reveal.overview .slides section:after, .reveal.overview .slides section:before {
+    display: none !important; }
+  .reveal.overview .slides > section.stack {
+    padding: 0;
+    top: 0 !important;
+    background: none;
+    outline: none;
+    overflow: visible; }
+  .reveal.overview .backgrounds {
+    -webkit-perspective: inherit;
+            perspective: inherit; }
+  .reveal.overview .backgrounds .slide-background {
+    opacity: 1;
+    visibility: visible;
+    outline: 10px solid rgba(150, 150, 150, 0.1);
+    outline-offset: 10px; }
+
+.reveal.overview .slides section, .reveal.overview-deactivating .slides section {
+  -webkit-transition: none;
+          transition: none; }
+
+.reveal.overview .backgrounds .slide-background, .reveal.overview-deactivating .backgrounds .slide-background {
+  -webkit-transition: none;
+          transition: none; }
+
+.reveal.overview-animated .slides, .reveal.overview-animated .slides section, .reveal.overview-animated .backgrounds .slide-background {
+  -webkit-transition: -webkit-transform 0.4s ease;
+          transition: transform 0.4s ease; }
+
 /*********************************************
  * RTL SUPPORT
  *********************************************/
diff --git a/css/reveal.scss b/css/reveal.scss
index a1c14a1e2d4e4955ff9125cd06fb509bc47f5668..70fe2c1ad7eb2d4ee3fdc138160b21e9da9b4c06 100644
--- a/css/reveal.scss
+++ b/css/reveal.scss
@@ -739,64 +739,6 @@ body {
 }
 
 
-/*********************************************
- * OVERVIEW
- *********************************************/
-
-.reveal.overview {
-	perspective-origin: 50% 50%;
-	perspective: 700px;
-}
-.reveal.overview .slides section {
-	height: 700px;
-	overflow: hidden;
-	opacity: 1 !important;
-	visibility: visible !important;
-	cursor: pointer;
-	background: rgba(0,0,0,0.1);
-	box-sizing: border-box;
-}
-.reveal.overview .slides section,
-.reveal.overview-deactivating .slides section {
-	transition: none !important;
-}
-.reveal.overview .slides section .fragment {
-	opacity: 1;
-}
-.reveal.overview .slides section:after,
-.reveal.overview .slides section:before {
-	display: none !important;
-}
-.reveal.overview .slides section>section {
-	opacity: 1;
-	cursor: pointer;
-}
-	.reveal.overview .slides section:hover {
-		background: rgba(0,0,0,0.3);
-	}
-	.reveal.overview .slides section.present {
-		background: rgba(0,0,0,0.3);
-	}
-.reveal.overview .slides>section.stack {
-	padding: 0;
-	top: 0 !important;
-	background: none;
-	overflow: visible;
-}
-
-.reveal.overview .backgrounds {
-	perspective: inherit;
-}
-.reveal.overview .backgrounds .slide-background {
-	opacity: 1;
-	visibility: visible;
-}
-.reveal.overview .backgrounds .slide-background,
-.reveal.overview-deactivating .backgrounds .slide-background {
-	transition: none !important;
-}
-
-
 /*********************************************
  * PAUSED MODE
  *********************************************/
@@ -1037,6 +979,76 @@ body {
 }
 
 
+/*********************************************
+ * OVERVIEW
+ *********************************************/
+
+.reveal.overview {
+	perspective-origin: 50% 50%;
+	perspective: 700px;
+
+	.slides section {
+		height: 700px;
+		opacity: 1 !important;
+		overflow: hidden;
+		visibility: visible !important;
+		cursor: pointer;
+		box-sizing: border-box;
+	}
+	.slides section:hover,
+	.slides section.present {
+		outline: 10px solid rgba(150,150,150,0.4);
+		outline-offset: 10px;
+	}
+	.slides section .fragment {
+		opacity: 1;
+		transition: none;
+	}
+	.slides section:after,
+	.slides section:before {
+		display: none !important;
+	}
+	.slides>section.stack {
+		padding: 0;
+		top: 0 !important;
+		background: none;
+		outline: none;
+		overflow: visible;
+	}
+
+	.backgrounds {
+		perspective: inherit;
+	}
+
+	.backgrounds .slide-background {
+		opacity: 1;
+		visibility: visible;
+
+		// This can't be applied to the slide itself in Safari
+		outline: 10px solid rgba(150,150,150,0.1);
+		outline-offset: 10px;
+	}
+}
+
+// Disable transitions transitions while we're activating
+// or deactivating the overview mode.
+.reveal.overview .slides section,
+.reveal.overview-deactivating .slides section {
+	transition: none;
+}
+
+.reveal.overview .backgrounds .slide-background,
+.reveal.overview-deactivating .backgrounds .slide-background {
+	transition: none;
+}
+
+.reveal.overview-animated .slides,
+.reveal.overview-animated .slides section,
+.reveal.overview-animated .backgrounds .slide-background {
+	transition: transform 0.4s ease;
+}
+
+
 /*********************************************
  * RTL SUPPORT
  *********************************************/
diff --git a/js/reveal.js b/js/reveal.js
index 9634c6bc30f685184d262ad40f6349e6bd880080..ad2d5a37c6d3307aa0b8df13d508522992d0357c 100644
--- a/js/reveal.js
+++ b/js/reveal.js
@@ -147,6 +147,9 @@
 		// Flags if reveal.js is loaded (has dispatched the 'ready' event)
 		loaded = false,
 
+		// Flags if the overview mode is currently active
+		overview = false,
+
 		// The horizontal and vertical index of the currently active slide
 		indexh,
 		indexv,
@@ -165,8 +168,9 @@
 		// The current scale of the presentation (see width/height config)
 		scale = 1,
 
-		// The current z position of the presentation container
-		z = 0,
+		// CSS transform that is currently applied to the slides container,
+		// split into two groups
+		slidesTransform = { layout: '', overview: '' },
 
 		// Cached references to DOM elements
 		dom = {},
@@ -296,7 +300,11 @@
 
 		features.touch = !!( 'ontouchstart' in window );
 
-		isMobileDevice = navigator.userAgent.match( /(iphone|ipod|ipad|android)/gi );
+		// Transitions in the overview are disabled in desktop and
+		// mobile Safari due to lag
+		features.overviewTransitions = !/Version\/[\d\.]+.*Safari/.test( navigator.userAgent );
+
+		isMobileDevice = /(iphone|ipod|ipad|android)/gi.test( navigator.userAgent );
 
 	}
 
@@ -1058,6 +1066,27 @@
 
 	}
 
+	/**
+	 * Applies CSS transforms to the slides container. The container
+	 * is transformed from two separate sources: layout and the overview
+	 * mode.
+	 */
+	function transformSlides( transforms ) {
+
+		// Pick up new transforms from arguments
+		if( typeof transforms.layout === 'string' ) slidesTransform.layout = transforms.layout;
+		if( typeof transforms.overview === 'string' ) slidesTransform.overview = transforms.overview;
+
+		// Apply the transforms to the slides container
+		if( slidesTransform.layout ) {
+			transformElement( dom.slides, slidesTransform.layout + ' ' + slidesTransform.overview );
+		}
+		else {
+			transformElement( dom.slides, slidesTransform.overview );
+		}
+
+	}
+
 	/**
 	 * Injects the given CSS styles into the DOM.
 	 */
@@ -1446,7 +1475,6 @@
 			var size = getComputedSlideSize();
 
 			var slidePadding = 20; // TODO Dig this out of DOM
-			var zTransform = z !== 0 ? 'translateZ(-'+ z +'px)' : '';
 
 			// Layout the contents of the slides
 			layoutSlideContents( config.width, config.height, slidePadding );
@@ -1468,13 +1496,13 @@
 				dom.slides.style.top = '';
 				dom.slides.style.bottom = '';
 				dom.slides.style.right = '';
-				transformElement( dom.slides, zTransform );
+				transformSlides( { layout: '' } );
 			}
 			else {
 				// Prefer zooming in desktop Chrome so that content remains crisp
 				if( !isMobileDevice && /chrome/i.test( navigator.userAgent ) && typeof dom.slides.style.zoom !== 'undefined' ) {
 					dom.slides.style.zoom = scale;
-					transformElement( dom.slides, zTransform );
+					transformSlides( { layout: '' } );
 				}
 				// Apply scale transform as a fallback
 				else {
@@ -1482,7 +1510,7 @@
 					dom.slides.style.top = '50%';
 					dom.slides.style.bottom = 'auto';
 					dom.slides.style.right = 'auto';
-					transformElement( dom.slides, 'translate(-50%, -50%) scale('+ scale +') ' + zTransform );
+					transformSlides( { layout: 'translate(-50%, -50%) scale('+ scale +')' } );
 				}
 			}
 
@@ -1624,98 +1652,122 @@
 	}
 
 	/**
-	 * Displays the overview of slides (quick nav) by
-	 * scaling down and arranging all slide elements.
-	 *
-	 * Experimental feature, might be dropped if perf
-	 * can't be improved.
+	 * Displays the overview of slides (quick nav) by scaling
+	 * down and arranging all slide elements.
 	 */
 	function activateOverview() {
 
 		// Only proceed if enabled in config
-		if( config.overview ) {
-
-			// Don't auto-slide while in overview mode
-			cancelAutoSlide();
-
-			var wasActive = dom.wrapper.classList.contains( 'overview' );
+		if( config.overview && !isOverview() ) {
 
-			// Set the depth of the presentation. This determinse how far we
-			// zoom out and varies based on display size. It gets applied at
-			// the layout step.
-			z = window.innerWidth < 400 ? 1000 : 2500;
+			overview = true;
 
 			dom.wrapper.classList.add( 'overview' );
 			dom.wrapper.classList.remove( 'overview-deactivating' );
 
+			if( features.overviewTransitions ) {
+				setTimeout( function() {
+					dom.wrapper.classList.add( 'overview-animated' );
+				}, 1 );
+			}
+
+			// Don't auto-slide while in overview mode
+			cancelAutoSlide();
+
 			// Move the backgrounds element into the slide container to
 			// that the same scaling is applied
 			dom.slides.appendChild( dom.background );
 
-			var horizontalSlides = dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ),
-				horizontalBackgrounds = dom.background.childNodes;
+			// Clicking on an overview slide navigates to it
+			toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) {
+				if( !slide.classList.contains( 'stack' ) ) {
+					slide.addEventListener( 'click', onOverviewSlideClicked, true );
+				}
+			} );
 
-			for( var i = 0, len1 = horizontalSlides.length; i < len1; i++ ) {
-				var hslide = horizontalSlides[i],
-					hbackground = horizontalBackgrounds[i],
-					hoffset = config.rtl ? -105 : 105;
+			updateSlidesVisibility();
+			layoutOverview();
+			updateOverview();
 
-				var htransform = 'translate(' + ( ( i - indexh ) * hoffset ) + '%, 0%)';
+			layout();
 
-				hslide.setAttribute( 'data-index-h', i );
+			// Notify observers of the overview showing
+			dispatchEvent( 'overviewshown', {
+				'indexh': indexh,
+				'indexv': indexv,
+				'currentSlide': currentSlide
+			} );
 
-				// Apply CSS transform
-				transformElement( hslide, htransform );
-				transformElement( hbackground, htransform );
+		}
 
-				if( hslide.classList.contains( 'stack' ) ) {
+	}
 
-					var verticalSlides = hslide.querySelectorAll( 'section' ),
-						verticalBackgrounds = hbackground.querySelectorAll( '.slide-background' );
+	/**
+	 * Uses CSS transforms to position all slides in a grid for
+	 * display inside of the overview mode.
+	 */
+	function layoutOverview() {
 
-					for( var j = 0, len2 = verticalSlides.length; j < len2; j++ ) {
-						var verticalIndex = i === indexh ? indexv : getPreviousVerticalIndex( hslide );
+		var margin = 70;
+		var slideWidth = config.width + margin,
+			slideHeight = config.height + margin;
 
-						var vslide = verticalSlides[j],
-							vbackground = verticalBackgrounds[j];
+		// Reverse in RTL mode
+		if( config.rtl ) {
+			slideWidth = -slideWidth;
+		}
 
-						var vtransform = 'translate(0%, ' + ( ( j - verticalIndex ) * 105 ) + '%)';
+		// Layout slides
+		toArray( dom.wrapper.querySelectorAll( HORIZONTAL_SLIDES_SELECTOR ) ).forEach( function( hslide, h ) {
+			hslide.setAttribute( 'data-index-h', h );
+			transformElement( hslide, 'translate3d(' + ( h * slideWidth ) + 'px, 0, 0)' );
 
-						vslide.setAttribute( 'data-index-h', i );
-						vslide.setAttribute( 'data-index-v', j );
+			if( hslide.classList.contains( 'stack' ) ) {
 
-						// Apply CSS transform
-						transformElement( vslide, vtransform );
-						transformElement( vbackground, vtransform );
+				toArray( hslide.querySelectorAll( 'section' ) ).forEach( function( vslide, v ) {
+					vslide.setAttribute( 'data-index-h', h );
+					vslide.setAttribute( 'data-index-v', v );
 
-						// Navigate to this slide on click
-						vslide.addEventListener( 'click', onOverviewSlideClicked, true );
-					}
+					transformElement( vslide, 'translate3d(0, ' + ( v * slideHeight ) + 'px, 0)' );
+				} );
 
-				}
-				else {
+			}
+		} );
 
-					// Navigate to this slide on click
-					hslide.addEventListener( 'click', onOverviewSlideClicked, true );
+		// Layout slide backgrounds
+		toArray( dom.background.childNodes ).forEach( function( hbackground, h ) {
+			transformElement( hbackground, 'translate3d(' + ( h * slideWidth ) + 'px, 0, 0)' );
 
-				}
-			}
+			toArray( hbackground.querySelectorAll( '.slide-background' ) ).forEach( function( vbackground, v ) {
+				transformElement( vbackground, 'translate3d(0, ' + ( v * slideHeight ) + 'px, 0)' );
+			} );
+		} );
 
-			updateSlidesVisibility();
+	}
 
-			layout();
+	/**
+	 * Moves the overview viewport to the current slides.
+	 * Called each time the current slide changes.
+	 */
+	function updateOverview() {
 
-			if( !wasActive ) {
-				// Notify observers of the overview showing
-				dispatchEvent( 'overviewshown', {
-					'indexh': indexh,
-					'indexv': indexv,
-					'currentSlide': currentSlide
-				} );
-			}
+		var margin = 70;
+		var slideWidth = config.width + margin,
+			slideHeight = config.height + margin;
 
+		// Reverse in RTL mode
+		if( config.rtl ) {
+			slideWidth = -slideWidth;
 		}
 
+		transformSlides( {
+			overview: [
+				'translateX('+ ( -indexh * slideWidth ) +'px)',
+				'translateY('+ ( -indexv * slideHeight ) +'px)',
+				'translateZ('+ ( window.innerWidth < 400 ? -1000 : -2500 ) +'px)'
+			].join( ' ' )
+		} );
+
 	}
 
 	/**
@@ -1727,10 +1779,10 @@
 		// Only proceed if enabled in config
 		if( config.overview ) {
 
-			dom.wrapper.classList.remove( 'overview' );
+			overview = false;
 
-			// Move the background element back out
-			dom.wrapper.appendChild( dom.background );
+			dom.wrapper.classList.remove( 'overview' );
+			dom.wrapper.classList.remove( 'overview-animated' );
 
 			// Temporarily add a class so that transitions can do different things
 			// depending on whether they are exiting/entering overview, or just
@@ -1741,6 +1793,9 @@
 				dom.wrapper.classList.remove( 'overview-deactivating' );
 			}, 1 );
 
+			// Move the background element back out
+			dom.wrapper.appendChild( dom.background );
+
 			// Clean up changes made to slides
 			toArray( dom.wrapper.querySelectorAll( SLIDES_SELECTOR ) ).forEach( function( slide ) {
 				transformElement( slide, '' );
@@ -1753,8 +1808,12 @@
 				transformElement( background, '' );
 			} );
 
+			transformSlides( { overview: '' } );
+
 			slide( indexh, indexv );
 
+			layout();
+
 			cueAutoSlide();
 
 			// Notify observers of the overview hiding
@@ -1793,7 +1852,7 @@
 	 */
 	function isOverview() {
 
-		return dom.wrapper.classList.contains( 'overview' );
+		return overview;
 
 	}
 
@@ -1943,7 +2002,7 @@
 
 		// If no vertical index is specified and the upcoming slide is a
 		// stack, resume at its previous vertical index
-		if( v === undefined ) {
+		if( v === undefined && !isOverview() ) {
 			v = getPreviousVerticalIndex( horizontalSlides[ h ] );
 		}
 
@@ -1993,9 +2052,9 @@
 			document.documentElement.classList.remove( stateBefore.pop() );
 		}
 
-		// If the overview is active, re-activate it to update positions
+		// Update the overview if it's currently active
 		if( isOverview() ) {
-			activateOverview();
+			updateOverview();
 		}
 
 		// Find the current horizontal slide and any possible vertical slides
@@ -2108,6 +2167,10 @@
 
 		formatEmbeddedContent();
 
+		if( isOverview() ) {
+			layoutOverview();
+		}
+
 	}
 
 	/**