如何实现自定义可编辑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
相关产品推荐
相关产品推荐

