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

如何实现自定义可编辑div:将输入字符逐个包裹在<span>中

实现带字符级样式的可编辑打字区域

要实现每个输入字符被<span>包裹的可编辑区域,替代原生<textarea>以支持自定义样式,这里提供一套完整的实现方案,包含输入拦截、字符包裹、样式控制和过渡效果:

核心代码实现

HTML 结构

<div class="typableCustomDiv" contenteditable="true"></div>

CSS 样式

.typableCustomDiv {
  width: 600px;
  min-height: 150px;
  padding: 12px;
  border: 1px solid #ccc;
  font-size: 18px;
  line-height: 1.6;
  outline: none;
  font-family: monospace;
}

.typableCustomDiv span {
  transition: opacity 0.25s ease-in-out;
  opacity: 0;
}

.typableCustomDiv span.visible {
  opacity: 1;
}

.typableCustomDiv span.correct {
  color: #2ecc71;
  font-weight: 500;
}

.typableCustomDiv span.incorrect {
  color: #e74c3c;
  text-decoration: line-through;
}

JavaScript 逻辑

const typableDiv = document.querySelector('.typableCustomDiv');

// 拦截键盘输入,手动处理字符插入
typableDiv.addEventListener('keydown', (e) => {
  // 只处理可打印字符(字母、数字、空格等)和退格键
  const isPrintableChar = (e.key.length === 1 && e.key !== ' ') || e.key === ' ';
  if (isPrintableChar) {
    e.preventDefault();
    const charSpan = document.createElement('span');
    charSpan.textContent = e.key;
    
    // 插入后触发渐显效果
    setTimeout(() => {
      charSpan.classList.add('visible');
    }, 10);
    
    // 可根据目标文本对比结果,动态添加correct/incorrect类
    // charSpan.classList.add('correct'); // 或 incorrect
    typableDiv.appendChild(charSpan);
  } else if (e.key === 'Backspace') {
    e.preventDefault();
    // 删除最后一个span元素
    const lastSpan = typableDiv.lastElementChild;
    if (lastSpan) {
      typableDiv.removeChild(lastSpan);
    }
  }
});

// 禁止粘贴纯文本,避免直接插入未包裹的字符
typableDiv.addEventListener('paste', (e) => {
  e.preventDefault();
  const pastedText = e.clipboardData.getData('text');
  pastedText.split('').forEach(char => {
    const charSpan = document.createElement('span');
    charSpan.textContent = char;
    setTimeout(() => {
      charSpan.classList.add('visible');
    }, 10);
    // 同样可在这里添加样式类
    typableDiv.appendChild(charSpan);
  });
});

关键功能说明

  • 可编辑区域配置:通过contenteditable="true"让<div>具备编辑能力,同时禁用默认outline、设置等宽字体保证字符对齐。
  • 字符包裹逻辑:拦截keydown事件的可打印字符输入,手动创建<span>元素插入到div中,阻止默认输入行为避免生成未包裹的文本节点。
  • 样式控制:通过.correct和.incorrect类实现正确字符绿色高亮、错误字符红色删除线的效果,可在插入字符时根据目标文本对比结果动态添加对应的类。
  • 渐显过渡效果:给每个<span>设置opacity过渡动画,初始隐藏,插入后延迟添加.visible类触发渐显效果,符合0.25秒的过渡要求。
  • 粘贴处理:拦截粘贴事件,将粘贴的文本拆分为单个字符并逐个包裹成<span>,保证输入内容的一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 08:13:40