{ CF }

11 CSS Page Transitions

Blur Morph Transition

Content softly de-focuses then re-focuses as the new view emerges. Calm and considered — ideal for data-heavy SaaS dashboards and admin apps.

CSS + JS MIT licensed

Blur Morph Transition the 5th 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

<div class="app">
  <!-- Sidebar -->
  <aside class="sidebar">
    <div class="sidebar-brand">
      <div class="brand-icon">◆</div>
      <div class="brand-name">Velocity</div>
    </div>

    <div class="nav-section">Main</div>
    <button class="nav-item active" data-page="overview">
      <span class="nav-icon">▦</span> Overview
    </button>
    <button class="nav-item" data-page="analytics">
      <span class="nav-icon">▲</span> Analytics
      <span class="nav-badge">3</span>
    </button>
    <button class="nav-item" data-page="transactions">
      <span class="nav-icon">≡</span> Transactions
    </button>

    <div class="nav-section">System</div>
    <button class="nav-item" data-page="settings">
      <span class="nav-icon">⚙</span> Settings
    </button>
  </aside>

  <!-- Main -->
  <div class="main">
    <!-- Topbar -->
    <div class="topbar">
      <div class="topbar-title" id="topbarTitle">Overview</div>
      <div class="topbar-right">
        <div class="search-bar">🔍 Search...</div>
        <div class="avatar">KL</div>
      </div>
    </div>

    <!-- Pages -->
    <div class="page-stack">

      <!-- Overview -->
      <div class="dash-page active" id="overview">
        <div class="page-heading">Good afternoon, Kayla 👋</div>
        <div class="page-sub">Here's what's happening with your business today.</div>

        <div class="kpi-row">
          <div class="kpi-card" style="--glow-a: var(--blue)">
            <div class="kpi-icon" style="background:rgba(59,130,246,0.15);color:var(--blue)">💰</div>
            <div class="kpi-value">$84.2k</div>
            <div class="kpi-label">Total Revenue</div>
            <div class="kpi-delta up">↑ 12.4% vs last month</div>
          </div>
          <div class="kpi-card" style="--glow-a: var(--purple)">
            <div class="kpi-icon" style="background:rgba(139,92,246,0.15);color:var(--purple)">👥</div>
            <div class="kpi-value">3,241</div>
            <div class="kpi-label">Active Users</div>
            <div class="kpi-delta up">↑ 8.1% vs last month</div>
          </div>
          <div class="kpi-card" style="--glow-a: var(--green)">
            <div class="kpi-icon" style="background:rgba(16,185,129,0.15);color:var(--green)">✓</div>
            <div class="kpi-value">98.2%</div>
            <div class="kpi-label">Uptime</div>
            <div class="kpi-delta up">↑ 0.3% vs last month</div>
          </div>
          <div class="kpi-card" style="--glow-a: var(--orange)">
            <div class="kpi-icon" style="background:rgba(245,158,11,0.15);color:var(--orange)">⚡</div>
            <div class="kpi-value">142ms</div>
            <div class="kpi-label">Avg Response</div>
            <div class="kpi-delta down">↓ 18ms vs last month</div>
          </div>
        </div>

        <div class="charts-row">
          <div class="chart-card">
            <div class="chart-title">Revenue by Month</div>
            <div class="chart-sub">January — June 2025</div>
            <div class="bar-chart">
              <div class="bar" style="height:55%;background:rgba(59,130,246,0.3)"></div>
              <div class="bar" style="height:70%;background:rgba(59,130,246,0.4)"></div>
              <div class="bar" style="height:45%;background:rgba(59,130,246,0.3)"></div>
              <div class="bar" style="height:85%;background:rgba(59,130,246,0.5)"></div>
              <div class="bar" style="height:72%;background:rgba(59,130,246,0.4)"></div>
              <div class="bar" style="height:95%;background:var(--blue)"></div>
            </div>
          </div>
          <div class="chart-card">
            <div class="chart-title">Traffic Sources</div>
            <div class="chart-sub">Current month breakdown</div>
            <div class="donut-wrap">
              <div class="donut"></div>
              <div class="legend">
                <div class="legend-item"><div class="legend-dot" style="background:var(--blue)"></div>Direct 42%</div>
                <div class="legend-item"><div class="legend-dot" style="background:var(--purple)"></div>Search 26%</div>
                <div class="legend-item"><div class="legend-dot" style="background:var(--green)"></div>Social 16%</div>
                <div class="legend-item"><div class="legend-dot" style="background:var(--muted)"></div>Other 16%</div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- Analytics -->
      <div class="dash-page" id="analytics">
        <div class="page-heading">Analytics</div>
        <div class="page-sub">Funnel performance and conversion data.</div>

        <div class="charts-row">
          <div class="chart-card">
            <div class="chart-title">Conversion Funnel</div>
            <div class="chart-sub">Visitors → Paying customers</div>
            <div class="funnel">
              <div class="funnel-row">
                <div class="funnel-label">Visitors</div>
                <div class="funnel-bar-bg"><div class="funnel-bar-fill" style="width:100%;background:var(--blue)">48,291</div></div>
              </div>
              <div class="funnel-row">
                <div class="funnel-label">Sign-ups</div>
                <div class="funnel-bar-bg"><div class="funnel-bar-fill" style="width:62%;background:var(--purple)">29,940</div></div>
              </div>
              <div class="funnel-row">
                <div class="funnel-label">Activated</div>
                <div class="funnel-bar-bg"><div class="funnel-bar-fill" style="width:38%;background:var(--green)">18,350</div></div>
              </div>
              <div class="funnel-row">
                <div class="funnel-label">Trial</div>
                <div class="funnel-bar-bg"><div class="funnel-bar-fill" style="width:21%;background:var(--orange)">10,141</div></div>
              </div>
              <div class="funnel-row">
                <div class="funnel-label">Paid</div>
                <div class="funnel-bar-bg"><div class="funnel-bar-fill" style="width:9%;background:var(--pink)">4,346</div></div>
              </div>
            </div>
          </div>
          <div class="chart-card">
            <div class="chart-title">Key Metrics</div>
            <div class="chart-sub">Rolling 30-day averages</div>
            <div style="display:flex;flex-direction:column;gap:20px;margin-top:8px">
              <div>
                <div class="kpi-label">Conversion Rate</div>
                <div class="kpi-value" style="font-size:22px">8.9%</div>
                <div class="kpi-delta up">↑ 1.2pp this month</div>
              </div>
              <div>
                <div class="kpi-label">Avg Session Duration</div>
                <div class="kpi-value" style="font-size:22px">4m 32s</div>
                <div class="kpi-delta up">↑ 14s this month</div>
              </div>
              <div>
                <div class="kpi-label">Bounce Rate</div>
                <div class="kpi-value" style="font-size:22px">34.1%</div>
                <div class="kpi-delta down">↓ 2.4pp this month</div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- Transactions -->
      <div class="dash-page" id="transactions">
        <div class="page-heading">Transactions</div>
        <div class="page-sub">Recent payment activity across all accounts.</div>

        <div class="table-card">
          <div class="table-header">
            <div class="table-title">Recent Transactions</div>
            <div style="font-size:12px;color:var(--blue);cursor:pointer">Export CSV</div>
          </div>
          <div class="table-row head">
            <div>Customer</div><div>Amount</div><div>Date</div><div>Status</div>
          </div>
          <div class="table-row"><div>Acme Corp</div><div>$4,200.00</div><div>Jun 12</div><div><span class="status-pill status-active">Paid</span></div></div>
          <div class="table-row"><div>GlobalTech</div><div>$11,800.00</div><div>Jun 11</div><div><span class="status-pill status-pending">Pending</span></div></div>
          <div class="table-row"><div>Sunrise Co</div><div>$860.00</div><div>Jun 10</div><div><span class="status-pill status-active">Paid</span></div></div>
          <div class="table-row"><div>Nova Labs</div><div>$2,100.00</div><div>Jun 9</div><div><span class="status-pill status-failed">Failed</span></div></div>
          <div class="table-row"><div>Peak Media</div><div>$7,450.00</div><div>Jun 8</div><div><span class="status-pill status-active">Paid</span></div></div>
          <div class="table-row"><div>Drift Studio</div><div>$3,300.00</div><div>Jun 7</div><div><span class="status-pill status-active">Paid</span></div></div>
          <div class="table-row"><div>Cloud Nine</div><div>$18,000.00</div><div>Jun 6</div><div><span class="status-pill status-pending">Pending</span></div></div>
        </div>
      </div>

      <!-- Settings -->
      <div class="dash-page" id="settings">
        <div class="page-heading">Settings</div>
        <div class="page-sub">Manage your account and preferences.</div>

        <div class="settings-grid">
          <div class="settings-nav">
            <div class="settings-nav-item active">General</div>
            <div class="settings-nav-item">Security</div>
            <div class="settings-nav-item">Billing</div>
            <div class="settings-nav-item">Notifications</div>
            <div class="settings-nav-item">Integrations</div>
          </div>
          <div class="settings-section">
            <div class="settings-row">
              <div>
                <div class="settings-label">Email Notifications</div>
                <div class="settings-desc">Receive alerts for new transactions and reports</div>
              </div>
              <button class="toggle-switch on" onclick="this.classList.toggle('on')"></button>
            </div>
            <div class="settings-row">
              <div>
                <div class="settings-label">Two-Factor Authentication</div>
                <div class="settings-desc">Add an extra layer of security to your account</div>
              </div>
              <button class="toggle-switch on" onclick="this.classList.toggle('on')"></button>
            </div>
            <div class="settings-row">
              <div>
                <div class="settings-label">Weekly Digest</div>
                <div class="settings-desc">Get a summary of your metrics every Monday</div>
              </div>
              <button class="toggle-switch" onclick="this.classList.toggle('on')"></button>
            </div>
            <div class="settings-row">
              <div>
                <div class="settings-label">Beta Features</div>
                <div class="settings-desc">Access new features before public release</div>
              </div>
              <button class="toggle-switch" onclick="this.classList.toggle('on')"></button>
            </div>
            <div class="settings-row">
              <div>
                <div class="settings-label">Usage Analytics</div>
                <div class="settings-desc">Help us improve by sharing anonymous usage data</div>
              </div>
              <button class="toggle-switch on" onclick="this.classList.toggle('on')"></button>
            </div>
          </div>
        </div>
      </div>

    </div><!-- /page-stack -->
  </div><!-- /main -->
