{ CF }

11 CSS Page Transitions

Clip-Path Wipe

A dramatic clip-path reveal that wipes the new page into view. High-impact and memorable — best reserved for creative portfolios and brand sites.

CSS + JS MIT licensed

Clip-Path Wipe the 4th of 11 designs in the 11 CSS Page Transitions collection. The design pairs CSS styling with a small amount of JavaScript for interactivity. Copy the HTML, CSS and JavaScript panels below into your project — the JS is self-contained, has zero dependencies, and is safe to drop into any framework (React, Vue, Svelte, plain HTML). The design honours prefers-reduced-motion and uses real semantic markup, so it ships accessibility-ready out of the box.

Live preview

This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.

Open in playground

The code

<!-- Pages -->
<div class="page" id="page-0">
  <div class="bg-word">STUDIO</div>
  <div class="hero-grid">
    <div>
      <div class="hero-eyebrow">Creative Studio · Est. 2019</div>
      <h1 class="hero-title">WE BUILD<br><span>BOLD</span><br>FUTURES</h1>
      <p class="hero-body">A multi-disciplinary studio pushing the boundaries of brand, motion, and digital experience design.</p>
      <button class="btn-hero" onclick="goTo(1)">View Work →</button>
    </div>
    <div class="hero-side">
      <div class="hero-stat">
        <div class="hero-stat-num">142</div>
        <div class="hero-stat-label">Projects</div>
      </div>
      <div class="hero-stat">
        <div class="hero-stat-num">8yr</div>
        <div class="hero-stat-label">Experience</div>
      </div>
      <div class="hero-stat">
        <div class="hero-stat-num">4.9</div>
        <div class="hero-stat-label">Avg Rating</div>
      </div>
    </div>
  </div>
</div>

<div class="page page-incoming" id="page-1">
  <div class="page-header">
    <h1>SELECTED<br>WORK</h1>
  </div>
  <div class="proj-grid">
    <div class="proj-card"><div class="proj-num">01</div><div class="proj-cat">Brand Identity</div><div class="proj-title">Luminary<br>Financial</div><div class="proj-arrow">→</div></div>
    <div class="proj-card"><div class="proj-num">02</div><div class="proj-cat">Digital Experience</div><div class="proj-title">Atlas<br>Platform</div><div class="proj-arrow">→</div></div>
    <div class="proj-card"><div class="proj-num">03</div><div class="proj-cat">Motion & Film</div><div class="proj-title">Epoch<br>Campaign</div><div class="proj-arrow">→</div></div>
    <div class="proj-card"><div class="proj-num">04</div><div class="proj-cat">Product Design</div><div class="proj-title">Nova<br>Wearables</div><div class="proj-arrow">→</div></div>
  </div>
</div>

<div class="page page-incoming" id="page-2">
  <div class="about-grid">
    <div>
      <h1>WE ARE<br><em>FORM</em><br>STUDIO</h1>
    </div>
    <div>
      <p class="about-body">A tight team of designers, developers, and strategists who believe that great work comes from obsessing over every pixel, every word, and every interaction.</p>
      <p class="about-body">We've partnered with everyone from pre-seed startups to Fortune 500s — always bringing the same level of care.</p>
      <div class="skill-row">
        <div class="skill-item">
          <div class="skill-name"><span>Brand Design</span><span>97%</span></div>
          <div class="skill-bar"><div class="skill-fill" style="width:97%"></div></div>
        </div>
        <div class="skill-item">
          <div class="skill-name"><span>Web Development</span><span>92%</span></div>
          <div class="skill-bar"><div class="skill-fill" style="width:92%"></div></div>
        </div>
        <div class="skill-item">
          <div class="skill-name"><span>Motion Design</span><span>88%</span></div>
          <div class="skill-bar"><div class="skill-fill" style="width:88%"></div></div>
        </div>
      </div>
    </div>
  </div>
</div>

<!-- Nav -->
<nav class="site-nav">
  <div class="nav-logo">FORM</div>
  <div class="nav-links">
    <button class="nav-link active" data-idx="0" onclick="goTo(0)">Home</button>
    <button class="nav-link" data-idx="1" onclick="goTo(1)">Work</button>
    <button class="nav-link" data-idx="2" onclick="goTo(2)">About</button>
  </div>
</nav>

<!-- Page dots -->
<div class="page-indicator">
  <button class="ind-dot active" data-idx="0" onclick="goTo(0)"></button>
  <button class="ind-dot" data-idx="1" onclick="goTo(1)"></button>
  <button class="ind-dot" data-idx="2" onclick="goTo(2)"></button>
