HTML Minifier|HTML 压缩工具

HTML Minifier|HTML 压缩工具

HTML 压缩工具 HTML Minifier

去除多余空白与注释,快速压缩 HTML 体积,便于线上发布与传输。
Remove unnecessary whitespaces and comments to reduce HTML size for faster delivery and cleaner deployments.

1. 输入内容与压缩选项 · Input & Options

小提示:如果你是要压缩 WordPress 模板或主题片段,建议先在本地测试渲染是否正常。
Tip: If you minify HTML used by templates/themes, test locally first to make sure formatting and scripts still work.

压缩规则 / Minification Rules 安全优先 · Safety first

说明:本工具以“常见安全压缩”为目标:默认不改动 <pre> / <textarea> / <code> 等“保留空白”的区域。
Note: This tool aims for safe minification and avoids touching whitespace-sensitive blocks such as <pre>, <textarea>, and <code>.

3. 使用说明 · Notes
  • 典型用途 · Typical Use Cases
    中文: 发布静态页面、落地页、邮件模板、站点小工具页面时,先压缩 HTML,减少体积与加载时间。
    English: Minify HTML for static pages, landing pages, email templates, and small web tools to reduce payload and improve load time.
  • 关于“注释移除” · About Removing Comments
    中文: 常规注释(<!– comment –>)一般可以安全移除;但某些老旧兼容写法(条件注释)可能仍有用,因此默认提供“保留条件注释”。
    English: Regular HTML comments can usually be removed safely. However, legacy IE conditional comments may still be used in some old templates, so we provide an option to keep them.
  • 关于“空白折叠” · About Collapsing Whitespace
    中文: 多数情况下,HTML 渲染会把多个空格视为一个空格,因此折叠空白能显著减小体积。但在 <pre> 等标签中空白有意义,本工具会自动保护这些区域。
    English: Browsers usually collapse multiple spaces into one, so whitespace collapsing can reduce size. But whitespace inside <pre> (and similar tags) is meaningful, and this tool automatically preserves it.
  • 关于“标签间空白移除” · About Removing Inter-tag Whitespace
    中文:> \n \t < 变为 ><,通常能进一步压缩;但如果你的布局依赖“换行/空格”作为视觉间距(常见于 inline-block),可能导致样式变化。
    English: Removing whitespace between tags often helps reduce size further, but it may affect layouts that rely on whitespace as visual gaps (commonly with inline-block elements).
  • 脚本与样式 · Script & Style
    中文: 本工具默认“保护 script/style 内容”,避免用简单空白规则误伤 JS/CSS(尤其是正则、字符串、模板字面量等)。如果你想进一步压缩 JS/CSS,建议使用专业的 JS/CSS minifier。
    English: By default, we preserve contents inside <script>/<style> to avoid breaking JS/CSS. For deeper minification, use dedicated JS/CSS minifiers.
  • 安全提示 · Safety Tip
    中文: 如果你要压缩来自第三方或不确定来源的 HTML,请先检查是否含有可疑脚本;本工具只做文本处理,不会为你“检测恶意代码”。
    English: If the HTML is from an untrusted source, review it for suspicious scripts first. This tool only minifies text and does not detect malware.

免责声明:本工具仅用于格式压缩与学习参考,不对压缩后页面在特定浏览器/框架中的兼容性作保证。
Disclaimer: This tool is for minification and learning only. Compatibility depends on your environment and browser/framework behaviors.

