HTML CSS JavaScript Image Compressor Tool

Large images take up more storage space and slow down websites. An Image Compressor reduces file size while maintaining quality. This makes sharing, uploading, and storing images much easier.

HTML CSS JavaScript Image Compressor

What is an Image Compressor?

An Image Compressor is a tool that reduces the file size of images by compressing data. It helps in optimizing images for faster loading times and better performance.

Why Compress Images?

Using an Image Compressor has several benefits:

  • Faster Website Load Time: Compressed images improve site speed.
  • Reduced Storage Space: Smaller files take up less disk space.
  • Better Performance: Optimized images improve user experience.
  • Improved SEO Ranking: Google ranks faster websites higher.

How Does Image Compression Work?

An Image Compressor reduces file size by:

  • Removing unnecessary metadata from images.
  • Compressing pixels without affecting image quality.
  • Using advanced compression methods like lossless and lossy compression.

Here is Sample

Compress images without losing quality

📁

Drag & Drop your image here

or click to browse files (JPG, PNG, WEBP)

Compression Quality 80%

Image Compression Results

Original Image
Original
Size: 0 KB
Dimensions: 0 x 0
Compressed Image
Compressed
Size: 0 KB
Dimensions: 0 x 0
Download Compressed Image
Original Size
0 KB
Compressed Size
0 KB
Space Saved
0%

Free Image Compressor Tool

Below is a  image compression tool that users can copy and use:

