Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using it's URL and the proper URL extention.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                		<script>
		document.documentElement.className = "js";
		var supportsCssVars = function() { var e, t = document.createElement("style"); return t.innerHTML = "root: { --tmp-var: bold; }", document.head.appendChild(t), e = !!(window.CSS && window.CSS.supports && window.CSS.supports("font-weight", "var(--tmp-var)")), t.parentNode.removeChild(t), e };
		supportsCssVars() || alert("Please view this demo in a modern browser that supports CSS Variables.");
		</script>	
<body class="loading">
		<svg class="hidden">
			<symbol id="icon-arrow" viewBox="0 0 24 24">
				<title>arrow</title>
				<polygon points="6.3,12.8 20.9,12.8 20.9,11.2 6.3,11.2 10.2,7.2 9,6 3.1,12 9,18 10.2,16.8 " />
			</symbol>
			<symbol id="icon-drop" viewBox="0 0 24 24">
				<title>drop</title>
				<path d="M12,21c-3.6,0-6.6-3-6.6-6.6C5.4,11,10.8,4,11.4,3.2C11.6,3.1,11.8,3,12,3s0.4,0.1,0.6,0.3c0.6,0.8,6.1,7.8,6.1,11.2C18.6,18.1,15.6,21,12,21zM12,4.8c-1.8,2.4-5.2,7.4-5.2,9.6c0,2.9,2.3,5.2,5.2,5.2s5.2-2.3,5.2-5.2C17.2,12.2,13.8,7.3,12,4.8z" />
				<path d="M12,18.2c-0.4,0-0.7-0.3-0.7-0.7s0.3-0.7,0.7-0.7c1.3,0,2.4-1.1,2.4-2.4c0-0.4,0.3-0.7,0.7-0.7c0.4,0,0.7,0.3,0.7,0.7C15.8,16.5,14.1,18.2,12,18.2z" />
			</symbol>
			<symbol id="icon-longarrow" viewBox="0 0 54 24">
				<title>longarrow</title>
				<path d="M.42 11.158L12.38.256c.333-.27.696-.322 1.09-.155.395.166.593.467.593.903v6.977h38.87c.29 0 .53.093.716.28.187.187.28.426.28.716v5.98c0 .29-.093.53-.28.716a.971.971 0 0 1-.716.28h-38.87v6.977c0 .416-.199.717-.592.903-.395.167-.759.104-1.09-.186L.42 12.62a1.018 1.018 0 0 1 0-1.462z" />
			</symbol>
			<symbol id="icon-navarrow" viewBox="0 0 408 408">
				<title>navarrow</title>
				<polygon fill="#fff" fill-rule="nonzero" points="204 0 168.3 35.7 311.1 178.5 0 178.5 0 229.5 311.1 229.5 168.3 372.3 204 408 408 204"></polygon>
			</symbol>
		</svg>
		<main>
			<div class="frame">
				<header class="codrops-header">
					<h1 class="codrops-header__title">Diagonal Slideshow</h1>
					<div class="codrops-links">
						<a class="github" href="https://github.com/codrops/DiagonalSlideshow/">GitHub</a>
						<a class="codrops-icon codrops-icon--prev" href="https://tympanus.net/Development/SlideOutBoxMenu/" title="Previous Demo">
							<svg class="icon icon--arrow">
								<use xlink:href="#icon-arrow"></use>
							</svg>
						</a>
						<a class="codrops-icon codrops-icon--drop" href="https://tympanus.net/codrops/?p=35765" title="Back to the article">
							<svg class="icon icon--drop">
								<use xlink:href="#icon-drop"></use>
							</svg>
						</a>
					</div>
				</header>
			</div>
			<div class="slideshow">
				<div class="slideshow__deco"></div>
				<div class="slide">
					<div class="slide__img-wrap">
						<div class="slide__img" style="background-image: url(https://tympanus.net/Development/DiagonalSlideshow/img/1.jpg);"></div>
					</div>
					<div class="slide__side">Memories &amp; Thoughts</div>
					<div class="slide__title-wrap">
						<span class="slide__number">1</span>
						<h3 class="slide__title">Automation</h3>
						<h4 class="slide__subtitle">A tree needs to be your friend if you're going to paint him</h4>
					</div>
				</div>
				<div class="slide">
					<div class="slide__img-wrap">
						<div class="slide__img" style="background-image: url(https://tympanus.net/Development/DiagonalSlideshow/img/2.jpg);"></div>
					</div>
					<div class="slide__side">Random Roam</div>
					<div class="slide__title-wrap">
						<span class="slide__number">2</span>
						<h3 class="slide__title">Machines</h3>
						<h4 class="slide__subtitle">This is probably the greatest thing to happen in my life</h4>
					</div>
				</div>
				<div class="slide">
					<div class="slide__img-wrap">
						<div class="slide__img" style="background-image: url(https://tympanus.net/Development/DiagonalSlideshow/img/3.jpg);"></div>
					</div>
					<div class="slide__side">Arbitrary Words</div>
					<div class="slide__title-wrap">
						<span class="slide__number">3</span>
						<h3 class="slide__title">Coexistence</h3>
						<h4 class="slide__subtitle">The only guide is your heart</h4>
					</div>
				</div>
				<div class="slide">
					<div class="slide__img-wrap">
						<div class="slide__img" style="background-image: url(https://tympanus.net/Development/DiagonalSlideshow/img/4.jpg);"></div>
					</div>
					<div class="slide__side">Haunted Drift</div>
					<div class="slide__title-wrap">
						<span class="slide__number">4</span>
						<h3 class="slide__title">Bellamio</h3>
						<h4 class="slide__subtitle">The only prerequisite is that it makes you happy</h4>
					</div>
				</div>
				<div class="slide">
					<div class="slide__img-wrap">
						<div class="slide__img" style="background-image: url(https://tympanus.net/Development/DiagonalSlideshow/img/5.jpg);"></div>
					</div>
					<div class="slide__side">Fun Diverge</div>
					<div class="slide__title-wrap">
						<span class="slide__number">5</span>
						<h3 class="slide__title">Pastures</h3>
						<h4 class="slide__subtitle">Let's go up in here, and start having some fun</h4>
					</div>
				</div>
				<div class="slide">
					<div class="slide__img-wrap">
						<div class="slide__img" style="background-image: url(https://tympanus.net/Development/DiagonalSlideshow/img/6.jpg);"></div>
					</div>
					<div class="slide__side">Hopes &amp; Dreams</div>
					<div class="slide__title-wrap">
						<span class="slide__number">6</span>
						<h3 class="slide__title">Focus</h3>
						<h4 class="slide__subtitle">This is unplanned it really just happens</h4>
					</div>
				</div>
				<button class="nav nav--prev">
					<svg class="icon icon--navarrow-prev">
						<use xlink:href="#icon-navarrow"></use>
					</svg>
				</button>
				<button class="nav nav--next">
					<svg class="icon icon--navarrow-next">
						<use xlink:href="#icon-navarrow"></use>
					</svg>
				</button>
			</div>
			<div class="content">
				<div class="content__item">
					<span class="content__number">1</span>
					<h3 class="content__title">Automation</h3>
					<h4 class="content__subtitle">A tree needs to be your friend if you're going to paint him</h4>
					<div class="content__text">Just let this happen. We just let this flow right out of our minds. Just relax and let it flow. That easy. Let's put some happy little clouds in our world. It's a very cold picture, I may have to go get my coat. It’s about to freeze me to death. This is gonna be a happy little seascape. Let's go up in here, and start having some fun The least little bit can do so much. Work on one thing at a time. Don't get carried away - we have plenty of time. Put your feelings into it, your heart, it's your world. These trees are so much fun. I get started on them and I have a hard time stopping.</div>
				</div>
				<div class="content__item">
					<span class="content__number">2</span>
					<h3 class="content__title">Machines</h3>
					<h4 class="content__subtitle">This is probably the greatest thing to happen in my life</h4>
					<div class="content__text">We're not trying to teach you a thing to copy. We're just here to teach you a technique, then let you loose into the world. Now, we're going to fluff this cloud. We don't have anything but happy trees here. Let's do that again. Use what you see, don't plan it. Let's go up in here, and start having some fun The least little bit can do so much. Work on one thing at a time. Don't get carried away - we have plenty of time. Put your feelings into it, your heart, it's your world. These trees are so much fun. I get started on them and I have a hard time stopping.</div>
				</div>
				<div class="content__item">
					<span class="content__number">3</span>
					<h3 class="content__title">Coexistence</h3>
					<h4 class="content__subtitle">The only guide is your heart</h4>
					<div class="content__text">Let's go up in here, and start having some fun The least little bit can do so much. Work on one thing at a time. Don't get carried away - we have plenty of time. Put your feelings into it, your heart, it's your world. These trees are so much fun. I get started on them and I have a hard time stopping. But we're not there yet, so we don't need to worry about it. Now let's put some happy little clouds in here. What the devil. A thin paint will stick to a thick paint. I'm going to mix up a little color. </div>
				</div>
				<div class="content__item">
					<span class="content__number">4</span>
					<h3 class="content__title">Bellamio</h3>
					<h4 class="content__subtitle">The only prerequisite is that it makes you happy</h4>
					<div class="content__text">See. We take the corner of the brush and let it play back-and-forth. This is unplanned it really just happens. I'm sort of a softy, I couldn't shoot Bambi except with a camera. I guess I'm a little weird. I like to talk to trees and animals. That's okay though; I have more fun than most people. We'll play with clouds today. Didn't you know you had that much power? You can move mountains. You can do anything. Let's go up in here, and start having some fun The least little bit can do so much. Work on one thing at a time. Don't get carried away - we have plenty of time. Put your feelings into it, your heart, it's your world. These trees are so much fun. I get started on them and I have a hard time stopping.</div>
				</div>
				<div class="content__item">
					<span class="content__number">5</span>
					<h3 class="content__title">Pastures</h3>
					<h4 class="content__subtitle">Let's go up in here, and start having some fun</h4>
					<div class="content__text">So often we avoid running water, and running water is a lot of fun. Everyone is going to see things differently - and that's the way it should be. A big strong tree needs big strong roots. Steve wants reflections, so let's give him reflections. We don't have to be committed. We are just playing here. Making all those little fluffies that live in the clouds. Let's go up in here, and start having some fun The least little bit can do so much. Work on one thing at a time. Don't get carried away - we have plenty of time. Put your feelings into it, your heart, it's your world. These trees are so much fun. I get started on them and I have a hard time stopping.</div>
				</div>
				<div class="content__item">
					<span class="content__number">6</span>
					<h3 class="content__title">Focus</h3>
					<h4 class="content__subtitle">This is unplanned it really just happens</h4>
					<div class="content__text">But we're not there yet, so we don't need to worry about it. Now let's put some happy little clouds in here. What the devil. A thin paint will stick to a thick paint. I'm going to mix up a little color. We’ll use Van Dyke Brown, Permanent Red, and a little bit of Prussian Blue. Let's go up in here, and start having some fun The least little bit can do so much. Work on one thing at a time. Don't get carried away - we have plenty of time. Put your feelings into it, your heart, it's your world. These trees are so much fun. I get started on them and I have a hard time stopping.</div>
				</div>
				<button class="content__close">
					<svg class="icon icon--longarrow">
						<use xlink:href="#icon-longarrow"></use>
					</svg>
				</button>
			</div>
		
		</main>
              
            
