已有基础代码,如何高亮输入文本与目标字符串的不匹配字符?
Got it, let's tackle this problem properly—instead of just red-bordering the whole input when there's a mismatch, we can highlight the exact characters that don't match the target string. The main catch here is that <textarea> doesn't let us style individual characters directly, so we need a small workaround to make this work. Here's a step-by-step solution:
We'll use an overlay setup: a transparent textarea for user input, paired with a div below it that displays the highlighted text. This way, users type into the textarea but see the styled content underneath.
<div class="input-container"> <textarea class="js-textarea" placeholder="Type the target text here..."></textarea> <div class="js-highlight-container"></div> </div>
Make sure both elements perfectly overlap, with the textarea transparent (but keeping the cursor visible) so users interact with it while seeing the highlighted content below:
.input-container { position: relative; width: 450px; height: 180px; } .js-textarea, .js-highlight-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; padding: 10px; font-family: monospace; /* Monospace ensures perfect character alignment */ font-size: 14px; line-height: 1.6; border: 1px solid #ddd; border-radius: 4px; white-space: pre-wrap; word-wrap: break-word; } .js-textarea { background: transparent; color: transparent; caret-color: #222; /* Keep the cursor visible */ z-index: 1; /* Ensure textarea receives input focus */ } .js-highlight-container { z-index: 0; pointer-events: none; /* Prevent the div from interfering with input */ } .highlight-red { background-color: #ffecec; color: #dc3545; }
Replace your existing code with this logic to compare characters one by one and generate the highlighted content in real time:
const targetString = "The quick brown fox jumps over the lazy dog"; const textarea = document.querySelector(".js-textarea"); const highlightContainer = document.querySelector(".js-highlight-container"); // Listen for real-time input changes textarea.addEventListener("input", updateHighlight); function updateHighlight() { const inputValue = textarea.value; let highlightedContent = ""; // Compare each character position between target and input for (let i = 0; i < Math.max(targetString.length, inputValue.length); i++) { const targetChar = targetString[i] || ""; const inputChar = inputValue[i] || ""; // Wrap mismatched characters in a highlighted span if (targetChar !== inputChar) { highlightedContent += `<span class="highlight-red">${escapeHTML(inputChar)}</span>`; } else { highlightedContent += escapeHTML(inputChar); } } // Update the highlight container with styled content highlightContainer.innerHTML = highlightedContent; } // Helper function to escape HTML special characters (prevents formatting issues/XSS) function escapeHTML(text) { return text .replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, """) .replace(/'/g, "'"); }
If users edit text in the middle of the input, the cursor might shift slightly. Add this tweak to save and restore the cursor position after updating highlights:
function updateHighlight() { // Save current cursor position const cursorStart = textarea.selectionStart; const cursorEnd = textarea.selectionEnd; // ... keep the character comparison logic here ... highlightContainer.innerHTML = highlightedContent; // Restore cursor position textarea.selectionStart = cursorStart; textarea.selectionEnd = cursorEnd; }
This setup gives you precise, per-character highlighting for mismatches while keeping the input experience smooth and familiar.
内容的提问来源于stack exchange,提问作者Mike L.

