<div class="text-container">
  <svg class="svg-clip">
    <defs>
      <clipPath id="text-clip"></clipPath>
    </defs>
  </svg>

  <h1 class="text-header">
    <div class="text-header__content text-header__content--orig">TEXT</div>
    <div class="text-header__content text-header__content--copy" aria-hidden="true">TEXT</div>
  </h1>
</div>
<section class="bg">
</section>
<section class="no-bg">
</section>
<section class="bg">
</section>
<section class="no-bg">
</section>
body,
html {
  margin: 0;
  padding: 0;
}

section {
  width: 100vw;
  height: 100vh;
  background: #fff;
}

.bg {
  background: #000 url("https://source.unsplash.com/featured?milkyway")
    no-repeat;
  background-size: cover;
}

.text-container {
  position: fixed;
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.svg-clip {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
}

.text-header {
  position: relative;
  font-size: 150px;
  z-index: 0;
}

.text-header__content {
  &--orig {
    background: linear-gradient(90deg, #8500ff, #ff8100);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    clip-path: url('#text-clip');
  }
  
  &--copy {
    position: absolute;
    top: 0;
    left: 0;
    color: #fff;
    z-index: -1;
  }
}
View Compiled
const clipedText = document.querySelector(".text-header__content--orig");
const clipPath = document.querySelector("#text-clip");
const sections = document.querySelectorAll(".no-bg");
let textRect = null;

function getPageBoundRect(el, sx = 0, sy = 0) {
  const r = el.getBoundingClientRect();
  return {
    x: r.x + sx,
    y: r.y + sy,
    w: r.width, 
    h: r.height,
  };
}

const xmlns = "http://www.w3.org/2000/svg";
const clipRects = Array.from(sections, (sect) => ({
  clipRectEl: document.createElementNS(xmlns, "rect"),
  sectionRect: null,
  section: sect
}));

clipRects.forEach((r) => clipPath.appendChild(r.clipRectEl));

function resizeClips() {
  textRect = clipedText.getBoundingClientRect();
  const dx = -textRect.x - window.scrollX;
  const dy = -textRect.y - window.scrollY;
  
  clipRects.forEach((r) => {
    r.sectionRect = getPageBoundRect(r.section, window.scrollX, window.scrollY);
    r.clipRectEl.setAttribute("x", r.sectionRect.x + dx);
    r.clipRectEl.setAttribute("y", r.sectionRect.y + dy);
    r.clipRectEl.setAttribute("width", r.sectionRect.w);
    r.clipRectEl.setAttribute("height", r.sectionRect.h);
  });
}

resizeClips();
window.addEventListener("resize", resizeClips);


window.addEventListener("scroll", e => {
  const dx = -textRect.x - window.scrollX;
  const dy = -textRect.y - window.scrollY;
  
  clipRects.forEach(r => {
    r.clipRectEl.setAttribute("x", r.sectionRect.x + dx);
    r.clipRectEl.setAttribute("y", r.sectionRect.y + dy);
  })
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.