</div><!-- /app -->
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

  :root {
    --bg: #090912;
    --surface: #0f0f1c;
    --surface-2: #161627;
    --border: rgba(255,255,255,0.06);
    --text: #e2e2f0;
    --muted: #6060a0;
    --blue: #3b82f6;
    --purple: #8b5cf6;
    --green: #10b981;
    --orange: #f59e0b;
    --red: #ef4444;
    --pink: #ec4899;
    --dur: 500ms;
    --ease: cubic-bezier(0.4, 0, 0.2, 1);
  }

  html, body {
    height: 100%;
    font-family: 'Plus Jakarta Sans', sans-serif;
    background: var(--bg);
    color: var(--text);
    overflow: hidden;
  }

  /* App Shell */
  .app {
    display: grid;
    grid-template-columns: 220px 1fr;
    height: 100vh;
  }

  /* Sidebar */
  .sidebar {
    background: var(--surface);
    border-right: 1px solid var(--border);
    padding: 24px 16px;
    display: flex;
    flex-direction: column;
    gap: 4px;
  }

  .sidebar-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    margin-bottom: 24px;
  }

  .brand-icon {
    width: 32px; height: 32px;
    background: linear-gradient(135deg, var(--blue), var(--purple));
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
  }

  .brand-name {
    font-size: 15px;
    font-weight: 700;
    color: var(--text);
    letter-spacing: -0.01em;
  }

  .nav-section { font-size: 10px; letter-spacing: 0.15em; text-transform: uppercase; color: var(--muted); padding: 16px 12px 8px; }

  .nav-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 8px;
    cursor: pointer;
    font-size: 13.5px;
    font-weight: 500;
    color: var(--muted);
    border: none;
    background: none;
    width: 100%;
    text-align: left;
    transition: background 0.15s, color 0.15s;
  }

  .nav-item:hover { background: rgba(255,255,255,0.04); color: var(--text); }
  .nav-item.active { background: rgba(59,130,246,0.12); color: var(--blue); }

  .nav-icon { font-size: 15px; width: 20px; text-align: center; }

  .nav-badge {
    margin-left: auto;
    padding: 2px 8px;
    border-radius: 10px;
    font-size: 10px;
    font-weight: 700;
    background: var(--blue);
    color: white;
  }

  /* Main area */
  .main {
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  /* Top bar */
  .topbar {
    height: 60px;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 32px;
    flex-shrink: 0;
  }

  .topbar-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
    transition: all var(--dur) var(--ease);
  }

  .topbar-right { display: flex; gap: 16px; align-items: center; }

  .avatar {
    width: 32px; height: 32px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--purple), var(--pink));
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    font-weight: 700;
  }

  .search-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 6px 14px;
    font-size: 12px;
    color: var(--muted);
    width: 200px;
  }

  /* Page stack */
  .page-stack {
    flex: 1;
    position: relative;
    overflow: hidden;
  }

  .dash-page {
    position: absolute;
    inset: 0;
    overflow-y: auto;
    padding: 32px;
    opacity: 0;
    filter: blur(8px);
    transform: scale(0.98) translateY(8px);
    pointer-events: none;
    transition:
      opacity var(--dur) var(--ease),
      filter var(--dur) var(--ease),
      transform var(--dur) var(--ease);
    will-change: opacity, filter, transform;
  }

  .dash-page.active {
    opacity: 1;
    filter: blur(0px);
    transform: scale(1) translateY(0px);
    pointer-events: auto;
  }

  /* Dashboard components */
  .page-heading {
    font-size: 22px;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 8px;
    letter-spacing: -0.02em;
  }

  .page-sub {
    font-size: 13px;
    color: var(--muted);
    margin-bottom: 28px;
  }

  /* KPI row */
  .kpi-row {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
    margin-bottom: 24px;
  }

  .kpi-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 20px;
    position: relative;
    overflow: hidden;
  }

  .kpi-card::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(135deg, var(--glow-a) 0%, transparent 60%);
    opacity: 0.06;
    pointer-events: none;
  }

  .kpi-icon {
    width: 36px; height: 36px;
    border-radius: 8px;
    display: flex; align-items: center; justify-content: center;
    font-size: 17px;
    margin-bottom: 14px;
  }

  .kpi-value {
    font-size: 26px;
    font-weight: 700;
    letter-spacing: -0.03em;
    color: var(--text);
    margin-bottom: 4px;
  }

  .kpi-label {
    font-size: 12px;
    color: var(--muted);
    margin-bottom: 10px;
  }

  .kpi-delta {
    font-size: 11px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 4px;
  }
  .kpi-delta.up { color: var(--green); }
  .kpi-delta.down { color: var(--red); }

  /* Charts row */
  .charts-row {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 16px;
    margin-bottom: 24px;
  }

  .chart-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    padding: 20px;
  }

  .chart-title {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
    margin-bottom: 4px;
  }

  .chart-sub { font-size: 11px; color: var(--muted); margin-bottom: 20px; }

  /* Fake bar chart */
  .bar-chart {
    display: flex;
    align-items: flex-end;
    gap: 6px;
    height: 120px;
  }

  .bar {
    flex: 1;
    border-radius: 4px 4px 0 0;
    transition: height 1s cubic-bezier(0.32, 0.72, 0, 1);
    min-width: 0;
  }

  /* Fake donut */
  .donut-wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
  }

  .donut {
    width: 100px; height: 100px;
    border-radius: 50%;
    background: conic-gradient(
      var(--blue) 0% 42%,
      var(--purple) 42% 68%,
      var(--green) 68% 84%,
      var(--muted) 84% 100%
    );
    position: relative;
  }

  .donut::after {
    content: '';
    position: absolute;
    inset: 20px;
    border-radius: 50%;
    background: var(--surface);
  }

  .legend {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    font-size: 11px;
    color: var(--muted);
    width: 100%;
  }

  .legend-item { display: flex; align-items: center; gap: 6px; }
  .legend-dot { width: 8px; height: 8px; border-radius: 2px; flex-shrink: 0; }

  /* Table */
  .table-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    overflow: hidden;
  }

  .table-header {
    padding: 16px 20px;
    border-bottom: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  .table-title { font-size: 13px; font-weight: 600; }

  .table-row {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 80px;
    padding: 14px 20px;
    border-bottom: 1px solid var(--border);
    font-size: 12.5px;
    align-items: center;
    transition: background 0.15s;
  }

  .table-row:last-child { border-bottom: none; }
  .table-row:hover { background: rgba(255,255,255,0.02); }
  .table-row.head { color: var(--muted); font-size: 11px; font-weight: 500; }

  .status-pill {
    padding: 3px 10px;
    border-radius: 10px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
  }
  .status-active { background: rgba(16,185,129,0.15); color: var(--green); }
  .status-pending { background: rgba(245,158,11,0.15); color: var(--orange); }
  .status-failed { background: rgba(239,68,68,0.15); color: var(--red); }

  /* Analytics page */
  .funnel {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 24px;
  }

  .funnel-row {
    display: flex;
    align-items: center;
    gap: 16px;
  }

  .funnel-label { font-size: 12px; color: var(--muted); width: 100px; flex-shrink: 0; }

  .funnel-bar-bg {
    flex: 1;
    height: 28px;
    background: var(--surface-2);
    border-radius: 4px;
    overflow: hidden;
  }

  .funnel-bar-fill {
    height: 100%;
    border-radius: 4px;
    display: flex;
    align-items: center;
    padding-left: 10px;
    font-size: 11px;
    font-weight: 700;
    color: white;
    white-space: nowrap;
  }

  /* Settings page */
  .settings-grid {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 24px;
  }

  .settings-nav { display: flex; flex-direction: column; gap: 2px; }
  .settings-nav-item {
    padding: 10px 14px;
    border-radius: 8px;
    font-size: 13px;
    color: var(--muted);
    cursor: pointer;
    transition: all 0.15s;
  }
  .settings-nav-item.active { background: rgba(59,130,246,0.12); color: var(--blue); }
  .settings-nav-item:hover { background: rgba(255,255,255,0.04); color: var(--text); }

  .settings-section {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    overflow: hidden;
  }

  .settings-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 18px 24px;
    border-bottom: 1px solid var(--border);
  }
  .settings-row:last-child { border-bottom: none; }

  .settings-label { font-size: 13.5px; font-weight: 500; margin-bottom: 3px; }
  .settings-desc { font-size: 12px; color: var(--muted); }

  .toggle-switch {
    width: 40px; height: 22px;
    background: rgba(255,255,255,0.1);
    border-radius: 11px;
    position: relative;
    cursor: pointer;
    transition: background 0.25s;
    border: none;
    flex-shrink: 0;
  }
  .toggle-switch.on { background: var(--blue); }
  .toggle-switch::after {
    content: '';
    position: absolute;
    width: 16px; height: 16px;
    background: white;
    border-radius: 50%;
    top: 3px; left: 3px;
    transition: transform 0.25s;
  }
  .toggle-switch.on::after { transform: translateX(18px); }

  @media (max-width: 768px) {
    .app { grid-template-columns: 1fr; }
    .sidebar { display: none; }
    .kpi-row { grid-template-columns: 1fr 1fr; }
    .charts-row { grid-template-columns: 1fr; }
  }

  @media (max-width: 500px) {
    .kpi-row { grid-template-columns: 1fr; }
  }
const navItems = document.querySelectorAll('.nav-item');
  const pages = document.querySelectorAll('.dash-page');
  const titles = { overview: 'Overview', analytics: 'Analytics', transactions: 'Transactions', settings: 'Settings' };

  navItems.forEach(item => {
    item.addEventListener('click', () => {
      const target = item.dataset.page;

      navItems.forEach(n => n.classList.remove('active'));
      item.classList.add('active');

      pages.forEach(p => p.classList.remove('active'));
      document.getElementById(target).classList.add('active');

      document.getElementById('topbarTitle').textContent = titles[target];
    });
  });

Search CodeFronts

Loading…