</div>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

  :root {
    --dur: 800ms;
    --ease: cubic-bezier(0.76, 0, 0.24, 1);
  }

  html, body {
    height: 100%;
    overflow: hidden;
    font-family: 'Space Grotesk', sans-serif;
  }

  /* Pages */
  .page {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
  }

  /* Base state: clipped to nothing (right side) */
  .page-incoming {
    clip-path: polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%);
    transition: clip-path var(--dur) var(--ease);
    pointer-events: none;
    z-index: 2;
  }

  /* Fully revealed */
  .page-incoming.reveal {
    clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
  }

  /* Exiting page stays visible beneath */
  .page-outgoing {
    z-index: 1;
  }

  /* Page 0 — Hero */
  #page-0 {
    background: #0e0e14;
    justify-content: flex-end;
    padding: 80px;
    color: white;
  }

  #page-0 .bg-word {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-family: 'Bebas Neue', sans-serif;
    font-size: min(25vw, 240px);
    line-height: 1;
    color: rgba(255,255,255,0.04);
    white-space: nowrap;
    pointer-events: none;
    letter-spacing: -0.02em;
  }

  #page-0 .hero-grid {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: end;
    gap: 40px;
    width: 100%;
    max-width: 1100px;
  }

  #page-0 .hero-eyebrow {
    font-size: 11px;
    letter-spacing: 0.25em;
    text-transform: uppercase;
    color: #8888aa;
    margin-bottom: 24px;
  }

  #page-0 .hero-title {
    font-family: 'Bebas Neue', sans-serif;
    font-size: clamp(52px, 9vw, 120px);
    line-height: 0.92;
    letter-spacing: -0.01em;
    color: white;
    margin-bottom: 32px;
  }

  #page-0 .hero-title span { color: #c8ff00; }

  #page-0 .hero-body {
    font-size: 15px;
    line-height: 1.75;
    color: #8888aa;
    max-width: 420px;
    margin-bottom: 48px;
  }

  .btn-hero {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    background: #c8ff00;
    color: #0e0e14;
    border: none;
    padding: 18px 36px;
    font-family: 'Space Grotesk', sans-serif;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    cursor: pointer;
    border-radius: 2px;
    transition: transform 0.2s, background 0.2s;
  }
  .btn-hero:hover { background: #d4ff33; transform: translateX(3px); }

  .hero-side {
    display: flex;
    flex-direction: column;
    gap: 12px;
    align-items: flex-end;
  }

  .hero-stat {
    text-align: right;
    border-right: 2px solid #c8ff00;
    padding-right: 20px;
  }

  .hero-stat-num {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 40px;
    color: white;
    line-height: 1;
  }

  .hero-stat-label {
    font-size: 10px;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: #555570;
  }

  /* Page 1 — Projects */
  #page-1 {
    background: #c8ff00;
    overflow-y: auto;
    padding: 80px;
    color: #0e0e14;
  }

  #page-1 .page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: 64px;
  }

  #page-1 h1 {
    font-family: 'Bebas Neue', sans-serif;
    font-size: clamp(52px, 9vw, 112px);
    line-height: 0.9;
    letter-spacing: -0.01em;
    color: #0e0e14;
  }

  .proj-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 3px;
  }

  .proj-card {
    background: #0e0e14;
    padding: 36px;
    color: white;
    display: flex;
    flex-direction: column;
    min-height: 220px;
    position: relative;
    overflow: hidden;
    cursor: pointer;
    transition: background 0.3s;
  }

  .proj-card:nth-child(even) { background: #1a1a24; }
  .proj-card:hover { background: #2a2a3a; }

  .proj-num {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 64px;
    color: rgba(200,255,0,0.15);
    line-height: 1;
    position: absolute;
    top: 16px;
    right: 24px;
    letter-spacing: -0.04em;
  }

  .proj-cat {
    font-size: 9px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: #555570;
    margin-bottom: 12px;
  }

  .proj-title {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 36px;
    letter-spacing: 0.01em;
    line-height: 1.1;
    color: white;
    margin-bottom: auto;
  }

  .proj-arrow {
    margin-top: 32px;
    font-size: 20px;
    color: #c8ff00;
  }

  /* Page 2 — About */
  #page-2 {
    background: #1a0a2e;
    color: white;
    padding: 80px;
    display: flex;
    align-items: center;
  }

  #page-2 .about-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 80px;
    align-items: center;
    max-width: 1000px;
    margin: 0 auto;
    width: 100%;
  }

  #page-2 h1 {
    font-family: 'Bebas Neue', sans-serif;
    font-size: clamp(52px, 8vw, 100px);
    line-height: 0.9;
    letter-spacing: -0.01em;
  }

  #page-2 h1 em {
    color: #c8ff00;
    font-style: italic;
    font-family: inherit;
  }

  #page-2 .about-body {
    font-size: 15px;
    line-height: 1.8;
    color: #8888aa;
    margin-bottom: 32px;
  }

  .skill-row { margin-top: 32px; }
  .skill-item { margin-bottom: 16px; }
  .skill-name {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 6px;
    color: #aaaacc;
  }
  .skill-bar {
    height: 2px;
    background: rgba(255,255,255,0.1);
    border-radius: 1px;
    overflow: hidden;
  }
  .skill-fill {
    height: 100%;
    background: #c8ff00;
    border-radius: 1px;
  }

  /* Nav */
  .site-nav {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 50;
    padding: 28px 48px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    mix-blend-mode: difference;
  }

  .nav-logo {
    font-family: 'Bebas Neue', sans-serif;
    font-size: 24px;
    letter-spacing: 0.05em;
    color: white;
    cursor: pointer;
  }

  .nav-links {
    display: flex;
    gap: 32px;
  }

  .nav-link {
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: white;
    cursor: pointer;
    border: none;
    background: none;
    position: relative;
    padding-bottom: 4px;
    transition: opacity 0.2s;
  }
  .nav-link::after {
    content: '';
    position: absolute;
    bottom: 0; left: 0;
    width: 0%; height: 1px;
    background: white;
    transition: width 0.3s;
  }
  .nav-link:hover::after,
  .nav-link.active::after { width: 100%; }

  /* Page indicator */
  .page-indicator {
    position: fixed;
    right: 32px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 50;
    display: flex;
    flex-direction: column;
    gap: 8px;
    mix-blend-mode: difference;
  }

  .ind-dot {
    width: 4px; height: 4px;
    background: rgba(255,255,255,0.3);
    border-radius: 2px;
    transition: height 0.3s, background 0.3s;
    cursor: pointer;
    border: none;
  }
  .ind-dot.active {
    height: 24px;
    background: white;
  }

  @media (max-width: 640px) {
    #page-0, #page-1, #page-2 { padding: 80px 24px 40px; }
    #page-0 .hero-grid { grid-template-columns: 1fr; }
    .hero-side { display: none; }
    .proj-grid { grid-template-columns: 1fr; }
    #page-2 .about-grid { grid-template-columns: 1fr; gap: 32px; }
    .site-nav { padding: 20px 24px; }
    .nav-links { gap: 16px; }
  }
