如何实时改变输入框中特定文字的颜色?<color=red>example</color>无效时的实现方案
输入框内部分文字实时变色的实现方案(替代
<color>标签无效场景) 普通<input>/<textarea>属于纯文本控件,无法直接解析渲染HTML标签,因此<color=red>example</color>这类写法不会生效。以下是两种实用的替代实现方案:
方案一:用contenteditable元素模拟输入框,实时解析标记替换样式
通过设置contenteditable="true"的<div>模拟输入框,监听输入事件解析自定义标记,将对应内容替换为带样式的<span>。
实现代码
<div id="editable" contenteditable="true" style="border:1px solid #ccc; padding:8px; min-height:100px;"></div>
const editable = document.getElementById('editable'); let lastContent = ''; editable.addEventListener('input', () => { if (editable.innerHTML === lastContent) return; const content = editable.textContent; // 匹配<color=颜色值>文本</color>格式 const colorRegex = /<color=([^>]+)>([^<]+)<\/color>/g; const parsedHtml = content.replace(colorRegex, (_, color, text) => { // 过滤非法颜色值,避免XSS风险 const safeColor = /^#[0-9a-fA-F]{3,6}$|^rgb\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\)$|^[a-zA-Z]+$/.test(color) ? color : 'inherit'; return `<span style="color:${safeColor}">${text}</span>`; }); // 保存并恢复光标位置,避免替换后光标错位 const selection = window.getSelection(); const range = selection.getRangeAt(0); const offset = range.startOffset; lastContent = parsedHtml; editable.innerHTML = parsedHtml; const textNode = editable.firstChild; if (textNode) { range.setStart(textNode, offset); selection.removeAllRanges(); selection.addRange(range); } });
注意事项
- 必须处理光标位置,避免替换HTML后光标跳转到输入框末尾
- 要过滤非法颜色值,防止XSS注入(限制为十六进制、RGB值或合法颜色名称)
- 可扩展支持其他自定义样式标记(如
<bold>文本</bold>)
方案二:原生textarea + 高亮层叠加(保留原生输入体验)
如果需要保留textarea的原生输入特性(比如回车换行、退格逻辑),可以采用透明textarea + 同步高亮层的方案:用户在透明textarea输入,上层用div展示解析后的高亮内容,两者样式完全对齐。
实现代码
<div class="input-wrapper"> <textarea id="textInput" style="position:absolute; top:0; left:0; width:100%; height:100%; border:1px solid #ccc; padding:8px; font:14px monospace; color:transparent; background:transparent; caret-color:#333;"></textarea> <div id="highlightLayer" style="position:absolute; top:0; left:0; width:100%; height:100%; border:1px solid #ccc; padding:8px; font:14px monospace; pointer-events:none; white-space:pre-wrap; word-wrap:break-word;"></div> </div>
.input-wrapper { position: relative; width: 500px; height: 150px; }
const textInput = document.getElementById('textInput'); const highlightLayer = document.getElementById('highlightLayer'); // 同步输入内容与高亮显示 textInput.addEventListener('input', syncHighlight); // 同步滚动位置 textInput.addEventListener('scroll', () => { highlightLayer.scrollTop = textInput.scrollTop; highlightLayer.scrollLeft = textInput.scrollLeft; }); function syncHighlight() { const rawContent = textInput.value; // 先转义特殊字符,避免原生HTML解析干扰 const escapedContent = rawContent.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); // 解析color标记并替换为高亮span const colorRegex = /<color=([^>]+)>([^<]+)<\/color>/g; const highlightedContent = escapedContent.replace(colorRegex, (_, color, text) => { const safeColor = /^#[0-9a-fA-F]{3,6}$|^rgb\(\d{1,3},\s*\d{1,3},\s*\d{1,3}\)$|^[a-zA-Z]+$/.test(color) ? color : 'inherit'; return `<span style="color:${safeColor}">${text}</span>`; }); highlightLayer.innerHTML = highlightedContent; } // 初始化高亮 syncHighlight();
优势
- 完全保留原生textarea的输入体验,无需额外处理光标、换行等逻辑
- 高亮层仅做展示,用户输入的原始内容不受影响,安全性更高
- 适配性强,支持所有textarea的原生特性
内容的提问来源于stack exchange,提问作者SOOBATON
相关产品推荐
相关产品推荐

