JSFiddle - React, Tailwind, and code Playground

by phloe

HTML

<div class="wrapper">
  <ol>
    <li class="selected"><figure>
      <div class="image">
      <img src="https://fillmurray.com/640/360"/>
      </div>
      <figcaption>Aliquam ut odio in neque facilisis efficitur.</figcaption>
    </figure></li>
    <li><figure>
      <div class="image">
      <img src="https://fillmurray.com/656/369"/>
      </div>
      <figcaption>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse cursus enim vitae metus interdum faucibus. Mauris at nibh congue, iaculis elit in, pulvinar ex.</figcaption>
    </figure></li>
    <li><figure>
      <div class="image">
      <img src="https://fillmurray.com/672/378"/>
      </div>
      <figcaption>Aenean varius leo sed orci pharetra, eu cursus nibh interdum. Praesent eget dui rhoncus, fringilla urna scelerisque, elementum sapien.</figcaption>
    </figure></li>
    <li><figure>
      <div class="image">
      <img src="https://fillmurray.com/688/387"/>
      </div>
      <figcaption>Aliquam quis felis vitae quam rutrum elementum. Sed in neque quam.</figcaption>
    </figure></li>
    <li><figure>
      <div class="image">
        <img src="https://fillmurray.com/704/396"/>
      </div>
      <figcaption>Fusce consequat egestas nunc eu feugiat. Fusce sit amet sapien vitae nibh dictum hendrerit.</figcaption>
    </figure></li>
  </ol>
</div>

CSS

.wrapper {
  overflow: visible;
  perspective: 1000px;
  perspective-origin: 50% 0;
  max-width: 600px;
  margin: 0 auto;
  background-color: #FFF;
}

ol {
  margin: 0;
  padding: 0;
  white-space: nowrap;
  font-size: 0;
  transition: transform .3s ease;
  transform-style: preserve-3d;
}
li {
  width: 100%;
  white-space: normal;
  font-size: 1rem;
  display: inline-block;
  vertical-align: top;
  transform-style: preserve-3d;
}

li .image {
  transform: translateZ(-1000px) translateX(-50%); 
  transition: transform .3s ease;
}
.selected .image {
  transform: none;
}
.selected ~ li .image {
  transform: translateZ(-1000px) translateX(50%); 
}
figure {
  margin: 0;
}
img {
  width: 100%;
  height: auto;
}
.image {
  position: relative;
  overflow: hidden;
}
.image:after {
  content: "";
  display: block;
  padding-bottom: 56.25%;
}
.image > * {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
figcaption {
	background-color: #FFF;
	padding: 20px;
	opacity: 0;
	transform: translateX(100%);
	transition: transform .3s ease, opacity .3s ease;
}
.selected figcaption {
	opacity: 1;
	transform: none;
}
.selected ~ li figcaption {
	pointer-events: none;
	transform: translateX(-100%);
}

JavaScript

var selected = document.querySelector("li.selected");
var wrapper = document.querySelector("ol");
var width = wrapper.offsetWidth;
var items = Array.from(wrapper.getElementsByTagName("li"));
wrapper.addEventListener("click", ({ target }) => {
window.console && console.log("click", target);
	var element = target.closest("li:not(.selected)");
  if (element) {
  	selected.classList.remove("selected");
    selected = element;
    selected.classList.add("selected");
    setOffset();
  }
});

function setOffset () {
    var index = items.indexOf(selected);
		var offset = index * -100;
    wrapper.style.transform = `translateX(${offset}%)`;
}

window.addEventListener("resize", () => {
	width = wrapper.offsetWidth;
	setOffset();
});