Summary

Step-by-step guide to building a responsive URL encoder/decoder tool using HTML, CSS (Tailwind), and JavaScript. Learn encoding/decoding techniques with complete code examples.

Article Body

How to Create a URL Encoder/Decoder Tool with HTML, CSS & JavaScript
How to Create a URL Encoder/Decoder Tool with HTML, CSS & JavaScript

How to Create a URL Encoder/Decoder Tool with HTML, CSS & JavaScript

URL encoding and decoding are essential skills for web developers. In this tutorial, we'll build a responsive, user-friendly URL encoder/decoder tool using HTML, CSS (with Tailwind), and vanilla JavaScript.

Step 1: Set Up the HTML Structure

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>URL Encoder/Decoder</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body class="bg-gray-100 min-h-screen flex items-center justify-center p-4">
    <div class="max-w-3xl w-full bg-white rounded-xl shadow-lg overflow-hidden">
        <!-- Tool content will go here -->
    </div>
</body>
</html>

Step 2: Create the Header Section

Add this inside the main div:

<div class="p-6 bg-gradient-to-r from-blue-600 to-blue-800 text-white">
    <h1 class="text-2xl font-bold">URL Encoder/Decoder</h1>
    <p class="opacity-90">Encode or decode URLs and strings for web applications</p>
</div>

Step 3: Build the Input/Output Text Areas

<div class="p-6 space-y-6">
    <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
        <div>
            <label for="input-text" class="block text-sm font-medium text-gray-700 mb-1">Input Text</label>
            <textarea 
                id="input-text" 
                rows="5" 
                class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition font-mono" 
                placeholder="Enter text to encode or decode"
            ></textarea>
        </div>
        <div>
            <label for="output-text" class="block text-sm font-medium text-gray-700 mb-1">Result</label>
            <textarea 
                id="output-text" 
                rows="5" 
                class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition font-mono bg-gray-50" 
                placeholder="Encoded or decoded result will appear here" 
                readonly
            ></textarea>
        </div>
    </div>

Step 4: Add Function Buttons

<div class="grid grid-cols-2 md:grid-cols-4 gap-3">
    <button 
        id="encode-btn" 
        class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition flex items-center justify-center"
    >
        <i class="fas fa-lock mr-2"></i> Encode URL
    </button>
    <button 
        id="decode-btn" 
        class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition flex items-center justify-center"
    >
        <i class="fas fa-lock-open mr-2"></i> Decode URL
    </button>
    <button 
        id="encode-component-btn" 
        class="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 transition flex items-center justify-center"
    >
        <i class="fas fa-code mr-2"></i> Encode Component
    </button>
    <button 
        id="decode-component-btn" 
        class="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 transition flex items-center justify-center"
    >
        <i class="fas fa-file-code mr-2"></i> Decode Component
    </button>
</div>

Step 5: Add Utility Buttons

<div class="flex flex-wrap gap-3 justify-between">
    <button 
        id="copy-btn" 
        class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 transition flex items-center"
        disabled
    >
        <i class="fas fa-copy mr-2"></i> Copy Result
    </button>
    <button 
        id="clear-btn" 
        class="px-4 py-2 bg-red-100 text-red-700 rounded-lg hover:bg-red-200 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 transition flex items-center"
    >
        <i class="fas fa-trash-alt mr-2"></i> Clear All
    </button>
    <button 
        id="test-url-btn" 
        class="px-4 py-2 bg-purple-100 text-purple-700 rounded-lg hover:bg-purple-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transition flex items-center"
        disabled
    >
        <i class="fas fa-external-link-alt mr-2"></i> Test URL
    </button>
</div>

Step 6: Add Information Section