!

CSS

              
                article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}audio,canvas,video{display:inline-block;}audio:not([controls]){display:none;height:0;}[hidden]{display:none;}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}body{margin:0;}a:focus{outline:thin dotted;}a:active,a:hover{outline:0;}h1{font-size:2em;margin:0.67em 0;}abbr[title]{border-bottom:1px dotted;}b,strong{font-weight:bold;}dfn{font-style:italic;}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}mark{background:#ff0;color:#000;}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em;}pre{white-space:pre-wrap;}q{quotes:"\201C" "\201D" "\2018" "\2019";}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sup{top:-0.5em;}sub{bottom:-0.25em;}img{border:0;}svg:not(:root){overflow:hidden;}figure{margin:0;}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}legend{border:0;padding:0;}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}button,input{line-height:normal;}button,select{text-transform:none;}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}button[disabled],html input[disabled]{cursor:default;}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}textarea{overflow:auto;vertical-align:top;}table{border-collapse:collapse;border-spacing:0;}
*,
*::after,
*::before {
	box-sizing: border-box;
}

body {
	--color-text: #f1f1f1;
    --color-bg: #0c0c0c;
    --color-link: #1ab3de;
    --color-link-hover: #f1f1f1;
	--color-deco: #141414;
	--color-side: #353535;
	font-family: Futura, "futura-pt", sans-serif;
	min-height: 100vh;
	color: #57585c;
	color: var(--color-text);
	background-color: var(--color-bg);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	padding-top: 10rem;
}

/* Page Loader */
.js .loading::before {
	content: '';
	position: fixed;
	z-index: 100000;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: var(--color-bg);
}

.js .loading::after {
	content: '';
	position: fixed;
	z-index: 100000;
	top: 50%;
	left: 50%;
	width: 60px;
	height: 60px;
	margin: -30px 0 0 -30px;
	pointer-events: none;
	border-radius: 50%;
	opacity: 0.4;
	background: var(--color-link);
	animation: loaderAnim 0.7s linear infinite alternate forwards;
}

@keyframes loaderAnim {
	to {
		opacity: 1;
		transform: scale3d(0.5,0.5,1);
	}
}

a {
	text-decoration: none;
	color: var(--color-link);
	outline: none;
}

a:hover,
a:focus {
	color: var(--color-link-hover);
	outline: none;
}

.hidden {
	position: absolute;
	overflow: hidden;
	width: 0;
	height: 0;
	pointer-events: none;
}

.message {
	position: relative;
	z-index: 100;
	display: none;
	padding: 1em;
	text-align: center;
	color: var(--color-bg);
	background: var(--color-text);
}

/* Icons */
.icon {
	display: block;
	width: 1.5em;
	height: 1.5em;
	margin: 0 auto;
	fill: currentColor;
}

.frame {
	position: fixed;
	z-index: 10000;
	top: 5rem;
	left: 0;
	width: 100%;
	max-width: none;
	min-height: 0;
	height: 100vh;
	padding: 1rem;
	pointer-events: none;
}

.frame a {
	pointer-events: auto;
}	

/* Header */
.codrops-header {
	position: relative;
	z-index: 100;
	display: flex;
	align-items: center;
	justify-content: space-between;
}

.codrops-header__title {
	font-size: 1rem;
	font-weight: normal;
	line-height: 1;
	margin: 0;
}

/* Top Navigation Style */
.codrops-links {
	position: relative;
	display: flex;
	justify-content: flex-end;
	align-items: center;
	white-space: nowrap;
}

.github {
	display: block;
	padding: 0.25em;
	margin: 0 0.25rem;
}

.codrops-icon {
	display: inline-block;
	padding: 0.25em;
	margin: 0.25em 0 0 0;
}

.slideshow {
	position: relative;
	overflow: hidden;
	margin: 0;
	height: 100vh;
	width: 100%;
	height: calc(100vh - 10rem);
	display: grid;
	grid-template-columns: 33% 33% 33%;
	grid-column-gap: 0.5%;
	grid-template-rows: 100%;
	grid-template-areas: '... slide ...';
}

.slide {
	width: 100%;
	display: flex;
	pointer-events: none;
	cursor: pointer;
	position: relative;
	height: 100%;
	grid-area: slide;
}

.slideshow--previewopen .slide {
	cursor: default;
}

.slide--current {
	pointer-events: auto;
}

.slide__img-wrap {
	width: 100%;
	overflow: hidden;
	z-index: 100;
	height: 80%;
	top: 10%;
	position: absolute;
}

.slideshow__deco {
	grid-area: slide;
	background: var(--color-deco);
	width: 100%;
	height: 80%;
	align-self: center;
	position: relative;
	margin: -40px 0 0 0;
	right: -20px;
}

.nav {
	position: absolute;
	background: none;
	width: 3rem;
	height: 3rem;
	z-index: 1000;
	border: 0;
	padding: 0;
	margin: 0;
	pointer-events: none;
	transition: transform 0.8s, opacity 0.8s;
	transition-timing-function: cubic-bezier(0.7,0,0.3,1);
}

.nav--next {
	bottom: 1rem;
	right: 1rem;
}

.icon--navarrow-next {
	transform: rotate(45deg);
}

.nav--prev {
	top: 1rem;
	left: 1rem;
}

.icon--navarrow-prev {
	transform: rotate(-135deg);
}

.slideshow--previewopen .nav {
	opacity: 0;
	transition-duration: 0.4s;
}

.slideshow--previewopen .nav--next {
	transform: translate3d(100%, 100%, 0);
}

.slideshow--previewopen .nav--prev {
	transform: translate3d(-100%, -100%, 0);
}

.slide__img {
	width: 100%;
	height: 100%;
	left: 0;
	top: 0;
	background-size: cover;
	background-position: 50% 50%;
	position: absolute;
	pointer-events: none;
	transform: scale3d(1.01,1.01,1);
}

.js .slide__img-wrap, 
.js .slide__title-wrap,
.js .slide__side {
	opacity: 0;
	pointer-events: none;
}

.js .slide--current .slide__img-wrap {
	opacity: 1;
	pointer-events: auto;
}

.slide--visible .slide__img-wrap {
	pointer-events: auto;
}

.slide__title-wrap {
	justify-self: flex-end;
	width: 100%;
	position: relative;
	z-index: 1000;
}

.slide__number {
	display: block;
	font-size: 2rem;
	font-weight: bold;
}

.slide__number::before {
	content: "\2014";
	display: inline-block;
	margin: 0 1rem 0 0;
}

.slide__title,
.slide__subtitle,
.slide__side {
	display: none;
}

.content {
	position: fixed;
	top: 10rem;
	left: 0;
	width: 100%;
	height: calc(100% - 10rem);
	pointer-events: none;
	z-index: 100;
}

.content__item {
	position: absolute;
	top: 0;
	right: 0;
	width: 100%;
	height: 100%;
	padding: 10vh 5vw;
	overflow: auto;
}

.content__item--current,
.content__item--current ~ .content__close {
	pointer-events: auto;
}

.content__close {
	position: absolute;
	top: 1rem;
	left: 1rem;
	background: none;
	color: currentColor;
	border: 0;
	margin: 0;
	padding: 0;
}

.icon--longarrow {
	width: 2rem;
}

.content__close:focus {
	outline: none;
}

.content__number {
	font-weight: bold;
}

.content__number::before {
	content: "\2014";
	display: inline-block;
	margin: 0 1rem 0 0;
}

.content__title {
	margin: 0.5rem 0;
	font-size: 2rem;
}

.content__subtitle {
	margin: 0 0 0.5rem;
	font-size: 1rem;
	font-weight: normal;
}

.content__text {
	font-size: 0.85rem;
}

.js .content__title,
.js .content__subtitle,
.js .content__number,
.js .content__text,
.js .content__close {
	opacity: 0;
}

@media screen and (min-width: 53em) {
	body {
		padding: 0;
	}
	.frame {
		top: 0;
		display: grid;
		align-items: start;
		justify-items: end;
		grid-template-columns: 50% 50%;
		grid-template-rows: 100%;
		grid-template-areas: '... header';
	}
	.codrops-header {
		grid-area: header;
		padding: 1rem 0.5rem;
		display: block;
	}
	.codrops-header__title {
		padding: 0 0.5rem;
	}
	.codrops-links {
		margin: 0.25rem auto 0 0.25rem;
	}
	.slideshow {
		height: 100vh;
		grid-template-columns: 27% 27% 27%;
		grid-column-gap: 9.5%;
	}
	.slide {
		padding: 10vh 0 7vh;
		flex-direction: column;
		justify-content: space-between;
	}
	.slide__side {
		margin: 0 0 0 -1.85rem;
	}
	.slide__title-wrap {
		margin: 0 0 0 -1.85rem;
	}
	.slide__title,
	.slide__subtitle,
	.slide__side {
		display: block;
	}
	.slide__title {
		font-size: 3.25rem;
		margin: 0 0 0.25rem;
	}
	.slide__subtitle {
		font-weight: normal;
		margin: 0;
		min-height: 50px;
	}
	.slide__side {
		color: var(--color-side);
		position: relative;
		-webkit-writing-mode: vertical-rl;
		writing-mode: vertical-rl;
		transform: rotate(180deg);
		z-index: 1000;
	}
	.content {
		top: 0;
		height: 100%;
	}
	.content__item {
		padding: calc(10vh + 5rem) 0 7vh;
		width: 50.5%;
		right: 7.5%;
		overflow: visible;
	}
	.content__close {
		left: 42%;
		top: calc(10vh + 1rem);
	}
	.content__number {
		position: absolute;
		bottom: 7vh;
		right: 0;
		font-size: 2rem;
	}
	.content__title {
		font-size: 7vw;
	}
	.content__subtitle {
		font-size: 1.15rem;
		margin-bottom: 7.5vh;
	}
	.content__text {
		font-size: 0.95rem;
		column-count: 2;
		column-gap: 2rem;
		max-width: 600px;
		text-align: justify;
	}
}
              
            
!

JS

              
                /**
 * demo.js
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * Copyright 2018, Codrops
 * http://www.codrops.com
 */
{
    // From http://www.quirksmode.org/js/events_properties.html#position
    // Get the mouse position.
	const getMousePos = (e) => {
        let posx = 0;
        let posy = 0;
		if (!e) e = window.event;
		if (e.pageX || e.pageY) 	{
			posx = e.pageX;
			posy = e.pageY;
		}
		else if (e.clientX || e.clientY) 	{
			posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
			posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
		}
		return { x : posx, y : posy }
    };
    // Gets a random integer.
    const getRandomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
    // Equation of a line (y = mx + b ).
    const lineEq = (y2, y1, x2, x1, currentVal) => {
        const m = (y2 - y1) / (x2 - x1);
        const b = y1 - m * x1;
        return m * currentVal + b;
    };

    // Some random chars.
    const chars = ['$','%','#','&','=','*','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','.',':',',','^'];
    const charsTotal = chars.length;
    
    // Randomize letters function. Used when navigating the slideshow to switch the curretn slide´s texts.
    const randomizeLetters = (letters) => {
        return new Promise((resolve, reject) => {
            const lettersTotal = letters.length;
            let cnt = 0;

            letters.forEach((letter, pos) => { 
                let loopTimeout;
                const loop = () => {
                    letter.innerHTML = chars[getRandomInt(0,charsTotal-1)];
                    loopTimeout = setTimeout(loop, getRandomInt(50,500));
                };
                loop();

                const timeout = setTimeout(() => {
                    clearTimeout(loopTimeout);
                    letter.style.opacity = 1;
                    letter.innerHTML = letter.dataset.initial;
                    ++cnt;
                    if ( cnt === lettersTotal ) {
                        resolve();
                    }
                }, pos*lineEq(40,0,8,200,lettersTotal));
            });
        });
    };

    // Hide each of the letters with random delays. Used when showing the current slide´s content.
    const disassembleLetters = (letters) => {
        return new Promise((resolve, reject) => {
            const lettersTotal = letters.length;
            let cnt = 0;
            
            letters.forEach((letter, pos) => {
                setTimeout(() => {
                    letter.style.opacity = 0;
                    ++cnt;
                    if ( cnt === lettersTotal ) {
                        resolve();
                    }
                }, pos*30);
            });
        });
    }
    
    // The Slide class.
    class Slide {
        constructor(el) {
            this.DOM = {el: el};
            // The image wrap element.
            this.DOM.imgWrap = this.DOM.el.querySelector('.slide__img-wrap');
            // The image element.
            this.DOM.img = this.DOM.imgWrap.querySelector('.slide__img');
            // The texts: the parent wrap, title, number and side text.
            this.DOM.texts = {
                wrap: this.DOM.el.querySelector('.slide__title-wrap'),
                title: this.DOM.el.querySelector('.slide__title'),
                number: this.DOM.el.querySelector('.slide__number'),
                side: this.DOM.el.querySelector('.slide__side'),
            };
            // Split the title and side texts into spans, one per letter. Sort these so we can later animate then with the 
            // randomizeLetters or disassembleLetters functions when navigating and showing the content.
            charming(this.DOM.texts.title);
            charming(this.DOM.texts.side);
            this.DOM.titleLetters = Array.from(this.DOM.texts.title.querySelectorAll('span')).sort(() => 0.5 - Math.random());
            this.DOM.sideLetters = Array.from(this.DOM.texts.side.querySelectorAll('span')).sort(() => 0.5 - Math.random());
            this.DOM.titleLetters.forEach(letter => letter.dataset.initial = letter.innerHTML);
            this.DOM.sideLetters.forEach(letter => letter.dataset.initial = letter.innerHTML);
            // Calculate the sizes of the image wrap. 
            this.calcSizes();
            // And also the transforms needed per position. 
            // We have 5 different possible positions for a slide: center, bottom right, top left and outside the viewport (top left or bottom right).
            this.calcTransforms();
            // Init/Bind events.
            this.initEvents();
        }
        // Gets the size of the image wrap.
        calcSizes() {
            this.width = this.DOM.imgWrap.offsetWidth;
            this.height = this.DOM.imgWrap.offsetHeight;
        }
        // Gets the transforms per slide position.
        calcTransforms() {
            /*
            Each position corresponds to the position of a given slide:
            0: left top corner outside the viewport
            1: left top corner (prev slide position)
            2: center (current slide position)
            3: right bottom corner (next slide position)
            4: right bottom corner outside the viewport
            5: left side, for when the content is shown
            */
            this.transforms = [
                {x: -1*(winsize.width/2+this.width), y: -1*(winsize.height/2+this.height), rotation: -30},
                {x: -1*(winsize.width/2-this.width/3), y: -1*(winsize.height/2-this.height/3), rotation: 0},
                {x: 0, y: 0, rotation: 0},
                {x: winsize.width/2-this.width/3, y: winsize.height/2-this.height/3, rotation: 0},
                {x: winsize.width/2+this.width, y: winsize.height/2+this.height, rotation: 30},
                {x: -1*(winsize.width/2 - this.width/2 - winsize.width*0.075), y: 0, rotation: 0}
            ];
        }
        // Init events:
        // Mouseevents for mousemove/tilt/scale on the current image, and window resize.
        initEvents() {
            this.mouseenterFn = () => {
                if ( !this.isPositionedCenter() || !allowTilt ) return;
                clearTimeout(this.mousetime);
                this.mousetime = setTimeout(() => {
                    // Scale the image.
                    TweenMax.to(this.DOM.img, 0.8, {
                        ease: Power3.easeOut,
                        scale: 1.1
                    });
                }, 40);
            };
            this.mousemoveFn = ev => requestAnimationFrame(() => {
                // Tilt the current slide.
                if ( !allowTilt || !this.isPositionedCenter() ) return;
                this.tilt(ev);
            });
            this.mouseleaveFn = (ev) => requestAnimationFrame(() => {
                if ( !allowTilt || !this.isPositionedCenter() ) return;
                clearTimeout(this.mousetime);

                // Reset tilt and image scale.
                TweenMax.to([this.DOM.imgWrap,this.DOM.texts.wrap], 1.8, {
                    ease: 'Power4.easeOut',
                    x: 0,
                    y: 0,
                    rotationX: 0,
                    rotationY: 0
                });
                TweenMax.to(this.DOM.img, 1.8, {
                    ease: 'Power4.easeOut',
                    scale: 1
                });
            });
            // When resizing the window recalculate size and transforms, since both will depend on the window size.
            this.resizeFn = () => {
                this.calcSizes();
                this.calcTransforms();
            };
            this.DOM.imgWrap.addEventListener('mouseenter', this.mouseenterFn);
            this.DOM.imgWrap.addEventListener('mousemove', this.mousemoveFn);
            this.DOM.imgWrap.addEventListener('mouseleave', this.mouseleaveFn);
            window.addEventListener('resize', this.resizeFn);
        }
        // Tilt the image wrap and texts when mouse moving the current slide.
        tilt(ev) {
            const mousepos = getMousePos(ev);
            // Document scrolls.
            const docScrolls = {
                left : document.body.scrollLeft + document.documentElement.scrollLeft, 
                top : document.body.scrollTop + document.documentElement.scrollTop
            };
            const bounds = this.DOM.imgWrap.getBoundingClientRect();;
            // Mouse position relative to the main element (this.DOM.el).
            const relmousepos = { 
                x : mousepos.x - bounds.left - docScrolls.left, 
                y : mousepos.y - bounds.top - docScrolls.top 
            };
            
            // Move the element from -20 to 20 pixels in both x and y axis.
            // Rotate the element from -15 to 15 degrees in both x and y axis.
            let t = {x:[-20,20],y:[-20,20]},
                r = {x:[-15,15],y:[-15,15]};

            const transforms = {
                translation : {
                    x: (t.x[1]-t.x[0])/bounds.width*relmousepos.x + t.x[0],
                    y: (t.y[1]-t.y[0])/bounds.height*relmousepos.y + t.y[0]
                },
                rotation : {
                    x: (r.x[1]-r.x[0])/bounds.height*relmousepos.y + r.x[0],
                    y: (r.y[1]-r.y[0])/bounds.width*relmousepos.x + r.y[0]
                }
            };

            // Move the image wrap.
            TweenMax.to(this.DOM.imgWrap, 1.5, {
                ease: 'Power1.easeOut',
                x: transforms.translation.x,
                y: transforms.translation.y,
                rotationX: transforms.rotation.x,
                rotationY: transforms.rotation.y
            }); 

            // Move the texts wrap.
            TweenMax.to(this.DOM.texts.wrap, 1.5, {
                ease: 'Power1.easeOut',
                x: -1*transforms.translation.x,
                y: -1*transforms.translation.y
            }); 
        }
        // Positions one slide (left, right or current) in the viewport.
        position(pos) {
            TweenMax.set(this.DOM.imgWrap, {
                x: this.transforms[pos].x, 
                y: this.transforms[pos].y, 
                rotationX: 0,
                rotationY: 0,
                opacity: 1,
                rotationZ: this.transforms[pos].rotation
            });
        }
        // Sets it as current.
        setCurrent(isContentOpen) {
            this.isCurrent = true;
            this.DOM.el.classList.add('slide--current', 'slide--visible');
            // Position it on the current´s position.
            this.position(isContentOpen ? 5 : 2);
        }
        // Position the slide on the left side.
        setLeft(isContentOpen) {
            this.isRight = this.isCurrent = false;
            this.isLeft = true;
            this.DOM.el.classList.add('slide--visible');
            // Position it on the left position.
            this.position(isContentOpen ? 0 : 1);
        }
        // Position the slide on the right side.
        setRight(isContentOpen) {
            this.isLeft = this.isCurrent = false;
            this.isRight = true;
            this.DOM.el.classList.add('slide--visible');
            // Position it on the right position.
            this.position(isContentOpen ? 4 : 3);
        }
        // Check if the slide is positioned on the right side (if it´s the next slide in the slideshow).
        isPositionedRight() {
            return this.isRight;
        }
        // Check if the slide is positioned on the left side (if it´s the previous slide in the slideshow).
        isPositionedLeft() {
            return this.isLeft;
        }
        // Check if the slide is the current one.
        isPositionedCenter() {
            return this.isCurrent;
        }
        // Reset classes and state.
        reset() {
            this.isRight = this.isLeft = this.isCurrent = false;
            this.DOM.el.classList = 'slide';
        }
        hide() {
            TweenMax.set(this.DOM.imgWrap, {x:0, y:0, rotationX:0, rotationY:0, rotationZ:0, opacity:0});
        }
        // Moves a slide to a specific position defined in settings.position.
        // Also, moves it from position settings.from and if we need to reset the image scale when moving the slide then settings.resetImageScale should be true.
        moveToPosition(settings) {
            return new Promise((resolve, reject) => {
                /*
                Moves the slide to a specific position:
                -2: left top corner outside the viewport
                -1: left top corner (prev slide position)
                0: center (current slide position)
                1: right bottom corner (next slide position)
                2: right bottom corner outside the viewport
                3: left side, for when the content is shown
                */
                TweenMax.to(this.DOM.imgWrap, .8, {
                    ease: Power4.easeInOut,
                    delay: settings.delay || 0,
                    startAt: settings.from !== undefined ? {
                        x: this.transforms[settings.from+2].x,
                        y: this.transforms[settings.from+2].y,
                        rotationX: 0,
                        rotationY: 0,
                        rotationZ: this.transforms[settings.from+2].rotation
                    } : {},
                    x: this.transforms[settings.position+2].x,
                    y: this.transforms[settings.position+2].y,
                    rotationX: 0,
                    rotationY: 0,
                    rotationZ: this.transforms[settings.position+2].rotation,
                    onStart: settings.from !== undefined ? () => TweenMax.set(this.DOM.imgWrap, {opacity: 1}) : null,
                    onComplete: resolve
                });
                
                // Reset image scale when showing the content of the current slide.
                if ( settings.resetImageScale ) {
                    TweenMax.to(this.DOM.img, .8, {
                        ease: Power4.easeInOut,
                        scale: 1
                    });
                }
            });
        }
        // Hides the current slide´s texts.
        hideTexts(animation = false) {
            if ( animation ) {
                disassembleLetters(this.DOM.titleLetters).then(() => TweenMax.set(this.DOM.texts.wrap, {opacity: 0}));
                disassembleLetters(this.DOM.sideLetters).then(() => TweenMax.set(this.DOM.texts.side, {opacity: 0}));
            }
            else {
                TweenMax.set(this.DOM.texts.wrap, {opacity: 0});
                TweenMax.set(this.DOM.texts.side, {opacity: 0});
            }
        }
        // Shows the current slide´s texts.
        showTexts(animation = true) {
            TweenMax.set(this.DOM.texts.wrap, {opacity: 1});
            TweenMax.set(this.DOM.texts.side, {opacity: 1});

            if ( animation ) { 
                randomizeLetters(this.DOM.titleLetters);
                randomizeLetters(this.DOM.sideLetters);
                TweenMax.to(this.DOM.texts.number, 0.6, {
                    ease: Elastic.easeOut.config(1,0.5),
                    startAt: {x: '-10%', opacity: 0},
                    x: '0%',
                    opacity: 1 
                });
            }
        }
    }

    // The Content class. Represents one content item per slide.
    class Content {
        constructor(el) {
            this.DOM = {el: el};
            this.DOM.number = this.DOM.el.querySelector('.content__number');
            this.DOM.title = this.DOM.el.querySelector('.content__title');
            this.DOM.subtitle = this.DOM.el.querySelector('.content__subtitle');
            this.DOM.text = this.DOM.el.querySelector('.content__text');
            this.DOM.backCtrl = this.DOM.el.parentNode.querySelector('.content__close');
            this.DOM.backCtrl.addEventListener('click', () => slideshow.hideContent());
        }
        show() {
            this.DOM.el.classList.add('content__item--current');

            TweenMax.staggerTo([this.DOM.backCtrl,this.DOM.number,this.DOM.title,this.DOM.subtitle,this.DOM.text], 0.8, {
                ease: Power4.easeOut,
                delay: 0.4,
                opacity: 1,
                startAt: {y: 40},
                y: 0
            }, 0.05);
        }
        hide() {
            this.DOM.el.classList.remove('content__item--current');

            TweenMax.staggerTo([this.DOM.backCtrl,this.DOM.number,this.DOM.title,this.DOM.subtitle,this.DOM.text].reverse(), 0.3, {
                ease: Power3.easeIn,
                opacity: 0,
                y: 10
            }, 0.01);
        }
    }

    // The Slideshow class.
    class Slideshow {
        constructor(el) {
            this.DOM = {el: el};
            // The slides.
            this.slides = [];
            Array.from(this.DOM.el.querySelectorAll('.slide')).forEach(slideEl => this.slides.push(new Slide(slideEl)));
            // The total number of slides.
            this.slidesTotal = this.slides.length;
            // At least 4 slides to continue...
            if ( this.slidesTotal < 4 ) {
                return false;
            }
            // Current slide position.
            this.current = 0;
            this.DOM.deco = this.DOM.el.querySelector('.slideshow__deco');

            this.contents = [];
            Array.from(document.querySelectorAll('.content > .content__item')).forEach(contentEl => this.contents.push(new Content(contentEl)));

            // Set the current/next/previous slides. 
            this.render();
            this.currentSlide.showTexts(false);
            // Init/Bind events.
            this.initEvents();
        }
        render() {
            // The current, next, and previous slides.
            this.currentSlide = this.slides[this.current];
            this.nextSlide = this.slides[this.current+1 <= this.slidesTotal-1 ? this.current+1 : 0];
            this.prevSlide = this.slides[this.current-1 >= 0 ? this.current-1 : this.slidesTotal-1];
            this.currentSlide.setCurrent();
            this.nextSlide.setRight();
            this.prevSlide.setLeft();
        }
        initEvents() {
            // Clicking the next and previous slide starts the navigation / clicking the current shows its content..
            this.clickFn = (slide) => {
                if ( slide.isPositionedRight() ) {
                    this.navigate('next');
                }
                else if ( slide.isPositionedLeft() ) {
                    this.navigate('prev');
                }
                else {
                    this.showContent();
                }
            };
            for (let slide of this.slides) {
                slide.DOM.imgWrap.addEventListener('click', () => this.clickFn(slide));
            }

            this.resizeFn = () => {
                // Reposition the slides.
                this.nextSlide.setRight(this.isContentOpen);
                this.prevSlide.setLeft(this.isContentOpen);
                this.currentSlide.setCurrent(this.isContentOpen);

                if ( this.isContentOpen ) {
                    TweenMax.set(this.DOM.deco, {
                        scaleX: winsize.width/this.DOM.deco.offsetWidth,
                        scaleY: winsize.height/this.DOM.deco.offsetHeight,
                        x: -20,
                        y: 20
                    });
                }
            };
            window.addEventListener('resize', this.resizeFn);
        }
        showContent() {
            if ( this.isContentOpen || this.isAnimating ) return;
            allowTilt = false;
            this.isContentOpen = true;
            this.DOM.el.classList.add('slideshow--previewopen');
            TweenMax.to(this.DOM.deco, .8, {
                ease: Power4.easeInOut,
                scaleX: winsize.width/this.DOM.deco.offsetWidth,
                scaleY: winsize.height/this.DOM.deco.offsetHeight,
                x: -20,
                y: 20
            });
            // Move away right/left slides.
            this.prevSlide.moveToPosition({position: -2});
            this.nextSlide.moveToPosition({position: 2});
            // Position the current slide and reset its image scale value.
            this.currentSlide.moveToPosition({position: 3, resetImageScale: true});
            // Show content and back arrow (to close the content).
            this.contents[this.current].show();
            // Hide texts.
            this.currentSlide.hideTexts(true);
        }
        hideContent() {
            if ( !this.isContentOpen || this.isAnimating ) return;

            this.DOM.el.classList.remove('slideshow--previewopen');

            // Hide content.
            this.contents[this.current].hide();

            TweenMax.to(this.DOM.deco, .8, {
                ease: Power4.easeInOut,
                scaleX: 1,
                scaleY: 1,
                x: 0,
                y: 0
            });
            // Move in right/left slides.
            this.prevSlide.moveToPosition({position: -1});
            this.nextSlide.moveToPosition({position: 1});
            // Position the current slide.
            this.currentSlide.moveToPosition({position: 0}).then(() => {
                allowTilt = true;
                this.isContentOpen = false;
            });
            // Show texts.
            this.currentSlide.showTexts();
        }
        // Animates the element behind the current slide.
        bounceDeco(direction, delay) {
            TweenMax.to(this.DOM.deco, .4, {
                ease: 'Power2.easeIn',
                delay: delay+delay*0.2,
                x: direction === 'next' ? -40 : 40,
                y: direction === 'next' ? -40 : 40,
                onComplete: () => {
                    TweenMax.to(this.DOM.deco, 0.6, {
                        //ease: Elastic.easeOut.config(1, 0.65),
                        ease: 'Power2.easeOut',
                        x: 0,
                        y: 0
                    });
                }
            });
        }
        // Navigate the slideshow.
        navigate(direction) {
            // If animating return.
            if ( this.isAnimating ) return;
            this.isAnimating = true;
            allowTilt = false;

            const upcomingPos = direction === 'next' ? 
                    this.current < this.slidesTotal-2 ? this.current+2 : Math.abs(this.slidesTotal-2-this.current):
                    this.current >= 2 ? this.current-2 : Math.abs(this.slidesTotal-2+this.current);
            
            this.upcomingSlide = this.slides[upcomingPos];

            // Update current.
            this.current = direction === 'next' ? 
                    this.current < this.slidesTotal-1 ? this.current+1 : 0 :
                    this.current > 0 ? this.current-1 : this.slidesTotal-1;
            
            // Move slides (the previous, current, next and upcoming slide).
            this.prevSlide.moveToPosition({position: direction === 'next' ? -2 : 0, delay: direction === 'next' ? 0 : 0.14}).then(() => {
                if ( direction === 'next' ) {
                    this.prevSlide.hide();
                }
            });
            
            this.currentSlide.moveToPosition({position: direction === 'next' ? -1 : 1, delay: 0.07 });
            this.currentSlide.hideTexts();
            
            this.bounceDeco(direction, 0.07);
            
            this.nextSlide.moveToPosition({position: direction === 'next' ? 0 : 2, delay: direction === 'next' ? 0.14 : 0 }).then(() => {
                if ( direction === 'prev' ) {
                    this.nextSlide.hide();
                }
            });

            if ( direction === 'next' ) {
                this.nextSlide.showTexts();
            }
            else {
                this.prevSlide.showTexts();
            }
            
            this.upcomingSlide.moveToPosition({position: direction === 'next' ? 1 : -1, from: direction === 'next' ? 2 : -2, delay: 0.21 }).then(() => {
                // Reset classes.
                [this.nextSlide,this.currentSlide,this.prevSlide].forEach(slide => slide.reset());
                this.render();
                allowTilt = true;
                this.isAnimating = false;
            });
        }
    }

    // Window sizes.
    let winsize;
    const calcWinsize = () => winsize = {width: window.innerWidth, height: window.innerHeight};
    calcWinsize();
    window.addEventListener('resize', calcWinsize);

    let allowTilt = true;

    // Init slideshow.
    const slideshow = new Slideshow(document.querySelector('.slideshow'));
    
    // Preload all the images in the page..
    const loader = document.querySelector('.loader');
    imagesLoaded(document.querySelectorAll('.slide__img'), {background: true}, () => document.body.classList.remove('loading'));
}
              
            
!
999px

Console