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

滚动时逐字切换文本颜色效果实现咨询(参考Polestar Precision区块)

Polestar官网Precision区块文本变色+粘性取消效果实现方案

核心实现原理

这个效果的核心逻辑分为两部分:

  • 文本渐变变色:通过双层文本叠加或拆分字母独立控制,结合滚动进度计算,逐步切换文本颜色;
  • 粘性定位动态取消:监听滚动位置,当变色动画完成后,移除元素的粘性定位属性。

方案一:双层文本叠加(性能更优,接近官方实现)

无需拆分字母,通过上下两层相同文本叠加,上层白色、下层目标色,滚动时裁剪上层文本实现渐变效果:

  1. HTML结构
<section class="precision-section">
  <div class="sticky-container">
    <h2 class="text-layer target-color">Precision</h2>
    <h2 class="text-layer white-color">Precision</h2>
  </div>
  <!-- 区块其他内容 -->
</section>
  1. CSS基础样式
.precision-section {
  min-height: 200vh; /* 预留足够滚动空间触发动画 */
}
.sticky-container {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
.text-layer {
  position: absolute;
  font-size: 8rem;
  font-weight: bold;
}
.target-color {
  color: rgb(211, 188, 141);
}
.white-color {
  color: #fff;
  clip-path: inset(0 0 0 0); /* 初始完全覆盖下层文本 */
}
  1. JavaScript逻辑
const stickyContainer = document.querySelector('.sticky-container');
const whiteText = document.querySelector('.white-color');
const section = document.querySelector('.precision-section');

window.addEventListener('scroll', () => {
  requestAnimationFrame(() => {
    // 计算当前滚动位置相对于区块的进度(0~1)
    const sectionTop = section.offsetTop;
    const sectionHeight = section.offsetHeight;
    const scrollY = window.scrollY;
    const progress = Math.min(1, Math.max(0, (scrollY - sectionTop) / (sectionHeight - window.innerHeight)));

    // 通过clip-path裁剪上层白色文本,逐步露出下层目标色
    whiteText.style.clipPath = `inset(0 0 ${progress * 100}% 0)`;

    // 进度达到1时取消粘性定位
    stickyContainer.style.position = progress === 1 ? 'static' : 'sticky';
  });
});

方案二:拆分字母独立控制(你尝试的思路)

将每个字母拆分为独立元素,按滚动进度依次切换颜色:

  1. HTML结构
<section class="precision-section">
  <div class="sticky-container">
    <h2 class="precision-text">Precision</h2>
  </div>
</section>
  1. CSS样式
.precision-section {
  min-height: 200vh;
}
.sticky-container {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
.precision-text span {
  display: inline-block;
  font-size: 8rem;
  font-weight: bold;
  color: #fff;
  transition: color 0.3s ease;
}
.precision-text span.colored {
  color: rgb(211, 188, 141);
}
  1. JavaScript逻辑
// 自动拆分字母为span元素
const textEl = document.querySelector('.precision-text');
const letters = textEl.textContent.split('').map(letter => {
  const span = document.createElement('span');
  span.textContent = letter;
  return span;
});
textEl.innerHTML = '';
letters.forEach(span => textEl.appendChild(span));

const stickyContainer = document.querySelector('.sticky-container');
const section = document.querySelector('.precision-section');
const totalLetters = letters.length;

window.addEventListener('scroll', () => {
  requestAnimationFrame(() => {
    const sectionTop = section.offsetTop;
    const sectionHeight = section.offsetHeight;
    const scrollY = window.scrollY;
    const progress = Math.min(1, Math.max(0, (scrollY - sectionTop) / (sectionHeight - window.innerHeight)));

    // 计算需要变色的字母数量,批量切换类名
    const coloredCount = Math.floor(progress * totalLetters);
    letters.forEach((letter, index) => {
      letter.classList.toggle('colored', index < coloredCount);
    });

    // 完成变色后取消粘性定位
    stickyContainer.style.position = progress === 1 ? 'static' : 'sticky';
  });
});

关键细节优化

  • 滚动事件用requestAnimationFrame包裹,避免频繁触发导致的卡顿;
  • 粘性定位取消也可通过切换类名实现(比如添加non-sticky类,设置position: static),更符合CSS模块化规范;
  • 滚动进度计算需确保在目标区块的滚动范围内完成动画,避免超出边界。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 01:08:13