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

CSS/JS打字动画覆盖字体颜色问题求助

解决打字动画丢失原有文本样式的问题

问题根源

你的代码出现样式丢失的核心原因有三个:

  • 用textContent获取内容会剥离所有HTML标签,导致<font color="blue">这类样式节点被丢弃
  • 重新生成的统一span元素强制设置了color属性,覆盖了原有文本的样式
  • 用占位&nbsp实现初始状态的方式复杂,且容易破坏原始布局

修复方案

核心思路是保留原始HTML结构,仅对文本节点做动画处理,用CSS伪元素实现闪烁光标,以下是完整修复代码:

1. 添加CSS光标样式

用伪元素实现闪烁光标,替代原来的占位span:

.css-typing.overlay {
  position: relative;
}
.css-typing.overlay::after {
  content: "";
  position: absolute;
  top: 0;
  right: -8px;
  width: 2px;
  height: 100%;
  background-color: currentColor;
  animation: blink 1s infinite;
}
@keyframes blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}

2. 修改JavaScript逻辑

重新编写JS,保留原始HTML结构,逐个处理节点实现动画:

// 选择所有目标元素
const elements = document.querySelectorAll('.css-typing');

if (elements.length > 0) {
  elements.forEach(el => {
    // 保存原始HTML内容,用于重置
    const originalHTML = el.innerHTML;
    // 初始添加overlay类显示光标
    el.classList.add('overlay');

    // 启动打字动画
    function startTyping() {
      el.classList.remove('overlay');
      el.innerHTML = '';
      
      // 递归处理节点:文本节点做动画,元素节点保留样式
      const processNodes = (nodes) => {
        nodes.forEach((node, nodeIndex) => {
          if (node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== '') {
            // 拆分文本节点的每个字符,逐个添加动画
            const chars = node.textContent.split('');
            chars.forEach((char, charIndex) => {
              const span = document.createElement('span');
              span.textContent = char;
              span.style.opacity = '0';
              el.appendChild(span);
              
              // 延迟渐入,累计节点和字符的索引保证顺序
              setTimeout(() => {
                span.style.transition = 'opacity 0.1s ease';
                span.style.opacity = '1';
              }, (nodeIndex * 100) + (charIndex * 100));
            });
          } else if (node.nodeType === Node.ELEMENT_NODE) {
            // 克隆元素节点,保留原有样式
            const clonedNode = node.cloneNode(true);
            el.appendChild(clonedNode);
            // 递归处理子节点
            processNodes(Array.from(clonedNode.childNodes));
          }
        });
      };

      // 临时容器解析原始HTML,获取节点列表
      const tempContainer = document.createElement('div');
      tempContainer.innerHTML = originalHTML;
      processNodes(Array.from(tempContainer.childNodes));

      // 移除鼠标进入事件,防止重复触发动画
      el.removeEventListener('mouseenter', startTyping);
    }

    // 重置为初始状态
    function resetState() {
      el.innerHTML = originalHTML;
      el.classList.add('overlay');
      el.addEventListener('mouseenter', startTyping);
    }

    // 绑定事件监听
    el.addEventListener('mouseenter', startTyping);
    el.addEventListener('mouseleave', resetState);
  });
} else {
  console.log('未找到带有css-typing类的元素');
}

3. 最终HTML结构

直接使用你原来的HTML,嵌入CSS和JS即可:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>
.css-typing.overlay {
  position: relative;
}
.css-typing.overlay::after {
  content: "";
  position: absolute;
  top: 0;
  right: -8px;
  width: 2px;
  height: 100%;
  background-color: currentColor;
  animation: blink 1s infinite;
}
@keyframes blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}
</style>
<span class="css-typing">lorem ipsum <font color="blue">target</font> dolor</span>

关键改进点

  • 保留原始样式:使用innerHTML保存原始HTML,避免textContent剥离标签
  • 节点差异化处理:文本节点拆分做动画,元素节点直接克隆保留原有样式
  • CSS光标实现:伪元素光标不占用布局空间,动画更流畅
  • 逻辑简化:用原生JS替代jQuery动画,减少依赖同时提升性能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 01:00:57