Modules
By default the modules should only perform safe transforms, see the module documentation below for details.
You can disable modules by passing false
as option, and enable them by passing true
.
The order in which the modules are documented is also the order in which they are applied.
Attributes
normalizeAttributeValues
- Normalize casing of specific attribute values that are case-insensitive (like
form[method]
,img[img]
andinput[type]
). - Apply invalid value default attribute to invalid attribute values (like
<input type=foo>
to<input type=text>
, which can then be minified to<input>
byremoveRedundantAttributes
module).
Example
Source:
<form method="GET"></form>
Minified:
<form method="get"></form>
removeEmptyAttributes
Removes empty safe-to-remove attributes.
Side effects
This module could break your styles or JS if you use selectors with attributes:
img[style=""] {
margin: 10px;
}
Example
Source:
<img src="foo.jpg" alt="" style="">
Minified:
<img src="foo.jpg" alt="">
collapseAttributeWhitespace
Collapse redundant white spaces in list-like attributes (class
, rel
, ping
).
Example
Source:
<a class=" content page " style=" display: block; " href=" https://example.com"></a>
Minified:
<a class="content page" style="display: block;" href="https://example.com"></a>
removeRedundantAttributes
Removes redundant attributes from tags if they contain default values:
method="get"
from<form>
type="text"
from<input>
type="submit"
from<button>
language="javascript"
andtype="text/javascript"
from<script>
charset
from<script>
if it's an external scriptmedia="all"
from<style>
and<link>
type="text/css"
from<link rel="stylesheet">
Options
This module is disabled by default, change option to true to enable this module.
Side effects
This module could break your styles or JS if you use selectors with attributes:
form[method="get"] {
color: red;
}
Example
Source:
<form method="get">
<input type="text">
</form>
Minified:
<form>
<input>
</form>
collapseBooleanAttributes
- Collapses boolean attributes (like
disabled
) to the minimized form. - Collapses empty string value attributes (like
href=""
) to the minimized form. - Collapses missing value default attributes that are empty strings (
audio[preload=auto]
andvideo[preload=auto]
) to the minimized form.
Options
If your document uses AMP, set the amphtml
flag
to collapse additonal, AMP-specific boolean attributes:
"collapseBooleanAttributes": {
"amphtml": true
}
Side effects
This module could break your styles or JS if you use selectors with attributes:
button[disabled="disabled"] {
color: red;
}
Example
Source:
<button disabled="disabled">click</button>
<script defer=""></script>
<a href=""></a>
<video preload="auto"></video>
Minified:
<button disabled>click</button>
<script defer></script>
<a href></a>
<video preload></video>
deduplicateAttributeValues
Remove duplicate values from list-like attributes (class
, rel
, ping
).
Example
Source:
<div class="sidebar left sidebar"></div>
Minified:
<div class="sidebar left"></div>
minifyUrls
Convert absolute URL to relative URL using relateurl.
You have to install relateurl
, terser
and srcset
in order to use this feature:
npm install --save-dev relateurl terser srcset
# if you prefer yarn
# yarn add --dev relateurl terser srcset
# if you prefer pnpm
# pnpm install --save-dev relateurl terser srcset
Options
The base URL to resolve against. Support String
& URL
.
htmlnano.process(html, {
minifyUrls: 'https://example.com' // Valid configuration
});
htmlnano.process(html, {
minifyUrls: new URL('https://example.com') // Valid configuration
});
htmlnano.process(html, {
minifyUrls: false // The module will be disabled
});
htmlnano.process(html, {
minifyUrls: true // Invalid configuration, the module will be disabled
});
Example
Basic Usage
Configuration:
htmlnano.process(html, {
minifyUrls: 'https://example.com'
});
Source:
<a href="https://example.com/foo/bar/baz">bar</a>
Minified:
<a href="foo/bar/baz">bar</a>
With sub-directory
Configuration:
htmlnano.process(html, {
minifyUrls: 'https://example.com/foo/baz/'
});
Source:
<a href="https://example.com/foo/bar">bar</a>
Minified:
<a href="../bar">bar</a>
sortAttributes
Sort attributes inside elements.
The module won't impact the plain-text size of the output. However it will improve the compression ratio of gzip/brotli used in HTTP compression.
Options
alphabetical
: Default option. Sort attributes in alphabetical order.frequency
: Sort attributes by frequency.
Example
alphabetical
Source:
<input type="text" class="form-control" name="testInput" autofocus="" autocomplete="off" id="testId">
Processed:
<input autocomplete="off" autofocus="" class="form-control" id="testId" name="testInput" type="text">
frequency
Source:
<input type="text" class="form-control" name="testInput" id="testId">
<a id="testId" href="#" class="testClass"></a>
<img width="20" src="../images/image.png" height="40" alt="image" class="cls" id="id2">
Processed:
<input class="form-control" id="testId" type="text" name="testInput">
<a class="testClass" id="testId" href="#"></a>
<img class="cls" id="id2" width="20" src="../images/image.png" height="40" alt="image">
sortAttributesWithLists
Sort values in list-like attributes (class
, rel
, ping
).
The module won't impact the plain-text size of the output. However it will improve the compression ratio of gzip/brotli used in HTTP compression.
Options
alphabetical
: Default option. Sort attribute values in alphabetical order.frequency
: Sort attribute values by frequency.
Example
alphabetical
Source:
<div class="foo baz bar">click</div>
Processed:
<div class="bar baz foo">click</div>
frequency
Source:
<div class="foo baz bar"></div><div class="bar foo"></div>
Processed:
<div class="foo bar baz"></div><div class="foo bar"></div>
Options
conservative
— collapses all redundant white spaces to 1 space (default)aggressive
— collapses all whitespaces that are redundant and safe to removeall
— collapses all redundant white spaces
Side effects
all
<i>hello</i> <i>world</i>
or <i>hello</i><br><i>world</i>
after minification will be rendered as helloworld
.
To prevent that use either the default conservative
option, or the aggressive
option.
Example
Source:
<div>
hello world!
<a href="#">answer</a>
<style>div { color: red; } </style>
<main></main>
</div>
Minified (with all
):
<div>hello world!<a href="#">answer</a><style>div { color: red; } </style><main></main></div>
Minified (with aggressive
):
<div> hello world! <a href="#">answer</a> <style>div { color: red; } </style><main></main></div>
Minified (with conservative
):
<div> hello world! <a href="#">answer</a> <style>div { color: red; } </style> <main></main> </div>
HTML Content
collapseWhitespace
Collapses redundant white spaces (including new lines). It doesn’t affect white spaces in the elements <style>
, <textarea>
, <script>
and <pre>
.
removeComments
Options
safe
– removes all HTML comments except the conditional comments and<!--noindex--><!--/noindex-->
(default)all
— removes all HTML comments- A
RegExp
— only HTML comments matching the given regexp will be removed. - A
Function
that returns boolean — removes HTML comments that can make the given callback function returns truthy value.
Example
Source:
{
removeComments: 'all'
}
<div><!-- test --></div>
Minified:
<div></div>
Source:
{
removeComments: /<!--(\/)?noindex-->/
}
<div><!--noindex-->this text will not be indexed<!--/noindex-->Lorem ipsum dolor sit amet<!--more-->Lorem ipsum dolor sit amet</div>
Minified:
<div>this text will not be indexedLorem ipsum dolor sit amet<!--more-->Lorem ipsum dolor sit amet</div>
Source:
{
removeComments: (comment) => {
if (comment.includes('noindex')) return true;
return false;
}
}
<div><!--noindex-->this text will not be indexed<!--/noindex-->Lorem ipsum dolor sit amet<!--more-->Lorem ipsum dolor sit amet</div>
Minified:
<div>this text will not be indexedLorem ipsum dolor sit amet<!--more-->Lorem ipsum dolor sit amet</div>
removeOptionalTags
Remove certain tags that can be omitted, see HTML Standard - 13.1.2.4 Optional tags.
Example
Source:
<html><head><title>Title</title></head><body><p>Hi</p></body></html>
Minified:
<title>Title</title><p>Hi</p>
Notice
Due to the limitation of PostHTML, htmlnano can't remove only the start tag or the end tag of an element. Currently, htmlnano only supports removing the following optional tags, as htmlnano can remove their start tag and end tag at the same time:
html
head
body
colgroup
tbody
removeOptionalTags
Remove certain tags that can be omitted, see HTML Standard - 13.1.2.4 Optional tags.
Example
Source:
<html><head><title>Title</title></head><body><p>Hi</p></body></html>
Minified:
<title>Title</title><p>Hi</p>
Notice
Due to the limitation of PostHTML, htmlnano can't remove only the start tag or the end tag of an element. Currently, htmlnano only supports removing the following optional tags, as htmlnano can remove their start tag and end tag at the same time:
html
head
body
colgroup
tbody
removeAttributeQuotes
Remove quotes around attributes when possible, see HTML Standard - 12.1.2.3 Attributes - Unquoted attribute value syntax.
Example
Source:
<div class="foo" title="hello world"></div>
Minified:
<div class=foo title="hello world"></div>
Notice
The feature is implemented by posthtml-render's quoteAllAttributes
, which is one of the PostHTML's option. So removeAttributeQuotes
could be overriden by other PostHTML's plugins and PostHTML's configuration.
For example:
posthtml([
htmlnano({
removeAttributeQuotes: true
})
]).process(html, {
quoteAllAttributes: true
})
removeAttributeQuotes
will not work because PostHTML's quoteAllAttributes
takes the priority.
<style>
, <script>
and <svg>
Tags
mergeStyles
Merges multiple <style>
with the same media
and type
into one tag.
<style scoped>...</style>
are skipped.
Example
Source:
<style>h1 { color: red }</style>
<style media="print">div { color: blue }</style>
<style type="text/css" media="print">a {}</style>
<style>div { font-size: 20px }</style>
Minified:
<style>h1 { color: red } div { font-size: 20px }</style>
<style media="print">div { color: blue } a {}</style>
mergeScripts
Merge multiple <script>
with the same attributes (id, class, type, async, defer
) into one (last) tag.
Side effects
It could break your code if the tags with different attributes share the same variable scope. See the example below.
Example
Source:
<script>const foo = 'A:1';</script>
<script class="test">foo = 'B:1';</script>
<script type="text/javascript">foo = 'A:2';</script>
<script defer>foo = 'C:1';</script>
<script>foo = 'A:3';</script>
<script defer="defer">foo = 'C:2';</script>
<script class="test" type="text/javascript">foo = 'B:2';</script>
Minified:
<script>const foo = 'A:1'; foo = 'A:2'; foo = 'A:3';</script>
<script defer="defer">foo = 'C:1'; foo = 'C:2';</script>
<script class="test" type="text/javascript">foo = 'B:1'; foo = 'B:2';</script>
minifyCss
Minifies CSS with cssnano inside <style>
tags and style
attributes.
You have to install cssnano
and postcss
in order to use this feature:
npm install --save-dev cssnano postcss
# if you prefer yarn
# yarn add --dev cssnano postcss
# if you prefer pnpm
# pnpm install --save-dev cssnano postcss
Options
See the documentation of cssnano for all supported optimizations.
By default CSS is minified with preset default
, which shouldn't have any side-effects.
To use another preset or disabled some optimizations pass options to minifyCss
module:
htmlnano.process(html, {
minifyCss: {
preset: ['default', {
discardComments: {
removeAll: true,
},
}]
}
});
Example
Source:
<div>
<style>
h1 {
margin: 10px 10px 10px 10px;
color: #ff0000;
}
</style>
</div>
Minified:
<div>
<style>h1{margin:10px;color:red}</style>
</div>
minifyJs
Minifies JS using Terser inside <script>
tags.
You have to install terser
in order to use this feature:
npm install --save-dev terser
# if you prefer yarn
# yarn add --dev terser
# if you prefer pnpm
# pnpm install --save-dev terser
Options
See the documentation of Terser for all supported options.
Terser options can be passed directly to the minifyJs
module:
htmlnano.process(html, {
minifyJs: {
output: { quote_style: 1 },
},
});
Example
Source:
<div>
<script>
/* comment */
const foo = function () {
};
</script>
</div>
Minified:
<div>
<script>const foo=function(){};</script>
</div>
minifyJson
Minifies JSON inside <script type="application/json"></script>
.
Example
Source:
<script type="application/json">
{
"user": "me"
}
</script>
Minified:
<script type="application/json">{"user":"me"}</script>
minifySvg
Minifies SVG inside <svg>
tags using SVGO.
Options
See the documentation of SVGO for all supported options.
SVGO options can be passed directly to the minifySvg
module:
htmlnano.process(html, {
minifySvg: {
plugins: [
{
name: 'preset-default',
params: {
overrides: {
builtinPluginName: {
optionName: 'optionValue'
},
},
},
}
]
}
});
Example
Source:
<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="red" />
<circle cx="150" cy="100" r="80" fill="green" />
<text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text>
</svg>`
Minified:
<svg baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="red"/><circle cx="150" cy="100" r="80" fill="green"/><text x="150" y="125" font-size="60" text-anchor="middle" fill="#fff">SVG</text></svg>
removeUnusedCss
Removes unused CSS inside <style>
tags with either uncss
or PurgeCSS.
With uncss
You have to install uncss
in order to use this feature:
npm install --save-dev uncss
# if you prefer yarn
# yarn add --dev uncss
# if you prefer pnpm
# pnpm install --save-dev uncss
You can also use a mainted fork @novaatwarren/uncss instead.
Options
See the documentation of uncss for all supported options.
uncss options can be passed directly to the removeUnusedCss
module:
htmlnano.process(html, {
removeUnusedCss: {
ignore: ['.do-not-remove']
}
});
The following uncss options are ignored if passed to the module:
stylesheets
ignoreSheets
raw
With PurgeCSS
Use PurgeCSS instead of uncss by adding tool: 'purgeCSS'
to the options.
You have to install purgecss
in order to use this feature:
npm install --save-dev purgecss
# if you prefer yarn
# yarn add --dev purgecss
# if you prefer pnpm
# pnpm install --save-dev purgecss
Options
See the documentation of PurgeCSS for all supported options.
PurgeCSS options can be passed directly to the removeUnusedCss
module:
htmlnano.process(html, {
removeUnusedCss: {
tool: 'purgeCSS',
safelist: ['.do-not-remove']
}
});
The following PurgeCSS options are ignored if passed to the module:
content
css
extractors
Example
Source:
<div class="b">
<style>
.a {
margin: 10px 10px 10px 10px;
}
.b {
color: #ff0000;
}
</style>
</div>
Optimized:
<div class="b">
<style>
.b {
color: #ff0000;
}
</style>
</div>
Miscellaneous
custom
It's also possible to pass custom modules in the minifier. As a function:
const options = {
custom: function (tree, options) {
// Some minification
return tree;
}
};
Or as a list of functions:
const options = {
custom: [
function (tree, options) {
// Some minification
return tree;
},
function (tree, options) {
// Some other minification
return tree;
}
]
};
htmlnano's options are passed to your custom plugin by the second parameter options
.