const pages = document.querySelectorAll('.page');
  const navLinks = document.querySelectorAll('.nav-link');
  const indDots = document.querySelectorAll('.ind-dot');
  let current = 0;
  let transitioning = false;

  function goTo(idx) {
    if (idx === current || transitioning) return;
    transitioning = true;

    const prev = current;
    current = idx;

    // Update nav & dots
    navLinks.forEach(l => l.classList.toggle('active', +l.dataset.idx === current));
    indDots.forEach(d => d.classList.toggle('active', +d.dataset.idx === current));

    // Set the incoming page visible but clipped
    const incoming = pages[current];
    incoming.classList.add('page-incoming');
    incoming.classList.remove('reveal');
    incoming.style.zIndex = 2;

    // Trigger reflow then animate
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        incoming.classList.add('reveal');
      });
    });

    // After animation, clean up old page
    setTimeout(() => {
      pages[prev].style.zIndex = 1;
      incoming.style.zIndex = 1;

      // Reset all other pages to hidden state
      pages.forEach((p, i) => {
        if (i !== current) {
          p.classList.add('page-incoming');
          p.classList.remove('reveal');
          p.style.zIndex = '';
        } else {
          p.classList.remove('page-incoming');
          p.classList.remove('reveal');
          p.style.zIndex = '';
        }
      });

      transitioning = false;
    }, 850);
  }

  // Initialize: show first page, hide rest
  pages.forEach((p, i) => {
    if (i === 0) {
      p.classList.remove('page-incoming');
    } else {
      p.classList.add('page-incoming');
    }
  });

  // Keyboard
  document.addEventListener('keydown', e => {
    if (e.key === 'ArrowRight' || e.key === 'ArrowDown') goTo(Math.min(current + 1, pages.length - 1));
    if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') goTo(Math.max(current - 1, 0));
  });

  // Wheel
  let lastWheel = 0;
  document.addEventListener('wheel', e => {
    const now = Date.now();
    if (now - lastWheel < 900) return;
    lastWheel = now;
    if (e.deltaY > 0) goTo(Math.min(current + 1, pages.length - 1));
    if (e.deltaY < 0) goTo(Math.max(current - 1, 0));
  });

Search CodeFronts

Loading…