<div class="bg-gray-50 px-6 py-4 border-t border-gray-200">
    <h3 class="font-medium text-gray-700 mb-2">About URL Encoding</h3>
    <div class="text-sm text-gray-600 space-y-2">
        <p><strong>URL Encoding</strong> converts characters into a format that can be transmitted over the Internet. Only alphanumerics and these special characters are allowed: <code class="bg-gray-200 px-1 rounded">- _ . ~</code></p>
        <p><strong>encodeURI()</strong> - Encodes a complete URL (doesn't encode: <code class="bg-gray-200 px-1 rounded">;,/?:@&=+$#</code>)</p>
        <p><strong>encodeURIComponent()</strong> - Encodes a URI component (encodes more characters)</p>
    </div>
</div>

Step 7: Add the JavaScript Functionality

<script>
    document.addEventListener('DOMContentLoaded', function() {
        // Get all DOM elements
        const inputText = document.getElementById('input-text');
        const outputText = document.getElementById('output-text');
        const encodeBtn = document.getElementById('encode-btn');
        const decodeBtn = document.getElementById('decode-btn');
        const encodeComponentBtn = document.getElementById('encode-component-btn');
        const decodeComponentBtn = document.getElementById('decode-component-btn');
        const copyBtn = document.getElementById('copy-btn');
        const clearBtn = document.getElementById('clear-btn');
        const testUrlBtn = document.getElementById('test-url-btn');
        const notification = document.getElementById('notification');

        // Button event listeners
        encodeBtn.addEventListener('click', () => {
            try {
                outputText.value = encodeURI(inputText.value);
                updateButtonStates();
                showNotification('URL encoded successfully!');
            } catch (e) {
                showNotification('Error encoding URL: ' + e.message, false);
            }
        });

        decodeBtn.addEventListener('click', () => {
            try {
                outputText.value = decodeURI(inputText.value);
                updateButtonStates();
                showNotification('URL decoded successfully!');
            } catch (e) {
                showNotification('Error decoding URL: ' + e.message, false);
            }
        });

        encodeComponentBtn.addEventListener('click', () => {
            try {
                outputText.value = encodeURIComponent(inputText.value);
                updateButtonStates();
                showNotification('URI component encoded successfully!');
            } catch (e) {
                showNotification('Error encoding component: ' + e.message, false);
            }
        });

        decodeComponentBtn.addEventListener('click', () => {
            try {
                outputText.value = decodeURIComponent(inputText.value);
                updateButtonStates();
                showNotification('URI component decoded successfully!');
            } catch (e) {
                showNotification('Error decoding component: ' + e.message, false);
            }
        });

        copyBtn.addEventListener('click', () => {
            if (outputText.value) {
                navigator.clipboard.writeText(outputText.value).then(() => {
                    showNotification('Copied to clipboard!');
                }).catch(err => {
                    showNotification('Failed to copy: ' + err, false);
                });
            }
        });

        clearBtn.addEventListener('click', () => {
            inputText.value = '';
            outputText.value = '';
            updateButtonStates();
            showNotification('Cleared all fields!');
        });

        testUrlBtn.addEventListener('click', () => {
            if (outputText.value) {
                try {
                    if (/^https?:\/\//i.test(outputText.value) || /^[a-z]+:\/\//i.test(outputText.value)) {
                        window.open(outputText.value, '_blank');
                    } else {
                        showNotification('This doesn\'t appear to be a complete URL', false);
                    }
                } catch (e) {
                    showNotification('Error testing URL: ' + e.message, false);
                }
            }
        });

        // Input event to enable/disable buttons
        inputText.addEventListener('input', updateButtonStates);
        outputText.addEventListener('input', updateButtonStates);

        function updateButtonStates() {
            const hasInput = inputText.value.trim() !== '';
            const hasOutput = outputText.value.trim() !== '';
            
            encodeBtn.disabled = !hasInput;
            decodeBtn.disabled = !hasInput;
            encodeComponentBtn.disabled = !hasInput;
            decodeComponentBtn.disabled = !hasInput;
            copyBtn.disabled = !hasOutput;
            
            testUrlBtn.disabled = !hasOutput || !(/^[a-z]+:/i.test(outputText.value));
        }

        function showNotification(message, isSuccess = true) {
            notification.textContent = message;
            notification.className = 'fixed top-4 right-4 p-4 rounded-lg shadow-lg transition-opacity duration-300';
            
            if (isSuccess) {
                notification.classList.add('bg-green-100', 'border-green-400', 'text-green-700');
            } else {
                notification.classList.add('bg-red-100', 'border-red-400', 'text-red-700');
            }
            
            notification.classList.remove('hidden');
            
            setTimeout(() => {
                notification.classList.add('hidden');
            }, 3000);
        }
    });
</script>

Step 8: Add Notification Element

<div id="notification" class="hidden fixed top-4 right-4 p-4 bg-green-100 border border-green-400 text-green-700 rounded-lg shadow-lg transition-opacity duration-300"></div>

 

TOPICS MENTIONED IN THIS ARTICLE

About the Author(s)

  • ttimesnow photo

    ttimesnow

    ttimesnow – Author, Curator, and Analyst at [ttimesnow]

    ttimesnow is an experienced journalist with a passion for uncovering the latest trends and breaking news in technology, politics, and culture. ttimesnow combines deep research with a unique perspective to deliver insightful, well-rounded articles that keep readers informed and engaged. At [ttimesnow], ttimesnow curates daily content that brings the world’s most relevant news right to your fingertips.

    View all articles by ttimesnow