About this snippet

Guide your users with an SVG glowing scroll timeline. As they move down the page, a neon line traces their exact path, so the journey feels alive.

Size
3.5 KB
Uses
HTML, CSS, JavaScript
Loads
Nothing external
Views
191
<div class="timeline-wrapper">
  <div class="header-space">Scroll to Trace</div>
  
  <div class="timeline-content" id="timeline-container">
    <svg class="timeline-svg" viewBox="0 0 100 1000" preserveAspectRatio="none">
      <path id="base-path" d="M 50 0 C 90 200, 10 400, 50 600 C 90 800, 10 900, 50 1000" fill="none" stroke="rgba(255, 255, 255, 0.05)" stroke-width="4"></path>
      <path id="glow-path" d="M 50 0 C 90 200, 10 400, 50 600 C 90 800, 10 900, 50 1000" fill="none" stroke="#10b981" stroke-width="4"></path>
    </svg>
    
    <div class="timeline-item" style="top: 20%;">
      <h3>Planning Phase</h3>
      <p>We strategize and outline the core architecture flawlessly.</p>
    </div>
    
    <div class="timeline-item right-side" style="top: 50%;">
      <h3>Development</h3>
      <p>We build out the structural components gracefully.</p>
    </div>
    
    <div class="timeline-item" style="top: 80%;">
      <h3>Launch Ready</h3>
      <p>The project finally goes live to the entire world.</p>
    </div>
  </div>
  
  <div class="header-space">End of Journey</div>
</div>
*, *::before, *::after {
  box-sizing: border-box;
}

body {
  font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  margin: 0;
  background: #0f172a;
  color: #ffffff;
}

.header-space {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 2rem;
  font-weight: 700;
  color: #64748b;
  text-transform: uppercase;
  letter-spacing: 4px;
}

.timeline-wrapper {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.timeline-content {
  position: relative;
  width: 100%;
  max-width: 800px;
  height: 1500px;
  margin: 0 auto;
}

.timeline-svg {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 100px;
  height: 100%;
  overflow: visible;
}

#glow-path {
  stroke-linecap: round;
  filter: drop-shadow(0 0 12px #10b981);
  transition: stroke-dashoffset 0.1s linear;
}

.timeline-item {
  position: absolute;
  left: calc(50% + 80px);
  width: 300px;
  background: rgba(255, 255, 255, 0.05);
  backdrop-filter: blur(10px);
  padding: 24px;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
}

.timeline-item.right-side {
  left: auto;
  right: calc(50% + 80px);
  text-align: right;
}

.timeline-item h3 {
  margin: 0 0 8px 0;
  color: #10b981;
  font-size: 1.5rem;
}

.timeline-item p {
  margin: 0;
  color: #cbd5e1;
  line-height: 1.6;
}

@media (max-width: 800px) {
  .timeline-svg { left: 40px; transform: none; }
  .timeline-item, .timeline-item.right-side { left: 120px; right: auto; text-align: left; width: calc(100% - 160px); }
}
const path = document.getElementById("glow-path");
const container = document.getElementById("timeline-container");

const pathLength = path.getTotalLength();

// Setup the initial drawing state
path.style.strokeDasharray = pathLength;
path.style.strokeDashoffset = pathLength;

window.addEventListener("scroll", function() {
  const rect = container.getBoundingClientRect();
  const top = rect.top;
  const height = rect.height;
  const windowHeight = window.innerHeight;
  
  // Calculate how much of the container is visible
  let progress = (windowHeight - top) / (height + windowHeight);
  
  if (progress < 0) progress = 0;
  if (progress > 1) progress = 1;
  
  // Update the dash offset to draw the SVG naturally
  const drawLength = pathLength * progress;
  path.style.strokeDashoffset = pathLength - drawLength;
});
Esc
↑↓ moveEnter select

Start from a template

Open an .html file, or HTML, CSS, JS, Markdown, Less or TypeScript files. You can also drop them here. Styles and scripts go into their panes.

Share

Source

Keyboard shortcuts

Save