
本文介绍一种纯 javascript 实现的“悬停打乱字母”交互效果:当鼠标移入文本元素时,其字符被快速随机重组若干次,最后平滑恢复原始顺序,同时通过 css 技术避免因连字/字距导致的布局抖动。
本文介绍一种纯 javascript 实现的“悬停打乱字母”交互效果:当鼠标移入文本元素时,其字符被快速随机重组若干次,最后平滑恢复原始顺序,同时通过 css 技术避免因连字/字距导致的布局抖动。
这种视觉效果在高端品牌网站(如 Locomotive、TUX)中广泛使用,能显著提升导航或标题的动态感与专业度。与依赖 jQuery 的旧方案不同,现代实现应采用原生 JavaScript,兼顾性能、可维护性与稳定性。
核心挑战在于两点:视觉真实感(每个字母都应充分参与随机置换,而非仅尾部渐进还原)和布局稳定性(避免因 fi 连字或 AV 字距变化引发的宽度跳动)。以下为完整解决方案:
✅ 关键 CSS 重置(防布局抖动)
.shuffle {
font-kerning: none; /* 禁用字距调整 */
font-feature-settings: "liga" 0; /* 禁用连字特性 */
/* 可选:固定字体宽度,进一步保障一致性 */
font-variant-ligatures: none;
}⚠️ 注意:
font-kerning和font-feature-settings需配合支持 OpenType 的字体(如系统 San-serif 或 Google Fonts 中的 Inter、Manrope),否则可能无效。
✅ 原生 JavaScript 动画逻辑
// 配置参数:打乱帧数 & 每帧间隔(ms)
const DURATION = 50;
const FRAMES_MAX = 7;
// 获取所有目标元素
const shuffledEls = document.querySelectorAll(".shuffle");
shuffledEls.forEach(el => {
const originalText = el.textContent;
let animationId = null;
const shuffleArr = (arr) => {
const shuffled = [...arr];
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
}
return shuffled;
};
const startScramble = () => {
let frame = 0;
const charArr = originalText.split("");
animationId = setInterval(() => {
if (frame < FRAMES_MAX) {
el.textContent = shuffleArr(charArr).join("");
frame++;
} else {
clearInterval(animationId);
el.textContent = originalText; // 强制还原,避免残留错位
}
}, DURATION);
};
// 绑定事件
el.addEventListener("mouseenter", startScramble);
el.addEventListener("mouseleave", () => {
clearInterval(animationId);
el.textContent = originalText; // 立即还原,防止状态残留
});
});✅ HTML 使用示例(兼容内联与块级)
<!-- 导航项 --> <nav> <a class="shuffle" href="#careers">Careers</a> <a class="shuffle" href="#work">Work</a> </nav> <!-- 段落内单个词(推荐) --> <p>We’re looking for passionate <span class="shuffle">designers</span> and <span class="shuffle">engineers</span>.</p> <!-- ❌ 不推荐用于长段落 --> <!-- <p class="shuffle">This will cause layout shifts...</p> -->
? 注意事项与优化建议
- 仅对短文本使用:该效果适用于单词或短语(≤12 字符),长文本打乱易造成可读性灾难与性能负担;
-
避免
textContent频繁写入:若需更高性能(如大量元素),可改用innerHTML+<span></span>包裹每个字符,并仅更新innerText; -
响应式适配:结合
vmin单位设置字体大小(如font-size: 4vmin),确保在不同屏幕下保持动画节奏一致; -
无障碍友好:为
.shuffle元素添加aria-live="off",避免屏幕阅读器重复播报打乱过程; -
降级处理:可检测
prefers-reduced-motion并禁用动画:if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) { return; // 跳过初始化 }
此方案轻量(.shuffle 类应用于任意内联元素,即可获得专业级悬停反馈。

















