You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求协助实现CSS动画:滚动时灰色线条停在标题起始位置

How to Lock a Scroll-Triggered Gray Line to the Start of Each Heading

Hey there! Let’s get that gray line snapping to the start of your headings (like the "a" in "about reena") as you scroll. Here’s a practical, step-by-step approach to make this work smoothly:

1. Use Intersection Observer to Track Heading Visibility

Instead of listening to the scroll event directly (which can feel janky), the Intersection Observer API is perfect for detecting when your headings enter the viewport. It’s more performant and way easier to fine-tune trigger timing.

2. Control the Line with CSS Variables

We’ll use a CSS variable to handle the line’s left position—this lets JavaScript update the position dynamically while CSS takes care of the smooth transition between positions.

First, style your line in CSS:

.scroll-indicator-line {
  position: fixed;
  top: 50%; /* Adjust this to match your line's vertical position */
  transform: translateY(-50%);
  height: 2px;
  width: 80px; /* Set your desired line length */
  background-color: #888; /* Your gray color */
  left: var(--line-offset, 0);
  transition: left 0.3s ease-out; /* Smooth transition between positions */
}

3. Sync Line Position with Heading Offsets

Now, write JavaScript to grab each heading’s left offset and update the CSS variable when the heading comes into view.

// Grab the line element and all your target headings
const scrollLine = document.querySelector('.scroll-indicator-line');
const sectionHeadings = document.querySelectorAll('h2.section-heading'); // Adjust selector to match your headings

// Set up the Intersection Observer
const headingObserver = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      // Get the heading's left position relative to its parent container
      const headingStartPosition = entry.target.offsetLeft;
      // Update the CSS variable to move the line
      scrollLine.style.setProperty('--line-offset', `${headingStartPosition}px`);
    }
  });
}, {
  threshold: 0.6, // Trigger when 60% of the heading is visible
  rootMargin: '0px 0px -15% 0px' // Adjust to fine-tune when the animation starts
});

// Observe each heading
sectionHeadings.forEach(heading => headingObserver.observe(heading));

4. Fine-Tune for Edge Cases

  • Responsive Adjustments: If your headings shift position on mobile, use getBoundingClientRect() instead of offsetLeft to get the heading’s position relative to the viewport:
    const rect = entry.target.getBoundingClientRect();
    const headingStartPosition = rect.left + window.scrollX;
    
  • Initial Position: Set a default --line-offset value in CSS to position the line correctly when the page loads.
  • Smooth Scrolling: If your site uses smooth scroll, ensure the observer’s timing aligns with the scroll animation duration.

5. Bonus: Smooth Scroll-Driven Transition (Optional)

If you want the line to glide between heading positions as you scroll (instead of snapping), use a library like GSAP’s ScrollTrigger. It can map scroll progress directly to the line’s position for a seamless effect:

// Example with GSAP ScrollTrigger
gsap.to(scrollLine, {
  left: () => {
    // Calculate total range of heading offsets
    const firstHeadingLeft = sectionHeadings[0].offsetLeft;
    const lastHeadingLeft = sectionHeadings[sectionHeadings.length - 1].offsetLeft;
    return `${lastHeadingLeft}px`;
  },
  scrollTrigger: {
    trigger: 'body',
    start: 'top top',
    end: 'bottom bottom',
    scrub: 0.3, // Smoothly scrub the animation with scroll
    snap: {
      snapTo: sectionHeadings.map(heading => heading.offsetTop / document.body.scrollHeight),
      duration: 0.2
    }
  }
});

Play around with the transition timing, observer thresholds, and snap points to get the exact behavior you want. If you hit snags with your specific markup, feel free to share more details!

内容的提问来源于stack exchange,提问作者Reena Verma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:27:37