`; document.getElementById('html-input').value = demo; showSuccess('已加载示例。Example loaded.'); document.getElementById('results-card').style.display = 'none'; } function clearAll() { document.getElementById('html-input').value = ''; document.getElementById('html-output').value = ''; document.getElementById('results-card').style.display = 'none'; document.getElementById('copy-pill').style.display = 'none'; showError(''); showSuccess(''); } function escapeRegExp(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } // Extract blocks we should preserve as-is: // pre, textarea, code, script, style (optional for script/style) function extractPreserveBlocks(html, preserveScriptStyle) { const blocks = []; const tags = preserveScriptStyle ? ['pre', 'textarea', 'code', 'script', 'style'] : ['pre', 'textarea', 'code']; let out = html; // Extract using a cautious pattern: ... // This is not a full HTML parser, but good enough for practical snippets. tags.forEach((tag) => { const re = new RegExp(`<${tag}(\\s[^>]*)?>[\\s\\S]*?<\\/${tag}>`, 'gi'); out = out.replace(re, (m) => { const token = `__WX_PRESERVE_${tag.toUpperCase()}_${blocks.length}__`; blocks.push({ token, value: m }); return token; }); }); return { html: out, blocks }; } function restorePreserveBlocks(html, blocks) { let out = html; for (const b of blocks) { out = out.replaceAll(b.token, b.value); } return out; } function isConditionalComment(fullMatch) { // Keep patterns like // and also ... const s = (fullMatch || '').toLowerCase(); return s.startsWith('/g, (m) => { if (keepConditional && isConditionalComment(m)) return m; return ''; }); } function collapseWhitespace(html) { // Collapse runs of whitespace to a single space. // (Preserved blocks already extracted.) return html.replace(/\s+/g, ' '); } function removeWhitespaceBetweenTags(html) { // > < => >< return html.replace(/>\s+<'); } function minifyHTML() { showError(''); showSuccess(''); document.getElementById('copy-pill').style.display = 'none'; const input = document.getElementById('html-input').value || ''; if (!input.trim()) { showError('❌ 请输入需要压缩的 HTML 内容。Please paste some HTML to minify.'); return; } const optRemoveComments = document.getElementById('opt-remove-comments').checked; const optKeepConditional = document.getElementById('opt-keep-conditional').checked; const optCollapseWhitespace = document.getElementById('opt-collapse-whitespace').checked; const optRemoveIntertag = document.getElementById('opt-remove-intertag').checked; const optTrim = document.getElementById('opt-trim').checked; const optPreserveScriptStyle = document.getElementById('opt-preserve-script-style').checked; // Extract preserve blocks first const extracted = extractPreserveBlocks(input, optPreserveScriptStyle); let work = extracted.html; // Minify operations if (optRemoveComments) { work = removeHtmlComments(work, optKeepConditional); } if (optCollapseWhitespace) { work = collapseWhitespace(work); } if (optRemoveIntertag) { work = removeWhitespaceBetweenTags(work); } if (optTrim) { work = work.trim(); } // Restore preserved blocks const output = restorePreserveBlocks(work, extracted.blocks); // Stats const b1 = bytesOfUtf8(input); const b2 = bytesOfUtf8(output); const saved = b1 - b2; const ratio = b1 > 0 ? (saved / b1) : 0; document.getElementById('stat-original').textContent = formatBytes(b1); document.getElementById('stat-minified').textContent = formatBytes(b2); document.getElementById('stat-reduction').textContent = (saved >= 0 ? ('-' + (ratio * 100).toFixed(2) + '%') : '+0.00%'); document.getElementById('html-output').value = output; document.getElementById('results-card').style.display = 'block'; // Hint let hints = []; if (optRemoveComments) hints.push('已移除注释 / comments removed'); if (optCollapseWhitespace) hints.push('已折叠空白 / whitespace collapsed'); if (optRemoveIntertag) hints.push('已去除标签间空白 / inter-tag whitespace removed'); if (optPreserveScriptStyle) hints.push('已保护 script/style / preserved script/style'); document.getElementById('result-hint').textContent = `压缩完成:${hints.length ? hints.join(',') : '使用默认输出'}。` + `建议:将结果复制到你的项目中后,打开页面做一次快速回归测试(字体、间距、脚本是否正常)。` + ` Done. Tip: paste into your project and do a quick regression check (spacing/scripts).`; showSuccess('✅ 压缩完成。Minification completed.'); } async function copyOutput() { const out = document.getElementById('html-output').value || ''; if (!out.trim()) { showError('❌ 没有可复制的内容。No output to copy.'); return; } try { await navigator.clipboard.writeText(out); const pill = document.getElementById('copy-pill'); pill.style.display = 'inline-flex'; setTimeout(() => { pill.style.display = 'none'; }, 1400); showSuccess('已复制到剪贴板。Copied to clipboard.'); } catch (e) { // Fallback const ta = document.getElementById('html-output'); ta.focus(); ta.select(); try { document.execCommand('copy'); const pill = document.getElementById('copy-pill'); pill.style.display = 'inline-flex'; setTimeout(() => { pill.style.display = 'none'; }, 1400); showSuccess('已复制到剪贴板(兼容模式)。Copied (fallback mode).'); } catch (err) { showError('❌ 复制失败:浏览器可能禁止剪贴板访问。Copy failed: clipboard permission denied.'); } } } function downloadOutput() { const out = document.getElementById('html-output').value || ''; if (!out.trim()) { showError('❌ 没有可下载的内容。No output to download.'); return; } const blob = new Blob([out], { type: 'text/html;charset=utf-8' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'minified.html'; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url); showSuccess('已开始下载 minified.html。Download started.'); } // Optional: load example by default for first-time体验 // loadExample();