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

基于视口可见产品卡片更新横向导航圆圈颜色的JS实现

Solution to Sync Navigation Dots with Horizontal Scroll for Product Cards

I get your frustration right now—those navigation dots only update when you click them, not when you swipe through the product cards. Since you’re already using scroll-snap for horizontal scrolling, we can fix this by listening to the scroll event on your .usp-container and updating the corresponding radio input’s checked state based on which card is visible in the viewport.

Here’s a straightforward implementation:

Step 1: Add the JavaScript

We’ll listen for scroll events, calculate which card is active, and sync the navigation dots. We’ll also add a throttle to avoid performance hits from too-frequent scroll events, and restrict this logic to mobile/tablet screens.

// Throttle function to limit how often the sync runs (prevents jank)
function throttle(func, limit) {
  let inThrottle;
  return function() {
    const args = arguments;
    const context = this;
    if (!inThrottle) {
      func.apply(context, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  }
}

// Core function to sync dots with visible card
function syncNavigationDots() {
  const container = document.querySelector('.usp-container');
  const items = document.querySelectorAll('.usp-item');
  const radios = document.querySelectorAll('.usp-radio');
  
  // Only run on mobile/tablet (adjust breakpoint to match your design)
  if (window.innerWidth > 768) return;

  // Calculate which card is in view
  const scrollPos = container.scrollLeft;
  const itemWidth = items[0].offsetWidth;
  const activeCardIndex = Math.round(scrollPos / itemWidth);

  // Update the corresponding radio input
  if (radios[activeCardIndex]) {
    radios[activeCardIndex].checked = true;
  }
}

// Attach the throttled scroll listener
const scrollContainer = document.querySelector('.usp-container');
scrollContainer.addEventListener('scroll', throttle(syncNavigationDots, 100));

// Sync dots on page load too
window.addEventListener('load', syncNavigationDots);

Step 2: How it works

  • Throttle: Limits the sync function to run every 100ms, so it doesn’t fire nonstop during scrolling (keeps things smooth).
  • Active card calculation: Since each .usp-item takes 100% of the container width, dividing the scroll position by the item width gives us the index of the visible card.
  • Mobile/tablet restriction: The function only runs on screens narrower than 768px—tweak this number to match your breakpoint for tablet/mobile.
  • Initial sync: Makes sure the correct dot is highlighted when the page first loads.

Step 3: No CSS changes needed

Your existing CSS already handles styling the active dot perfectly, so you can leave this part as-is:

.usp-radio:checked + label { background-color: #707070; }

Quick notes

  • Double-check that your .usp-item elements are exactly 100% width of the container (your current CSS already enforces this with width: 100%;).
  • If your mobile/tablet breakpoint is different, adjust the window.innerWidth > 768 value to match your design specs.
  • The scroll-snap-type: x mandatory ensures only one card is fully visible at a time, so Math.round() will always pick the correct active card index.

With this setup, the navigation dots will update automatically whether users click the dots or swipe through the cards.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 21:52:59