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

如何实时改变输入框中特定文字的颜色?<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, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  // 解析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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 08:38:49