<section class="cards__wrapper">
	<figure class="card">
		<div class="card__image--wrapper">
			<div class="card__image--outer">
				<img src="https://t.ly/xgCIZ" alt="Portrait" class="card__image" />
			</div>
		</div>
		<div class="card__text">
			<span class="card__text--inner" data-splitting>STYLE</span>
		</div>
	</figure>

	<figure class="card">
		<div class="card__image--wrapper">
			<div class="card__image--outer">
				<img src="https://t.ly/GsIR4" alt="Portrait" class="card__image" />
			</div>
		</div>
		<div class="card__text">
			<span class="card__text--inner" data-splitting>PRAISE</span>
		</div>
	</figure>

	<figure class="card">
		<div class="card__image--wrapper">
			<div class="card__image--outer">
				<img src="https://t.ly/RfNBf" alt="Portrait" class="card__image" />
			</div>
		</div>
		<div class="card__text">
			<span class="card__text--inner" data-splitting>FASHION</span>
		</div>
	</figure>
</section>

<div class="support">
	<a href="https://vstefanova.com" target="_blank">VS</a>
</div>
@import url("https://fonts.googleapis.com/css2?family=Red+Rose:wght@400;700&display=swap");
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html, body {
  width: 100%;
  height: 100%;
}

body {
  background: #121013;
  display: grid;
  place-items: center;
}

.cards__wrapper {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  pointer-events: none;
  opacity: 0;
}
.cards__wrapper .card {
  position: relative;
  width: 340px;
  height: 400px;
  margin: 3rem 5rem;
  pointer-events: none;
}
.cards__wrapper .card__image--wrapper {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  filter: grayscale(0);
  transition: filter 0.5s ease;
}
.cards__wrapper .card__image {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  object-fit: cover;
  transform: scale(1.15);
  transition: transform 0.5s ease, opacity 0.35s ease;
}
.cards__wrapper .card__image--outer {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.cards__wrapper .card__text {
  position: absolute;
  left: 0;
  bottom: 25%;
  transform: translateX(-8rem);
  pointer-events: none;
  user-select: none;
  mix-blend-mode: difference;
}
.cards__wrapper .card__text--inner {
  display: inline-block;
  color: #fff;
  font-size: 5rem;
  font-family: "Red Rose", Roboto;
  font-weight: 700;
  overflow: hidden;
}
.cards__wrapper .card__text--inner .word {
  white-space: nowrap;
}
.cards__wrapper .card__text--inner .char {
  display: inline-block;
  transform: translateY(100%);
  transition: transform 0.5s cubic-bezier(0.5, 0, 0, 1);
  transition-delay: calc(0ms + var(--char-index) * 20ms);
}
.cards__wrapper .card:hover .card__image {
  transform: scale(1);
}
.cards__wrapper .card:hover .card__text--inner .char {
  transform: translateY(0%);
}
.cards__wrapper:hover > .card:not(:hover) .card__image--wrapper {
  filter: grayscale(1);
}
.cards__wrapper:hover > .card:not(:hover) .card__image {
  opacity: 0.8;
}

.support {
  position: fixed;
  right: 10px;
  bottom: 10px;
  padding: 10px;
  display: flex;
}
.support a {
  margin: 0 10px;
  color: #fff;
  font-size: 1.8rem;
  backface-visibility: hidden;
  transition: all 150ms ease;
}
.support a:hover {
  transform: scale(1.1);
}
console.clear();

const { gsap, Splitting } = window;

Splitting();

gsap.set('.cards__wrapper', { autoAlpha: 1 })

gsap.timeline({
	defaults: {
		duration: 1.25,
		stagger: 0.125,
		ease: "expo.inOut",
	},
})
	.fromTo(".card__image--wrapper", { yPercent: 110 }, { yPercent: 0 }, 0)
	.fromTo(".card__image--outer", { yPercent: -110 }, { yPercent: 0 }, 0)
	.set(".cards__wrapper, .card", { pointerEvents: "all" }, "-=1");

External CSS

  1. https://fonts.googleapis.com/css?family=Montserrat&amp;display=swap"rel="stylesheet

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/gsap/3.1.1/gsap.min.js
  2. https://unpkg.com/splitting/dist/splitting.min.js