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

React+Tailwind中如何为输入框指定文本后的内容设置蓝色样式?

解决方案:React + Tailwind 实现输入框指定文本高亮

首先明确核心问题:input 是浏览器的替换元素,无法通过 :before/:after 伪元素修改内容或样式,这就是你尝试 after 伪元素无效的原因。下面提供两种可行的实现方案:


方案1:用 contenteditable 模拟输入框(适合简单场景)

通过可编辑的 div 替代原生 input,直接拆分文本并给目标部分套上蓝色样式的 span:

import { useState } from 'react';

function HighlightEditableInput() {
  const [text, setText] = useState('a<>b<>c<>');

  const handleInput = (e) => {
    setText(e.target.textContent);
  };

  // 处理文本高亮逻辑:拆分<>,将后续部分(含<>)设为蓝色
  const renderHighlightedContent = () => {
    const parts = text.split('<>');
    if (parts.length <= 1) return <span>{text}</span>;

    return (
      <>
        <span>{parts[0]}</span>
        {parts.slice(1).map((part, idx) => (
          <span key={idx} className="text-blue-500">
            &lt;&gt;{part}
          </span>
        ))}
        {/* 补全末尾的<>(如果输入以<>结尾) */}
        {text.endsWith('<>') && <span className="text-blue-500">&lt;&gt;</span>}
      </>
    );
  };

  return (
    <div
      contentEditable
      onInput={handleInput}
      className="border border-gray-300 p-2 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
      dangerouslySetInnerHTML={{ __html: renderHighlightedContent().props.children }}
    />
  );
}

export default HighlightEditableInput;

如果只需要高亮b<>c<>(不含前后的<>),只需修改 span 里的内容为{part}&lt;&gt;即可。


方案2:原生 input + 叠加显示层(接近原生输入体验)

用隐藏的原生 input 负责输入逻辑,上方叠加一个 span 负责展示高亮样式,同步输入内容和光标位置:

import { useState, useRef, useEffect } from 'react';

function HighlightInputOverlay() {
  const [text, setText] = useState('a<>b<>c<>');
  const inputRef = useRef(null);

  // 同步input值与光标位置
  useEffect(() => {
    if (!inputRef.current) return;
    inputRef.current.value = text;
    
    // 修复光标错位问题
    const selection = window.getSelection();
    if (selection.rangeCount > 0) {
      const range = selection.getRangeAt(0);
      const displaySpan = document.getElementById('highlight-display');
      if (displaySpan && range.commonAncestorContainer === displaySpan) {
        inputRef.current.setSelectionRange(range.startOffset, range.startOffset);
      }
    }
  }, [text]);

  const handleChange = (e) => {
    setText(e.target.value);
  };

  // 生成带高亮的HTML内容
  const getHighlightedHtml = () => {
    const parts = text.split('<>');
    if (parts.length <= 1) return text;

    let html = parts[0];
    parts.slice(1).forEach(part => {
      html += `<span class="text-blue-500">&lt;&gt;${part}</span>`;
    });
    if (text.endsWith('<>')) html += '<span class="text-blue-500">&lt;&gt;</span>';
    return html;
  };

  return (
    <div className="relative w-fit">
      {/* 隐藏的原生input,负责输入 */}
      <input
        ref={inputRef}
        type="text"
        value={text}
        onChange={handleChange}
        className="absolute inset-0 w-full h-full opacity-0 border border-gray-300 p-2 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
      />
      {/* 显示层,负责高亮 */}
      <span
        id="highlight-display"
        className="block border border-gray-300 p-2 rounded min-h-[2.25rem] whitespace-nowrap"
        dangerouslySetInnerHTML={{ __html: getHighlightedHtml() }}
      />
    </div>
  );
}

export default HighlightInputOverlay;

注意事项

  • 使用dangerouslySetInnerHTML时,若涉及用户输入建议搭配DOMPurify做XSS防护;
  • contenteditable方案需自行处理回车、换行等细节,适合纯文本输入场景;
  • 叠加方案更贴近原生input的交互体验,但需要维护光标同步逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:28:33