htmlviewer.html (2)
htmlviewer.html (2)
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-
scale=1.0, user-scalable=no">
<title>Image Compressor Pro | Free Online Tool</title>
<meta name="description" content="Free online tool to compress and resize images
without losing quality. Works completely in your browser - no server upload
needed.">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-
awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary: #4f46e5;
--primary-light: #6366f1;
--dark: #1e293b;
--light: #f8fafc;
--gray: #94a3b8;
--border-radius: 12px;
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0,
0.06);
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
html, body {
touch-action: manipulation;
overflow-x: hidden;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
background-color: #f1f5f9;
color: var(--dark);
line-height: 1.5;
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* Header/Navigation */
header {
background-color: white;
box-shadow: var(--shadow);
position: sticky;
top: 0;
z-index: 100;
}
nav {
max-width: 1200px;
margin: 0 auto;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
font-size: 1.5rem;
font-weight: 700;
color: var(--primary);
text-decoration: none;
display: flex;
align-items: center;
gap: 0.5rem;
}
.logo i {
font-size: 1.8rem;
}
/* Hero Section */
.hero {
text-align: center;
padding: 4rem 2rem;
background: linear-gradient(135deg, #f5f7ff 0%, #e2e8ff 100%);
}
.hero h1 {
font-size: 2.5rem;
margin-bottom: 1rem;
color: var(--primary);
}
.hero p {
font-size: 1.2rem;
color: var(--dark);
max-width: 700px;
margin: 0 auto 2rem;
}
.card {
background: white;
border-radius: var(--border-radius);
box-shadow: var(--shadow);
padding: 2rem;
margin-bottom: 2rem;
}
/* Upload Area */
.upload-area {
border: 2px dashed #cbd5e1;
border-radius: var(--border-radius);
padding: 2.5rem 1rem;
text-align: center;
cursor: pointer;
transition: var(--transition);
margin-bottom: 1.5rem;
position: relative;
}
.upload-area:hover {
border-color: var(--primary-light);
background-color: rgba(99, 102, 241, 0.03);
}
.upload-area.highlight {
border-color: var(--primary);
background-color: rgba(79, 70, 229, 0.05);
}
.upload-icon {
font-size: 2.5rem;
color: var(--primary-light);
margin-bottom: 1rem;
}
.upload-text {
font-weight: 600;
margin-bottom: 0.5rem;
}
.upload-hint {
color: var(--gray);
font-size: 0.875rem;
}
#fileInput {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
opacity: 0;
cursor: pointer;
}
/* Controls */
.controls {
display: none;
animation: fadeIn 0.4s ease-out;
}
.control-group {
margin-bottom: 1.5rem;
}
.slider-container {
margin-top: 0.5rem;
}
.slider-header {
display: flex;
justify-content: space-between;
margin-bottom: 0.5rem;
}
.slider-label {
font-weight: 500;
font-size: 0.9375rem;
}
.slider-value {
font-weight: 600;
color: var(--primary);
}
.range-slider {
width: 100%;
height: 6px;
-webkit-appearance: none;
appearance: none;
background: #e2e8f0;
border-radius: 3px;
outline: none;
touch-action: none;
}
.range-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 18px;
height: 18px;
background: var(--primary);
border-radius: 50%;
cursor: pointer;
transition: var(--transition);
}
.range-slider::-webkit-slider-thumb:hover {
transform: scale(1.15);
background: var(--primary-light);
}
/* Preview Section */
.preview-container {
display: none;
margin-top: 1.5rem;
animation: fadeIn 0.4s ease-out;
}
.preview-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
.preview-title {
font-weight: 600;
font-size: 1.125rem;
}
.preview-frame {
border-radius: var(--border-radius);
overflow: hidden;
box-shadow: var(--shadow);
margin-bottom: 1.5rem;
background: #f8fafc;
display: flex;
justify-content: center;
align-items: center;
height: 300px; /* Fixed height for preview */
border: 1px solid #e2e8f0;
position: relative;
}
#previewCanvas {
max-width: 100%;
max-height: 100%;
width: auto;
height: auto;
display: block;
object-fit: contain;
}
.file-info {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.info-card {
background: #f8fafc;
border-radius: 8px;
padding: 1rem;
text-align: center;
border: 1px solid #e2e8f0;
}
.info-label {
font-size: 0.8125rem;
color: var(--gray);
margin-bottom: 0.25rem;
}
.info-value {
font-weight: 600;
color: var(--dark);
font-size: 0.9375rem;
}
/* Buttons */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
background: var(--primary);
color: white;
padding: 0.75rem 1.25rem;
border-radius: 8px;
text-decoration: none;
font-weight: 500;
border: none;
cursor: pointer;
transition: var(--transition);
width: 100%;
font-size: 1rem;
}
.btn:hover {
background: var(--primary-light);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(79, 70, 229, 0.2);
}
.btn i {
margin-right: 8px;
}
#downloadBtn {
display: none;
}
/* Spinner */
.spinner {
display: none;
width: 2.5rem;
height: 2.5rem;
margin: 1rem auto;
border: 3px solid rgba(79, 70, 229, 0.1);
border-radius: 50%;
border-top-color: var(--primary);
animation: spin 1s linear infinite;
}
/* Features Section */
.features {
max-width: 1200px;
margin: 4rem auto;
padding: 0 2rem;
}
.features h2 {
text-align: center;
font-size: 2rem;
margin-bottom: 2rem;
color: var(--primary);
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.feature-card {
background: white;
border-radius: var(--border-radius);
padding: 2rem;
box-shadow: var(--shadow);
text-align: center;
}
.feature-icon {
font-size: 2.5rem;
color: var(--primary);
margin-bottom: 1rem;
}
.feature-card h3 {
margin-bottom: 1rem;
color: var(--dark);
}
/* Footer */
footer {
background: var(--dark);
color: white;
text-align: center;
padding: 2rem;
margin-top: auto;
}
.footer-content {
max-width: 1200px;
margin: 0 auto;
}
.footer-links {
display: flex;
justify-content: center;
gap: 2rem;
margin: 1rem 0;
}
.footer-links a {
color: white;
text-decoration: none;
transition: var(--transition);
}
.footer-links a:hover {
color: var(--primary-light);
}
.copyright {
color: var(--gray);
font-size: 0.875rem;
}
/* Animations */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes spin {
to { transform: rotate(360deg); }
}
/* Responsive adjustments */
@media (max-width: 768px) {
.hero h1 {
font-size: 2rem;
}
.hero p {
font-size: 1rem;
}
.card {
padding: 1.5rem;
}
.features-grid {
grid-template-columns: 1fr;
}
.preview-frame {
height: 250px; /* Slightly smaller on mobile */
}
}
.hero {
padding: 3rem 1rem;
}
.container {
padding: 0 1rem;
}
.upload-area {
padding: 2rem 1rem;
}
.file-info {
grid-template-columns: 1fr;
}
.footer-links {
flex-direction: column;
gap: 1rem;
}
.preview-frame {
height: 200px; /* Even smaller on very small devices */
}
}
</style>
</head>
<body>
<!-- Header with Navigation -->
<header>
<nav>
<a href="#" class="logo">
<i class="fas fa-compress-alt"></i>
<span>ImageCompressor Pro</span>
</a>
</nav>
</header>
<div class="preview-frame">
<canvas id="previewCanvas"></canvas>
</div>
<div class="file-info">
<div class="info-card">
<div class="info-label">Original Dimensions</div>
<div class="info-value" id="originalDimensions">-</div>
</div>
<div class="info-card">
<div class="info-label">New Dimensions</div>
<div class="info-value" id="newDimensions">-</div>
</div>
<div class="info-card">
<div class="info-label">Size Reduction</div>
<div class="info-value" id="reductionValue">-</div>
</div>
</div>
</div>
<script>
// DOM Elements
const uploadArea = document.getElementById('uploadArea');
const fileInput = document.getElementById('fileInput');
const spinner = document.getElementById('spinner');
const controls = document.getElementById('controls');
const previewContainer = document.getElementById('previewContainer');
const previewCanvas = document.getElementById('previewCanvas');
const previewCtx = previewCanvas.getContext('2d');
const qualitySlider = document.getElementById('qualitySlider');
const qualityValue = document.getElementById('qualityValue');
const originalDimensions = document.getElementById('originalDimensions');
const newDimensions = document.getElementById('newDimensions');
const reductionValue = document.getElementById('reductionValue');
const fileSizeValue = document.getElementById('fileSizeValue');
const downloadBtn = document.getElementById('downloadBtn');
// Variables
let originalImage = new Image();
let originalWidth = 0;
let originalHeight = 0;
let originalSize = 0;
let processing = false;
// Initialize
initEventListeners();
function initEventListeners() {
// File input handling
fileInput.addEventListener('change', handleFileSelect);
// Download button
downloadBtn.addEventListener('click', downloadImage);
function handleFileSelect(event) {
const file = event.target.files[0];
if (!file || !file.type.match('image.*')) return;
startProcessing();
originalSize = file.size;
const reader = new FileReader();
reader.onload = function(e) {
originalImage.onload = function() {
originalWidth = originalImage.naturalWidth;
originalHeight = originalImage.naturalHeight;
reader.readAsDataURL(file);
}
// Only update download URL on final processing (not during live updates)
if (updateDownload) {
// Create a temporary canvas for the actual download
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
tempCanvas.width = newWidth;
tempCanvas.height = newHeight;
tempCtx.drawImage(originalImage, 0, 0, newWidth, newHeight);
// Update UI
fileSizeValue.textContent = `${sizeInKB.toFixed(1)} KB`;
const reduction = ((originalSize / 1024 - sizeInKB) / (originalSize / 1024)
* 100).toFixed(1);
reductionValue.textContent = `${reduction}%`;
}
}
function handleSliderInput() {
const quality = qualitySlider.value;
qualityValue.textContent = `${quality}%`;
function handleSliderChange() {
if (!processing) {
processing = true;
setTimeout(() => {
// Final processing with download URL update
processImage(true);
processing = false;
}, 100);
}
}
function downloadImage() {
const dataUrl = downloadBtn.getAttribute('data-url');
if (!dataUrl) return;
function handleDragLeave() {
uploadArea.classList.remove('highlight');
}
function handleDrop(e) {
e.preventDefault();
uploadArea.classList.remove('highlight');
if (e.dataTransfer.files.length) {
fileInput.files = e.dataTransfer.files;
handleFileSelect({ target: fileInput });
}
}
function finishProcessing() {
processing = false;
spinner.style.display = 'none';
controls.style.display = 'block';
previewContainer.style.display = 'block';
downloadBtn.style.display = 'flex';
}
</script>
</body>
</html>