<div class="content">
<div class="layer background background-animation">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/217233/pc1.png" />
</div>
<div class="layer train train-animation">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/217233/pc2.png" />
</div>
<div class="layer foreground foreground-animation">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/217233/pc3.png" />
</div>
<div class="frame"></div>
</div>
/* Press "Play Animation" to restart/replay */
* {
box-sizing: border-box;
}
body {
background-color: rgb(197, 217, 255);
overflow-x: auto;
}
.content {
position: relative;
height: 200px;
width: 200px;
margin: 60px auto;
}
.layer {
position: absolute;
}
.background {
transform: translateX(0);
}
.train {
transform: translateX(-440px);
}
.foreground {
transform: translateX(-210px);
}
.background-animation {
animation: background-shift 4s linear 1 forwards;
}
.train-animation {
animation: train-shift 4s linear 1 forwards;
}
.foreground-animation {
animation: foreground-shift 4s linear 1 forwards;
}
@keyframes background-shift {
to {
transform: translateX(-80px);
}
}
@keyframes train-shift {
to {
transform: translateX(-140px);
}
}
@keyframes foreground-shift {
to {
transform: translateX(-400px);
}
}
/* Just for demostration, not required for animation */
.frame {
position: absolute;
top: 0;
width: 100%;
height: 100%;
border: 3px solid rgb(0, 255, 21);
}
.bordered {
border: 2px dotted red;
}
// JS only necessary for deconstruction demo. It is a CSS-only animation
const gui = new dat.GUI({ name: "My GUI" });
const content = document.getElementsByClassName("content")[0];
const layers = document.getElementsByClassName("layer");
const images = document.getElementsByTagName("img");
const replaying = false;
const config = {
overflow: true,
exploded: false,
replay: replay,
reset: reset,
};
gui
.add(config, "overflow")
.name("Overflow?")
.onChange((newValue) => {
if (newValue === false) {
content.style.overflow = "hidden";
} else {
content.style.overflow = "visible";
}
});
gui
.add(config, "exploded")
.name("Explode?")
.onChange((newValue) => {
if (newValue === true) {
const overFlowCheckbox = document.querySelector(
"div.dg.main li:first-child input"
);
overFlowCheckbox.checked = true;
overFlowCheckbox.disabled = true;
content.style.overflow = "visible";
for (element of layers) {
element.style.position = "static";
}
} else {
config.overflow = false;
const overFlowCheckbox = document.querySelector(
"div.dg.main li:first-child input"
);
if (overFlowCheckbox.checked === true) {
overFlowCheckbox.click();
}
overFlowCheckbox.disabled = false;
for (element of layers) {
element.style.position = "absolute";
}
}
toggleBorders();
});
gui
.add(config, "replay")
.name("Play Animation")
.onChange((newValue) => {
replay();
});
function replay() {
reset();
setTimeout(() => {
layers[0].classList.add("background-animation");
layers[1].classList.add("train-animation");
layers[2].classList.add("foreground-animation");
}, 20);
}
gui
.add(config, "reset")
.name("Reset Animation")
.onChange((newValue) => {
reset();
});
function reset() {
layers[0].classList.remove("background-animation");
layers[1].classList.remove("train-animation");
layers[2].classList.remove("foreground-animation");
}
function toggleBorders() {
for (img of images) {
img.classList.toggle("bordered");
}
}
This Pen doesn't use any external CSS resources.