JSFiddle - React, Tailwind, and code Playground
by Christian Sonne
HTML
<div class="parallax">
<div id="group1" class="parallax__group">
<div class="parallax__layer parallax__layer--base">
<div class="title">Base Layer</div>
</div>
</div>
<div id="group2" class="parallax__group">
<div class="parallax__layer parallax__layer--base">
<div class="title">Base Layer</div>
</div>
<div class="parallax__layer range parallax__layer--back">
<div class="title">Background Layer</div>
</div>
</div>
<div id="group3" class="parallax__group">
<div class="parallax__layer parallax__layer--fore">
<div class="title">Foreground Layer</div>
</div>
<div class="parallax__layer parallax__layer--base">
<div class="title">Base Layer</div>
</div>
</div>
<div id="group4" class="parallax__group">
<div class="parallax__layer parallax__layer--base">
<div class="title">Base Layer</div>
</div>
<div class="parallax__layer parallax__layer--back">
<div class="title">Background Layer</div>
</div>
<div class="parallax__layer parallax__layer--deep">
<div class="title">Deep Background Layer</div>
</div>
</div>
<div id="group5" class="parallax__group">
<div class="parallax__layer parallax__layer--fore">
<div class="title">Foreground Layer</div>
</div>
<div class="parallax__layer parallax__layer--base">
<div class="title">Base Layer</div>
</div>
</div>
<div id="group6" class="parallax__group">
<div class="parallax__layer parallax__layer--back">
<div class="title">Background Layer</div>
</div>
<div class="parallax__layer parallax__layer--base">
<div class="title">Base Layer</div>
</div>
</div>
<div id="group7" class="parallax__group">
<div class="parallax__layer parallax__layer--base">
<div class="title">Base Layer</div>
</div>
</div>
</div>
CSS
html,
body {
margin: 0;
padding: 0;
}
body {
}
.range {
height: 100vh;
position: absolute;
left: 0;
right: 0;
background: linear-gradient(to top, white, black);
}
/* Parallax base styles
--------------------------------------------- */
.parallax {
height: 500px; /* fallback for older browsers */
height: 100vh;
overflow-x: hidden;
overflow-y: auto;
-webkit-perspective: 300px;
perspective: 300px;
-webkit-perspective-origin-x: 100%;
perspective-origin-x: 100%;
}
.parallax__group {
position: relative;
height: 500px; /* fallback for older browsers */
height: 100vh;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.parallax__layer {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
-webkit-transform-origin-x: 100%;
transform-origin-x: 100%;
}
.parallax__layer--fore {
-webkit-transform: translateZ(90px) scale(.7);
transform: translateZ(90px) scale(.7);
z-index: 1;
}
.parallax__layer--base {
-webkit-transform: translateZ(0);
transform: translateZ(0);
z-index: 4;
}
.parallax__layer--back {
-webkit-transform: translateZ(-900px) scale(2);
transform: translateZ(-3600px) scale(24);
z-index: 3;
}
.parallax__layer--deep {
-webkit-transform: translateZ(-600px) scale(3);
transform: translateZ(-600px) scale(3);
z-index: 2;
}
/* demo styles
--------------------------------------------- */
body, html {
overflow: hidden;
}
body {
font: 100% / 1.5 Arial;
}
* {
margin:0;
padding:0;
}
.parallax {
font-size: 200%;
}
/* centre the content in the parallax layers */
.title {
text-align: center;
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
/* style the groups
--------------------------------------------- */
#group1 {
...
JavaScript
function range(el, HEIGHT_MAX) {
// parameters - change to your liking
let STEP_MAX = 2.5;
let STEP_CHANGE = 1.0;
// starting conditions
let height = Math.random() * HEIGHT_MAX;
let slope = (Math.random() * STEP_MAX) * 2 - STEP_MAX;
// creating the landscape
let arr = ["100% 100%", "0% 100%"];
for (var x = 0; x <= 100; x++) {
// change height and slope
height += slope;
slope += (Math.random() * STEP_CHANGE) * 2 - STEP_CHANGE;
// clip height and slope to maximum
if (slope > STEP_MAX) {
slope = STEP_MAX
}
if (slope < -STEP_MAX) {
slope = -STEP_MAX
}
if (height > HEIGHT_MAX) {
height = HEIGHT_MAX;
slope *= -1;
}
if (height < 0) {
height = 0;
slope *= -1;
}
// draw column
arr.push(`${x}% ${100-height}%`);
}
let poly = `polygon(${arr.join(", ")})`;
el.style.clipPath = poly;
}
let ranges = document.querySelectorAll(".range");
for (let i = 0; i < ranges.length; i++) {
range(ranges[i], 100-i*20);
}