<style>
    /* Custom CSS with unique class names */
    :root {
      --primary-color: #4361ee;
      --secondary-color: #3a0ca3;
      --accent-color: #f72585;
      --light-color: #f8f9fa;
      --dark-color: #212529;
      --success-color: #4cc9f0;
      --warning-color: #f8961e;
    }


    .app-container {
      min-height: 100vh;
      background: linear-gradient(135deg, #4cc9f0 0%, #4361ee 50%, #3a0ca3 100%);
      display: flex;
      flex-direction: column;
      align-items: center;
      padding: 2rem;
        border-radius: 16px;
    }

    .header-wrapper {
      margin-bottom: 2rem;
      text-align: center;
    }

    .main-title {
      font-size: 3rem;
      color: white;
      margin-bottom: 0.5rem;
      text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
    }

    .sub-title {
      color: var(--light-color);
      font-size: 1.2rem;
      opacity: 0.9;
    }

    .compressor-panel {
      width: 100%;
      max-width: 800px;
      background-color: white;
      border-radius: 16px;
      padding: 2rem;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
      margin-bottom: 2rem;
    }

    .upload-zone {
      border: 3px dashed var(--primary-color);
      border-radius: 12px;
      padding: 3rem 2rem;
      text-align: center;
      margin-bottom: 1.5rem;
      cursor: pointer;
      transition: all 0.3s ease;
      position: relative;
    }

    .upload-zone:hover {
      background-color: rgba(67, 97, 238, 0.05);
      transform: translateY(-5px);
    }

    .upload-icon {
      font-size: 3rem;
      color: var(--primary-color);
      margin-bottom: 1rem;
    }

    .upload-text {
      color: var(--dark-color);
      font-size: 1.2rem;
      margin-bottom: 0.5rem;
    }

    .upload-subtext {
      color: #6c757d;
      font-size: 0.9rem;
    }

    .file-input {
      position: absolute;
      width: 100%;
      height: 100%;
      top: 0;
      left: 0;
      opacity: 0;
      cursor: pointer;
    }

    .option-controls {
      margin-bottom: 1.5rem;
    }

    .slider-container {
      margin-bottom: 1rem;
    }

    .slider-label {
      display: flex;
      justify-content: space-between;
      color: var(--dark-color);
      font-weight: 600;
      margin-bottom: 0.5rem;
    }

    .quality-value {
      color: var(--primary-color);
      font-weight: bold;
    }

    .quality-slider {
      width: 100%;
      -webkit-appearance: none;
      height: 8px;
      border-radius: 4px;
      background: linear-gradient(to right, var(--success-color), var(--warning-color));
      outline: none;
    }

    .quality-slider::-webkit-slider-thumb {
      -webkit-appearance: none;
      appearance: none;
      width: 20px;
      height: 20px;
      border-radius: 50%;
      background: var(--primary-color);
      cursor: pointer;
      box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
      transition: all 0.2s;
    }

    .quality-slider::-webkit-slider-thumb:hover {
      transform: scale(1.2);
    }

    .action-button {
      display: block;
      width: 100%;
      padding: 1rem;
      border: none;
      border-radius: 8px;
      background-color: var(--accent-color);
      color: white;
      font-size: 1.1rem;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.3s ease;
      margin-bottom: 1rem;
    }

    .action-button:hover {
      background-color: #e5177b;
      transform: translateY(-2px);
      box-shadow: 0 5px 15px rgba(247, 37, 133, 0.3);
    }

    .action-button:disabled {
      background-color: #cccccc;
      cursor: not-allowed;
      transform: none;
      box-shadow: none;
    }

    .preview-section {
      display: none;
      margin-top: 2rem;
    }

    .preview-title {
      font-size: 1.5rem;
      color: var(--dark-color);
      margin-bottom: 1rem;
      text-align: center;
    }

    .preview-container {
      display: flex;
      flex-wrap: wrap;
      justify-content: space-between;
      gap: 1rem;
    }

    .preview-box {
      flex: 1;
      min-width: 300px;
      border-radius: 8px;
      overflow: hidden;
      box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
    }

    .preview-header {
      background-color: var(--primary-color);
      color: white;
      padding: 0.7rem;
      text-align: center;
      font-weight: 600;
    }

    .preview-img-container {
      height: 250px;
      overflow: hidden;
      display: flex;
      align-items: center;
      justify-content: center;
      background-color: #f8f9fa;
    }

    .preview-img {
      max-width: 100%;
      max-height: 100%;
      object-fit: contain;
    }

    .preview-info {
      padding: 1rem;
      background-color: white;
      color: var(--dark-color);
    }

    .file-info {
      display: flex;
      justify-content: space-between;
      margin-bottom: 0.5rem;
    }

    .info-label {
      font-weight: 600;
    }

    .info-value {
      color: var(--primary-color);
    }

    .download-btn {
      display: block;
      width: 100%;
      padding: 0.7rem;
      border: none;
      border-radius: 6px;
      background-color: var(--success-color);
      color: white;
      font-size: 1rem;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.3s ease;
      text-align: center;
      text-decoration: none;
      margin-top: 1rem;
    }

    .download-btn:hover {
      background-color: #3db8e0;
      transform: translateY(-2px);
      box-shadow: 0 5px 15px rgba(76, 201, 240, 0.3);
    }

    .compression-stats {
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 1rem;
      margin-top: 1.5rem;
      padding: 1rem;
      background-color: rgba(255, 255, 255, 0.9);
      border-radius: 8px;
      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
    }

    .stat-box {
      flex: 1;
      text-align: center;
      padding: 1rem;
      border-radius: 8px;
      background-color: white;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
    }

    .stat-title {
      font-size: 0.9rem;
      color: #6c757d;
    }

    .stat-value {
      font-size: 1.5rem;
      font-weight: 700;
      color: var(--primary-color);
      margin: 0.5rem 0;
    }

    .stat-box.savings {
      background-color: rgba(76, 201, 240, 0.1);
    }

    .loading-overlay {
      display: none;
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: rgba(0, 0, 0, 0.5);
      z-index: 999;
      justify-content: center;
      align-items: center;
    }

    .spinner {
      width: 50px;
      height: 50px;
      border: 5px solid rgba(255, 255, 255, 0.3);
      border-radius: 50%;
      border-top-color: var(--accent-color);
      animation: spin 1s ease-in-out infinite;
    }

    @keyframes spin {
      to { transform: rotate(360deg); }
    }

    .footer-text {
      margin-top: 2rem;
      color: white;
      text-align: center;
      opacity: 0.7;
    }

    @media (max-width: 768px) {
      .compressor-panel {
        padding: 1.5rem;
      }

      .preview-container {
        flex-direction: column;
      }

      .main-title {
        font-size: 2.2rem;
      }
    }
  </style>

  <div class="app-container">
    <div class="header-wrapper">
    
      <p class="sub-title">Compress images without losing quality</p>
    </div>

    <div class="compressor-panel">
      <div class="upload-zone" id="uploadZone">
        <div class="upload-icon">📁</div>
        <p class="upload-text">Drag & Drop your image here</p>
        <p class="upload-subtext">or click to browse files (JPG, PNG, WEBP)</p>
        <input type="file" class="file-input" id="fileInput" accept="image/*" />
      </div>

      <div class="option-controls">
        <div class="slider-container">
          <div class="slider-label">
            <span>Compression Quality</span>
            <span class="quality-value" id="qualityValue">80%</span>
          </div>
          <input type="range" min="1" max="100" value="80" class="quality-slider" id="qualitySlider">
        </div>
      </div>

      <button class="action-button" id="compressBtn" disabled>Compress Image</button>
    </div>

    <div class="preview-section" id="previewSection">
      <h2 class="preview-title">Image Compression Results</h2>
      
      <div class="preview-container">
        <div class="preview-box">
          <div class="preview-header">Original Image</div>
          <div class="preview-img-container">
            <img src="" alt="Original" class="preview-img" id="originalImg">
          </div>
          <div class="preview-info">
            <div class="file-info">
              <span class="info-label">Size:</span>
              <span class="info-value" id="originalSize">0 KB</span>
            </div>
            <div class="file-info">
              <span class="info-label">Dimensions:</span>
              <span class="info-value" id="originalDimensions">0 x 0</span>
            </div>
          </div>
        </div>

        <div class="preview-box">
          <div class="preview-header">Compressed Image</div>
          <div class="preview-img-container">
            <img src="" alt="Compressed" class="preview-img" id="compressedImg">
          </div>
          <div class="preview-info">
            <div class="file-info">
              <span class="info-label">Size:</span>
              <span class="info-value" id="compressedSize">0 KB</span>
            </div>
            <div class="file-info">
              <span class="info-label">Dimensions:</span>
              <span class="info-value" id="compressedDimensions">0 x 0</span>
            </div>
            <a href="#" class="download-btn" id="downloadBtn">Download Compressed Image</a>
          </div>
        </div>
      </div>

      <div class="compression-stats">
        <div class="stat-box">
          <div class="stat-title">Original Size</div>
          <div class="stat-value" id="statsOriginalSize">0 KB</div>
        </div>
        <div class="stat-box">
          <div class="stat-title">Compressed Size</div>
          <div class="stat-value" id="statsCompressedSize">0 KB</div>
        </div>
        <div class="stat-box savings">
          <div class="stat-title">Space Saved</div>
          <div class="stat-value" id="statsSaved">0%</div>
        </div>
      </div>
    </div>

    <p class="footer-text">Compress images privately & securely in your browser</p>
  </div>

  <div class="loading-overlay" id="loadingOverlay">
    <div class="spinner"></div>
  </div>

  <script>
    document.addEventListener('DOMContentLoaded', () => {
      // DOM Elements
      const fileInput = document.getElementById('fileInput');
      const uploadZone = document.getElementById('uploadZone');
      const compressBtn = document.getElementById('compressBtn');
      const qualitySlider = document.getElementById('qualitySlider');
      const qualityValue = document.getElementById('qualityValue');
      const previewSection = document.getElementById('previewSection');
      const originalImg = document.getElementById('originalImg');
      const compressedImg = document.getElementById('compressedImg');
      const originalSize = document.getElementById('originalSize');
      const compressedSize = document.getElementById('compressedSize');
      const originalDimensions = document.getElementById('originalDimensions');
      const compressedDimensions = document.getElementById('compressedDimensions');
      const downloadBtn = document.getElementById('downloadBtn');
      const loadingOverlay = document.getElementById('loadingOverlay');
      const statsOriginalSize = document.getElementById('statsOriginalSize');
      const statsCompressedSize = document.getElementById('statsCompressedSize');
      const statsSaved = document.getElementById('statsSaved');

      // Variables
      let selectedFile = null;
      let originalSizeBytes = 0;
      let compressedSizeBytes = 0;

      // Update quality value when slider changes
      qualitySlider.addEventListener('input', () => {
        qualityValue.textContent = `${qualitySlider.value}%`;
      });

      // Handle file selection
      fileInput.addEventListener('change', handleFileSelect);

      // Handle drag and drop
      uploadZone.addEventListener('dragover', (e) => {
        e.preventDefault();
        uploadZone.style.borderColor = '#f72585';
        uploadZone.style.backgroundColor = 'rgba(247, 37, 133, 0.05)';
      });

      uploadZone.addEventListener('dragleave', (e) => {
        e.preventDefault();
        uploadZone.style.borderColor = '#4361ee';
        uploadZone.style.backgroundColor = '';
      });

      uploadZone.addEventListener('drop', (e) => {
        e.preventDefault();
        uploadZone.style.borderColor = '#4361ee';
        uploadZone.style.backgroundColor = '';
        
        if (e.dataTransfer.files.length) {
          fileInput.files = e.dataTransfer.files;
          handleFileSelect(e);
        }
      });

      // Compress button click handler
      compressBtn.addEventListener('click', compressImage);

      // Format bytes to human-readable size
      function formatBytes(bytes, decimals = 2) {
        if (bytes === 0) return '0 Bytes';
        
        const k = 1024;
        const dm = decimals < 0 ? 0 : decimals;
        const sizes = ['Bytes', 'KB', 'MB', 'GB'];
        
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        
        return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
      }

      // Handle file selection
      function handleFileSelect(e) {
        const file = e.target.files[0] || e.dataTransfer.files[0];
        
        if (!file) return;
        
        // Check if file is an image
        if (!file.type.match('image.*')) {
          alert('Please select an image file (JPG, PNG, or WEBP)');
          return;
        }
        
        selectedFile = file;
        originalSizeBytes = file.size;
        originalSize.textContent = formatBytes(originalSizeBytes);
        statsOriginalSize.textContent = formatBytes(originalSizeBytes);
        
        const reader = new FileReader();
        
        reader.onload = (e) => {
          originalImg.src = e.target.result;
          
          // Get image dimensions
          const img = new Image();
          img.onload = () => {
            originalDimensions.textContent = `${img.width} x ${img.height}`;
          };
          img.src = e.target.result;
        };
        
        reader.readAsDataURL(file);
        compressBtn.disabled = false;
      }

      // Compress image
      function compressImage() {
        if (!selectedFile) return;
        
        loadingOverlay.style.display = 'flex';
        
        const quality = parseInt(qualitySlider.value) / 100;
        const reader = new FileReader();
        
        reader.onload = (e) => {
          const img = new Image();
          
          img.onload = () => {
            // Create canvas
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            
            // Set dimensions
            canvas.width = img.width;
            canvas.height = img.height;
            
            // Draw image on canvas
            ctx.drawImage(img, 0, 0, img.width, img.height);
            
            // Get compressed image
            let mimeType = selectedFile.type || 'image/jpeg';
            const compressedDataUrl = canvas.toDataURL(mimeType, quality);
            
            // Display compressed image
            compressedImg.src = compressedDataUrl;
            compressedDimensions.textContent = `${img.width} x ${img.height}`;
            
            // Calculate compressed size
            let byteString;
            if (compressedDataUrl.split(',')[0].indexOf('base64') >= 0) {
              byteString = atob(compressedDataUrl.split(',')[1]);
            } else {
              byteString = unescape(compressedDataUrl.split(',')[1]);
            }
            
            // Calculate compressed size and savings
            compressedSizeBytes = byteString.length;
            compressedSize.textContent = formatBytes(compressedSizeBytes);
            statsCompressedSize.textContent = formatBytes(compressedSizeBytes);
            
            const savingPercentage = ((originalSizeBytes - compressedSizeBytes) / originalSizeBytes * 100).toFixed(1);
            statsSaved.textContent = `${savingPercentage}%`;
            
            // Set download link
            downloadBtn.href = compressedDataUrl;
            downloadBtn.download = `compressed_${selectedFile.name}`;
            
            // Show preview section
            previewSection.style.display = 'block';
            
            // Hide loading overlay
            loadingOverlay.style.display = 'none';
          };
          
          img.src = e.target.result;
        };
        
        reader.readAsDataURL(selectedFile);
      }
    });
  </script>

This is a basic structure. A fully functional image compressor requires a backend to process file compression.

Conclusion

Using an Image Compressor is essential for optimizing images for websites, social media, and storage. It helps in reducing file size while maintaining quality, making images more efficient for use. Try an online tool or integrate a server-based solution for better compression results.

Previous Post