Have you ever tried to spot the differences between two long paragraphs of text? Reading line-by-line to find a missing word or a new sentence is a massive headache.
In this tutorial, you’ll build your very own browser-based Text Compare Tool. It will take an original piece of text, compare it against a changed version, and instantly highlight exactly what was added or removed.
Building this project will help you level up your JavaScript skills. You’ll also create a tool that’s highly secure, because everything happens locally in the user’s browser. No sensitive data is ever sent to a server.
Let’s get started.
Prerequisites
To follow along easily, you should know:
-
Basic HTML and CSS knowledge: How to structure a page and use Flexbox to put items side-by-side.
-
Basic JavaScript knowledge: How to write functions, use arrays, and listen for button clicks.
-
Your Setup: A code editor (like VS Code) and a web browser to view your work.
Table of Contents
Step 1: Set Up Your Project Files
First, you need a place to store your code. Create a new folder on your computer and name it text-compare-tool.
Inside that folder, create three empty files:
-
index.html(This holds the structure of your app) -
style.css(This makes your app look good) -
script.js(This makes your app actually work)
Step 2: Build the HTML Structure
Open your index.html file. You need to create a simple layout with two large text boxes: one for the original text, and one for the updated text.
Copy and paste this code into your HTML file:
Text Compare Tool
Quickly find every addition and deletion between two versions of your text. Just paste them into our tool, and we’ll show you exactly what’s been changed.
Understanding the HTML:
-
The two panels: Inside the
.panels-wrapper, you have a left side and a right side. -
Textareas vs results: Each side has a
/* Highlight Colors */
--red-bg: #fce8e6;
--red-text: #c5221f;
--green-bg: #e6f4ea;
--green-text: #137333;
}body {
font-family: Arial, sans-serif;
background-color: var(--background-color);
color: var(--text-color);
display: flex;
flex-direction: column;
align-items: center;
padding: 40px 20px;
margin: 0;
}h1 {
margin-bottom: 10px;
}.description {
text-align: center;
max-width: 600px;
color: #5f6368;
margin-bottom: 30px;
line-height: 1.5;
}.container {
background: white;
padding: 20px;
border-radius: 8px;
border: 1px solid var(--border-color);
width: 100%;
max-width: 1000px;
box-shadow: 0 4px 10px rgba(0,0,0,0.05);
}.panels-wrapper {
display: flex;
gap: 20px;
margin-bottom: 20px;
}.panel {
flex: 1;
display: flex;
flex-direction: column;
}textarea, .result-box {
width: 100%;
height: 300px;
padding: 15px;
border: 1px solid var(--border-color);
border-radius: 6px;
font-size: 16px;
line-height: 1.5;
box-sizing: border-box;
resize: vertical;
}textarea:focus {
outline: none;
border-color: var(--primary-blue);
}/* Hidden by default */
.result-box {
display: none;
background-color: #fafafa;
overflow-y: auto;
white-space: pre-wrap;
}.controls {
display: flex;
justify-content: center;
gap: 15px;
}button {
padding: 10px 25px;
font-size: 16px;
font-weight: bold;
border: none;
border-radius: 5px;
cursor: pointer;
}.btn-compare {
background-color: var(--primary-blue);
color: white;
}.btn-clear {
background-color: white;
color: var(--primary-blue);
border: 1px solid var(--border-color);
}/* How the differences will look */
.deleted {
background-color: var(--red-bg);
color: var(--red-text);
padding: 2px 4px;
border-radius: 3px;
}.added {
background-color: var(--green-bg);
color: var(--green-text);
padding: 2px 4px;
border-radius: 3px;
}
</code></pre>
<p>Understanding the CSS:</p>
<ul>
<li><p><strong>Flexbox layout:</strong> <code>display: flex;</code> inside <code>.panels-wrapper</code> is what places your two text boxes neatly side-by-side.</p>
</li>
<li><p><strong>The highlighters:</strong> The <code>.deleted</code> and <code>.added</code> classes are the most important part of the visual design. When a user deletes a word, we give it a soft red background. When they add a word, it gets a soft green background.</p>
</li>
</ul>
<p>This is what your tool will look like once it's finished:</p>
<img src="https://cdn.hashnode.com/uploads/covers/699c7b22cf5def0f6aaf982b/6676b86c-c0ea-4dec-b5b7-489e8e06f58b.png" alt="Text Compare Tool Preview" style="display:block;margin:0 auto" width="1874" height="872" loading="lazy"><h2 id="heading-step-4-write-the-javascript-engine">Step 4: Write the JavaScript Engine</h2>
<p>Now you need to make the tool actually work. How does your computer know if a word has changed?</p>
<p>We have to write logic that breaks paragraphs down into individual words. The code will look at the original list of words and compare it to the new list. If a word from the original text is missing, it gets marked as "deleted." If a brand new word appears, it gets marked as "added."</p>
<p>Open your <code>script.js</code> file and paste in this complete, working code:</p>
<pre><code class="language-javascript">function compareText() {
// 1. Grab the text from the text boxes
const text1 = document.getElementById('text1').value;
const text2 = document.getElementById('text2').value;// 2. Chop the text up into an array of words (and keep the spaces)
const words1 = text1.split(/(\s+)/);
const words2 = text2.split(/(\s+)/);// 3. Find the differences
const { diff1, diff2 } = calculateDifferences(words1, words2);const resultBox1 = document.getElementById('result1');
const resultBox2 = document.getElementById('result2');// 4. Turn those differences into HTML with colors
resultBox1.innerHTML = createColoredHTML(diff1, 'deleted');
resultBox2.innerHTML = createColoredHTML(diff2, 'added');// 5. Hide the text boxes and show the final results
document.getElementById('text1').style.display = 'none';
document.getElementById('text2').style.display = 'none';
resultBox1.style.display = 'block';
resultBox2.style.display = 'block';
}// The engine that compares the two lists of words
function calculateDifferences(arr1, arr2) {
const n = arr1.length;
const m = arr2.length;// Create a grid to keep track of matching words
const grid = Array.from({ length: n + 1 }, () => Array(m + 1).fill(0));for (let i = 1; i <= n; i++) {
for (let j = 1; j <= m; j++) {
if (arr1[i - 1] === arr2[j - 1]) {
grid[i][j] = grid[i - 1][j - 1] + 1;
} else {
grid[i][j] = Math.max(grid[i - 1][j], grid[i][j - 1]);
}
}
}let i = n, j = m;
const diff1 = [];
const diff2 = [];// Walk backwards through the grid to mark what changed
while (i > 0 || j > 0) {
if (i > 0 && j > 0 && arr1[i - 1] === arr2[j - 1]) {
diff1.unshift({ value: arr1[i - 1], type: 'equal' });
diff2.unshift({ value: arr2[j - 1], type: 'equal' });
i--;
j--;
} else if (j > 0 && (i === 0 || grid[i][j - 1] >= grid[i - 1][j])) {
diff2.unshift({ value: arr2[j - 1], type: 'changed' });
j--;
} else if (i > 0 && (j === 0 || grid[i][j - 1] < grid[i - 1][j])) {
diff1.unshift({ value: arr1[i - 1], type: 'changed' });
i--;
}
}return { diff1, diff2 };
}// Packages the text safely into HTML span elements
function createColoredHTML(diffArray, colorClass) {
return diffArray.map(wordItem => {
// Replace dangerous characters so the browser doesn't crash
const safeText = wordItem.value.replace(/</g, "<").replace(/>/g, ">");// If the word was changed (and isn't just a blank space), wrap it in color
if (wordItem.type === 'changed' && !/^\s+$/.test(wordItem.value)) {
return `<span class="${colorClass}">${safeText}</span>`;
}
return safeText;
}).join('');
}// Puts the tool back to its default state
function clearText() {
document.getElementById('text1').value="";
document.getElementById('text2').value="";document.getElementById('text1').style.display = 'block';
document.getElementById('text2').style.display = 'block';document.getElementById('result1').style.display = 'none';
document.getElementById('result2').style.display = 'none';
}
</code></pre>
<p>Understanding the JavaScript:</p>
<ol>
<li><p><strong>Keeping the formatting:</strong> In the first function, you see <code>.split(/(\s+)/)</code>. This splits the text up by spaces, but <em>keeps</em> the spaces and line-breaks. If you don't do this, all of the user's paragraphs will mash into one giant block of text!</p>
</li>
<li><p><strong>The grid system:</strong> The <code>calculateDifferences</code> function creates an invisible grid. It compares every word in the first box with every word in the second box. If it sees the same word in the same order, it leaves it alone. If it hits a snag, it marks the word as a change.</p>
</li>
<li><p><strong>Safety first:</strong> The <code>createColoredHTML</code> function wraps our changed words in <code><span class="added"></code> or <code><span class="deleted"></code> so CSS can color them. But before it does that, it removes any <code><</code> or <code>></code> symbols using <code>.replace()</code>. This stops hackers from pasting malicious code into your app.</p>
</li>
</ol>
<h2 id="heading-step-5-test-your-application">Step 5: Test Your Application</h2>
<p>You're completely done coding! Now it’s time to see it in action.</p>
<ol>
<li><p>Open your <code>text-compare-tool</code> folder.</p>
</li>
<li><p>Double-click the <code>index.html</code> file. It will open in your default web browser.</p>
</li>
<li><p>Type a sentence into the left box: <em>"The quick brown fox jumps over the lazy dog."</em></p>
</li>
<li><p>Type a slightly different sentence into the right box: <em>"The fast brown fox jumps over the sleepy dog."</em></p>
</li>
<li><p>Click <strong>Compare</strong>.</p>
</li>
</ol>
<p>You will instantly see the word "quick" highlight in red on the left, and the word "fast" highlight in green on the right. If you want to start over, just click <strong>Clear</strong>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Great job! You just built a highly practical, browser-based text comparison utility using nothing but pure HTML, CSS, and JavaScript.</p>
<p>You learned how to break text into arrays, compare them using a grid-based algorithm, and manipulate the DOM to show those differences to the user safely. Because this tool relies on local browser processing, it's incredibly fast and 100% private.</p>
<p>If you want to see this exact logic running in a live production environment, or if you need to bookmark a fast tool for your own writing tasks, check out the live <a href="https://99tools.net/text-compare-tool/">Text Compare Tool</a>. Keep experimenting with the code, and happy building!</p></section>
<div class="sidebar">
</div>
</div>
<hr><div class="post-full-author-header" data-test-label="author-header-with-bio">
<section class="author-card" data-test-label="author-card">
<img srcset="https://avatars.githubusercontent.com/u/254470266?v=4 60w" sizes="60px" src="https://avatars.githubusercontent.com/u/254470266?v=4" class="author-profile-image" alt="Bansidhar Kadiya" width="460" height="460" onerror="this.style.display='none'" loading="lazy" data-test-label="profile-image">
<section class="author-card-content ">
<span class="author-card-name">
<a href="https://www.freecodecamp.org/news/author/99tools/" data-test-label="profile-link">Bansidhar Kadiya
</a>
</span><p data-test-label="author-bio">Bansidhar Kadiya is a WordPress Developer and SEO specialist focused on building fast, practical web experiences. He is the creator of 99tools.net, a growing collection of free browser-based utilities designed to help developers, creators, and everyday users complete common tasks quickly and efficiently.</p>
</section>
</section></div>
<hr><p data-test-label="social-row-cta" class="social-row">
If you read this far, thank the author to show them you care. <button id="tweet-btn" class="cta-button" data-test-label="tweet-button">Say Thanks</button>
</p><div class="learn-cta-row" data-test-label="learn-cta-row">
<p>
Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. <a href="https://www.freecodecamp.org/learn" class="cta-button" id="learn-to-code-cta" rel="noopener noreferrer" target="_blank">Get started</a>
</p>
</div></section>
<div class="banner-ad-bottom">
<div class="ad-text" data-test-label="ad-text">ADVERTISEMENT</div>
<div style="display: block; height: auto" id="gam-ad-bottom">
</div></div>
</article>
</div>
</main><footer class="site-footer">
<div class="footer-top">
<div class="footer-desc-col">
<p data-test-label="tax-exempt-status">freeCodeCamp is a donor-supported tax-exempt 501(c)(3) charity organization (United States Federal Tax Identification Number: 82-0779546)</p>
<p data-test-label="mission-statement">Our mission: to help people learn to code for free. We accomplish this by creating thousands of videos, articles, and interactive coding lessons - all freely available to the public.</p>
<p data-test-label="donation-initiatives">Donations to freeCodeCamp go toward our education initiatives, and help pay for servers, services, and staff.</p>
<p class="footer-donation" data-test-label="donate-text">
You can <a href="https://www.freecodecamp.org/donate/" class="inline" rel="noopener noreferrer" target="_blank">make a tax-deductible donation here</a>.
</p>
</div>
<div class="trending-guides" data-test-label="trending-guides">
<h2 id="trending-guides" class="col-header">Trending Books and Handbooks</h2>
<ul class="trending-guides-articles" aria-labelledby="trending-guides">
<li>
<a href="https://www.freecodecamp.org/news/build-consume-and-document-a-rest-api/" rel="noopener noreferrer" target="_blank">REST APIs
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/how-to-write-clean-code/" rel="noopener noreferrer" target="_blank">Clean Code
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/learn-typescript-with-react-handbook/" rel="noopener noreferrer" target="_blank">TypeScript
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/learn-javascript-for-beginners/" rel="noopener noreferrer" target="_blank">JavaScript
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/how-to-build-an-ai-chatbot-with-redis-python-and-gpt/" rel="noopener noreferrer" target="_blank">AI Chatbots
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/command-line-for-beginners/" rel="noopener noreferrer" target="_blank">Command Line
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/building-consuming-and-documenting-a-graphql-api/" rel="noopener noreferrer" target="_blank">GraphQL APIs
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/complete-guide-to-css-transform-functions-and-properties/" rel="noopener noreferrer" target="_blank">CSS Transforms
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/how-to-build-scalable-access-control-for-your-web-app/" rel="noopener noreferrer" target="_blank">Access Control
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/rest-api-design-best-practices-build-a-rest-api/" rel="noopener noreferrer" target="_blank">REST API Design
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/the-php-handbook/" rel="noopener noreferrer" target="_blank">PHP
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/the-java-handbook/" rel="noopener noreferrer" target="_blank">Java
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/learn-linux-for-beginners-book-basic-to-advanced/" rel="noopener noreferrer" target="_blank">Linux
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/react-for-beginners-handbook/" rel="noopener noreferrer" target="_blank">React
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/learn-continuous-integration-delivery-and-deployment/" rel="noopener noreferrer" target="_blank">CI/CD
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/the-docker-handbook/" rel="noopener noreferrer" target="_blank">Docker
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/learn-golang-handbook/" rel="noopener noreferrer" target="_blank">Golang
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/the-python-handbook/" rel="noopener noreferrer" target="_blank">Python
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/get-started-with-nodejs/" rel="noopener noreferrer" target="_blank">Node.js
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/build-crud-operations-with-dotnet-core-handbook/" rel="noopener noreferrer" target="_blank">Todo APIs
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/how-to-use-classes-in-javascript-handbook/" rel="noopener noreferrer" target="_blank">JavaScript Classes
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/front-end-javascript-development-react-angular-vue-compared/" rel="noopener noreferrer" target="_blank">Front-End Libraries
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/the-express-handbook/" rel="noopener noreferrer" target="_blank">Express and Node.js
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/python-code-examples-sample-script-coding-tutorial-for-beginners/" rel="noopener noreferrer" target="_blank">Python Code Examples
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/clustering-in-python-a-machine-learning-handbook/" rel="noopener noreferrer" target="_blank">Clustering in Python
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/an-introduction-to-software-architecture-patterns/" rel="noopener noreferrer" target="_blank">Software Architecture
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/what-is-programming-tutorial-for-beginners/" rel="noopener noreferrer" target="_blank">Programming Fundamentals
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/learn-to-code-book/" rel="noopener noreferrer" target="_blank">Coding Career Preparation
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/become-a-full-stack-developer-and-get-a-job/" rel="noopener noreferrer" target="_blank">Full-Stack Developer Guide
</a>
</li>
<li>
<a href="https://www.freecodecamp.org/news/learn-python-for-javascript-developers-handbook/" rel="noopener noreferrer" target="_blank">Python for JavaScript Devs
</a>
</li>
</ul>
<div class="spacer" style="padding: 15px 0;"></div>
<div>
<h2 id="mobile-app" class="col-header">
Mobile App
</h2>
<div class="min-h-[1px] px-[15px] md:w-2/3 md:ml-[16.6%]">
<ul aria-labelledby="mobile-app" class="mobile-app-container">
<li>
<a href="https://apps.apple.com/us/app/freecodecamp/id6446908151?itsct=apps_box_link&itscg=30200" rel="noopener noreferrer" target="_blank">
<img src="https://cdn.freecodecamp.org/platform/universal/apple-store-badge.svg" lang="en" alt="Download on the App Store">
</a>
</li>
<li>
<a href="https://play.google.com/store/apps/details?id=org.freecodecamp" rel="noopener noreferrer" target="_blank">
<img src="https://cdn.freecodecamp.org/platform/universal/google-play-badge.svg" lang="en" alt="Get it on Google Play">
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="footer-bottom">
<h2 class="col-header" data-test-label="our-nonprofit">Our Charity</h2>
<div class="our-nonprofit"><a href="https://hashnode.com/" rel="noopener noreferrer" target="_blank" data-test-label="powered-by">
Publication powered by Hashnode
</a>
<a href="https://www.freecodecamp.org/news/about/" rel="noopener noreferrer" target="_blank" data-test-label="about">
About
</a>
<a href="https://www.linkedin.com/school/free-code-camp/people/" rel="noopener noreferrer" target="_blank" data-test-label="alumni">
Alumni Network
</a>
<a href="https://github.com/freeCodeCamp/" rel="noopener noreferrer" target="_blank" data-test-label="open-source">
Open Source
</a>
<a href="https://www.freecodecamp.org/news/shop/" rel="noopener noreferrer" target="_blank" data-test-label="shop">
Shop
</a>
<a href="https://www.freecodecamp.org/news/support/" rel="noopener noreferrer" target="_blank" data-test-label="support">
Support
</a>
<a href="https://www.freecodecamp.org/news/sponsors/" rel="noopener noreferrer" target="_blank" data-test-label="sponsors">
Sponsors
</a>
<a href="https://www.freecodecamp.org/news/academic-honesty-policy/" rel="noopener noreferrer" target="_blank" data-test-label="honesty">
Academic Honesty
</a>
<a href="https://www.freecodecamp.org/news/code-of-conduct/" rel="noopener noreferrer" target="_blank" data-test-label="coc">
Code of Conduct
</a>
<a href="https://www.freecodecamp.org/news/privacy-policy/" rel="noopener noreferrer" target="_blank" data-test-label="privacy">
Privacy Policy
</a>
<a href="https://www.freecodecamp.org/news/terms-of-service/" rel="noopener noreferrer" target="_blank" data-test-label="tos">
Terms of Service
</a>
<a href="https://www.freecodecamp.org/news/copyright-policy/" rel="noopener noreferrer" target="_blank" data-test-label="copyright">
Copyright Policy
</a>
</div>
</div>
</footer></div>
</body>
</html>

