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

仅使用原生JavaScript实现平滑滚动:替代jQuery方案及Safari兼容问题解决

Native JavaScript Smooth Scroll (Safari-Compatible)

Hey there! I’ve run into that exact Safari compatibility issue with scrollIntoView({ behavior: 'smooth' }) before—older Safari versions just don’t support it. Let’s replace your jQuery smooth scroll with a fully native solution that works across all modern browsers, including Safari.

Step 1: Set Up Anchor Click Listeners

First, we’ll listen for clicks on all anchor links starting with #, and override their default instant jump behavior:

document.addEventListener('DOMContentLoaded', function() {
  // Grab all anchor links pointing to in-page sections
  const anchorLinks = document.querySelectorAll('a[href^="#"]');
  
  anchorLinks.forEach(link => {
    link.addEventListener('click', function(e) {
      e.preventDefault(); // Stop the default jump action
      
      const targetId = this.getAttribute('href');
      
      // Handle empty # links (smooth scroll to top)
      if (targetId === '#') {
        smoothScrollTo(0, 1000);
        return;
      }
      
      const targetElement = document.querySelector(targetId);
      if (targetElement) {
        // Calculate the target position relative to the document top
        const targetOffset = targetElement.getBoundingClientRect().top + window.pageYOffset;
        smoothScrollTo(targetOffset, 1000);
      }
    });
  });
});

Step 2: Custom Smooth Scroll Function

Instead of relying on the inconsistent scrollIntoView smooth behavior, we’ll build our own using requestAnimationFrame—this works everywhere, including Safari. It even mimics jQuery’s default swing animation curve for a familiar, natural feel:

function smoothScrollTo(targetPos, duration) {
  const startPos = window.pageYOffset;
  const distance = targetPos - startPos;
  let startTime = null;
  
  function animateScroll(currentTime) {
    if (startTime === null) startTime = currentTime;
    const timeElapsed = currentTime - startTime;
    const progress = Math.min(timeElapsed / duration, 1);
    
    // Cubic easing to create smooth acceleration/deceleration
    const ease = easeInOutCubic(progress);
    window.scrollTo(0, startPos + (distance * ease));
    
    // Continue animating until we reach the desired duration
    if (timeElapsed < duration) {
      requestAnimationFrame(animateScroll);
    }
  }
  
  // Easing function that matches jQuery's default swing animation
  function easeInOutCubic(t) {
    return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
  }
  
  requestAnimationFrame(animateScroll);
}

Why This Works for Safari

  • We’re ditching the scrollIntoView({ behavior: 'smooth' }) API that Safari struggles with, using requestAnimationFrame instead—this is supported in all modern browsers, even older Safari versions.
  • The custom easing function ensures the scroll feels just like your original jQuery code, not a stiff linear scroll.
  • We handle edge cases like empty # links, which smoothly scroll back to the top of the page.

Bonus: Fix Fixed Navbar Overlap

If you have a fixed navbar that covers your target sections when scrolling, adjust the target offset by subtracting the navbar’s height:

// Replace 'navbar' with your actual navbar ID or selector
const navbar = document.getElementById('navbar');
const targetOffset = targetElement.getBoundingClientRect().top + window.pageYOffset - navbar.offsetHeight;

This ensures your target section is fully visible below the navbar when scrolling completes.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 22:12:28