# Htmlhint > This is the full developer documentation for HTMLHint --- # Htmlhint Documentation Source: https://htmlhint.com/llms-full.txt --- This is the full developer documentation for HTMLHint --- # HTMLHint > The web's most popular static code analysis tool you need for your HTML Configure the rules You can enable or disable [any of the rules](/rules/) and have them customized to fit your needs. Check out the guide to learn how to set up HTMLHint in your project. VS Code Extension Download the HTMLHint extension for Visual Studio Code to get real-time feedback on your HTML code. * [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=HTMLHint.vscode-htmlhint) * [Open VSX Registry](https://open-vsx.org/extension/HTMLHint/vscode-htmlhint) --- # Changelog > The release notes for HTMLHint, see what's changed with each new version. ## 1.8.0 *(2025-11-25)* [Section titled “1.8.0 (2025-11-25)”](#180-2025-11-25) * Feat Add support for disabling rules via HTML comments [#1767](https://github.com/htmlhint/HTMLHint/issues/1767) * Feat Add ‘allow-non-blocking’ option to [`head-script-disabled`](/rules/head-script-disabled/) rule [#1765](https://github.com/htmlhint/HTMLHint/issues/1765) ## 1.7.1 *(2025-09-17)* [Section titled “1.7.1 (2025-09-17)”](#171-2025-09-17) * Fix Update Glob dependency to version 9 ## 1.7.0 *(2025-09-11)* [Section titled “1.7.0 (2025-09-11)”](#170-2025-09-11) * Feat New rule: [`form-method-require`](/rules/form-method-require/) [#1670](https://github.com/htmlhint/HTMLHint/issues/1721) * Feat New rule: [`link-rel-canonical-require`](/rules/link-rel-canonical-require/) [#1671](https://github.com/htmlhint/HTMLHint/issues/1710) ## 1.6.3 *(2025-06-18)* [Section titled “1.6.3 (2025-06-18)”](#163-2025-06-18) * Fix Improve [`attr-value-no-duplication`](/rules/attr-value-no-duplication/) logic ## 1.6.2 *(2025-06-18)* [Section titled “1.6.2 (2025-06-18)”](#162-2025-06-18) * Fix Improve [`attr-value-no-duplication`](/rules/attr-value-no-duplication/) logic ## 1.6.1 *(2025-06-17)* [Section titled “1.6.1 (2025-06-17)”](#161-2025-06-17) * Fix Improve SARIF report formatting * Fix Improve [`attr-value-no-duplication`](/rules/attr-value-no-duplication/) logic ## 1.6.0 *(2025-06-17)* [Section titled “1.6.0 (2025-06-17)”](#160-2025-06-17) * Feat New rule: [`attr-value-no-duplication`](/rules/attr-value-no-duplication/) [#1650](https://github.com/htmlhint/HTMLHint/issues/1650) * Feat New rule: [`tag-no-obsolete`](/rules/tag-no-obsolete/) [#1660](https://github.com/htmlhint/HTMLHint/issues/1660) * Feat Improved SARIF formatter to output help text (useful for [GitHub Code Scanning](/usage/github-code-scanning/)) ## 1.5.1 *(2025-06-07)* [Section titled “1.5.1 (2025-06-07)”](#151-2025-06-07) * Feat Update Node SARIF Builder [#1641](https://github.com/htmlhint/HTMLHint/pull/1641) * Fix Fix SARIF formatter to output a `htmlhint.sarif` file [#1640](https://github.com/htmlhint/HTMLHint/pull/1640) ## 1.5.0 *(2025-06-06)* [Section titled “1.5.0 (2025-06-06)”](#150-2025-06-06) * Feat Add `htmlhint --init` command to create a `.htmlhintrc` file [#1630](https://github.com/htmlhint/HTMLHint/pull/1630) * Feat Add SARIF formatter [#1627](https://github.com/htmlhint/HTMLHint/issues/1627) * Feat New rule: [`frame-title-require`](/rules/frame-title-require/) [#1629](https://github.com/htmlhint/HTMLHint/issues/1629) * Feat New rule: [`meta-charset-require`](/rules/meta-charset-require/) [#1628](https://github.com/htmlhint/HTMLHint/issues/1628) * Fix Improve HTML report formatting (dark mode) [#1621](https://github.com/htmlhint/HTMLHint/issues/1621) * Fix Special character escape in HTML reports [#1626](https://github.com/htmlhint/HTMLHint/issues/1626) ## 1.4.0 *(2025-06-03)* [Section titled “1.4.0 (2025-06-03)”](#140-2025-06-03) * Feat New rule: [`button-type-require`](/rules/button-type-require/) [#1615](https://github.com/htmlhint/HTMLHint/issues/1615) * Feat New rule: [`meta-description-require`](/rules/meta-description-require/) [#1613](https://github.com/htmlhint/HTMLHint/issues/1613) * Feat New rule: [`meta-viewport-require`](/rules/meta-viewport-require/) [#1618](https://github.com/htmlhint/HTMLHint/issues/1618) * Fix Improved HTML Report formatting [#1617](https://github.com/htmlhint/HTMLHint/issues/1617) ## 1.3.0 *(2025-05-31)* [Section titled “1.3.0 (2025-05-31)”](#130-2025-05-31) * Feat New rule: [`main-require`](/rules/main-require/) [#1608](https://github.com/htmlhint/HTMLHint/issues/1608) * Feat New rule: [`h1-require`](/rules/h1-require/) [#1605](https://github.com/htmlhint/HTMLHint/issues/1605) * Feat Sort `data-*` attributes at end [#1591](https://github.com/htmlhint/HTMLHint/issues/1591) * Feat Add `rel` to list of sorted attributes [#1579](https://github.com/htmlhint/HTMLHint/issues/1579) * Fix `npx htmlhint -l` doesn’t list rules alphabetically [#1598](https://github.com/htmlhint/HTMLHint/issues/1598) * Fix `doctype-first` does not account for comments being permitted beforehand [#1610](https://github.com/htmlhint/HTMLHint/issues/1610) ## 1.2.0 *(2025-05-26)* [Section titled “1.2.0 (2025-05-26)”](#120-2025-05-26) * Feat Sort unknown attributes alphabetically [#668](https://github.com/htmlhint/HTMLHint/issues/668) * Feat display warning log message when it can not parse config [#893](https://github.com/htmlhint/HTMLHint/issues/893) * Fix Point `tag-pair` error message to correct line and column [#1503](https://github.com/htmlhint/HTMLHint/issues/1503) * Fix Remove ampersand from `spec-char-escape` [#1504](https://github.com/htmlhint/HTMLHint/issues/1504) * Fix Typo in `idclassaddisabled` default export name [#728](https://github.com/htmlhint/HTMLHint/issues/728) * Docs Switch website to use Astro Starlight ## 1.1.4 *(2022-04-11)* [Section titled “1.1.4 (2022-04-11)”](#114-2022-04-11) * Fix duplicate text [#981](https://github.com/htmlhint/HTMLHint/issues/981) ## 1.1.3 *(2022-03-28)* [Section titled “1.1.3 (2022-03-28)”](#113-2022-03-28) * Feat Replace parse-glob [#927](https://github.com/htmlhint/HTMLHint/issues/927) ## 1.1.2 *(2022-01-27)* [Section titled “1.1.2 (2022-01-27)”](#112-2022-01-27) * Fix Ignore hidden input without label, closes [#866](https://github.com/htmlhint/HTMLHint/issues/866) ## 1.1.1 *(2022-01-23)* [Section titled “1.1.1 (2022-01-23)”](#111-2022-01-23) * Fix Correct links to rule docs, closes [#867](https://github.com/htmlhint/HTMLHint/issues/867) ## 1.1.0 *(2021-12-31)* [Section titled “1.1.0 (2021-12-31)”](#110-2021-12-31) * Fix **attr-lowercase:** ignore camelCase SVG attributes ## 1.0.0 *(2021-11-26)* [Section titled “1.0.0 (2021-11-26)”](#100-2021-11-26) * Feat Set minimum support to es6 * Feat Upgrade to TypeScript 4 * Feat IE11 and older browsers are no longer supported ## 0.16.3 *(2021-11-24)* [Section titled “0.16.3 (2021-11-24)”](#0163-2021-11-24) * Revert “chore(deps-dev): upgrade strip-json-comments ([#763](https://github.com/htmlhint/HTMLHint/pull/763))” ([#767](https://github.com/htmlhint/HTMLHint/pull/767)) ## 0.16.2 *(2021-11-23)* [Section titled “0.16.2 (2021-11-23)”](#0162-2021-11-23) * cleanup non-functional typos [#727](https://github.com/htmlhint/HTMLHint/issues/727) ## 0.16.1 *(2021-11-12)* [Section titled “0.16.1 (2021-11-12)”](#0161-2021-11-12) * tagname-specialchars description [#714](https://github.com/htmlhint/HTMLHint/issues/714) ## 0.16.0 *(2021-10-29)* [Section titled “0.16.0 (2021-10-29)”](#0160-2021-10-29) * **rules:** add `empty-tag-not-self-closed` rule [#696](https://github.com/htmlhint/HTMLHint/issues/696), closes [#311](https://github.com/htmlhint/HTMLHint/issues/311) ## 0.15.2 *(2021-09-16)* [Section titled “0.15.2 (2021-09-16)”](#0152-2021-09-16) * **htmlhint.ts:** replace deprecated request module with what-wg fetch [#670](https://github.com/htmlhint/HTMLHint/issues/670) ## 0.15.1 *(2021-06-11)* [Section titled “0.15.1 (2021-06-11)”](#0151-2021-06-11) * Unexpected behavior of the HTML lang require rule [#655](https://github.com/htmlhint/HTMLHint/issues/655) ## 0.15.0 *(2021-06-10)* [Section titled “0.15.0 (2021-06-10)”](#0150-2021-06-10) * **rules:** add `html-lang-require` rule [#632](https://github.com/htmlhint/HTMLHint/issues/632) ## 0.14.2 *(2020-11-11)* [Section titled “0.14.2 (2020-11-11)”](#0142-2020-11-11) * Link to configuration.md from options page [#563](https://github.com/htmlhint/HTMLHint/issues/563) ## 0.14.1 *(2020-06-25)* [Section titled “0.14.1 (2020-06-25)”](#0141-2020-06-25) * windows path separator [#443](https://github.com/htmlhint/HTMLHint/issues/443) ## 0.14.0 *(2020-05-31)* [Section titled “0.14.0 (2020-05-31)”](#0140-2020-05-31) * use chalk instead of colors [#433](https://github.com/htmlhint/HTMLHint/issues/433) ## 0.13.1 *(2020-05-31)* [Section titled “0.13.1 (2020-05-31)”](#0131-2020-05-31) * add missing branches to action release [#425](https://github.com/htmlhint/HTMLHint/issues/425) * add missing plugins for docusaurus [#402](https://github.com/htmlhint/HTMLHint/issues/402) * correctly call hint queue drain [#409](https://github.com/htmlhint/HTMLHint/issues/409) * duplicate ga [#407](https://github.com/htmlhint/HTMLHint/issues/407) * ESLint fix * fix url repo pkg [#413](https://github.com/htmlhint/HTMLHint/issues/413) * GitHub token * remove unused dependency esm [#430](https://github.com/htmlhint/HTMLHint/issues/430) * **attr-no-unnecessary-whitespace:** fix when equals symbol in value [#405](https://github.com/htmlhint/HTMLHint/issues/405) ## 0.13.1-beta.2 *(2020-05-31)* [Section titled “0.13.1-beta.2 (2020-05-31)”](#0131-beta2-2020-05-31) * remove unused dependency esm [#430](https://github.com/htmlhint/HTMLHint/issues/430) ## 0.13.1-beta.1 *(2020-05-30)* [Section titled “0.13.1-beta.1 (2020-05-30)”](#0131-beta1-2020-05-30) * add missing branches to action release [#425](https://github.com/htmlhint/HTMLHint/issues/425) * add missing plugins for docusaurus [#402](https://github.com/htmlhint/HTMLHint/issues/402) * correctly call hint queue drain [#409](https://github.com/htmlhint/HTMLHint/issues/409) * duplicate ga [#407](https://github.com/htmlhint/HTMLHint/issues/407) * eslint fix * fix url repo pkg [#413](https://github.com/htmlhint/HTMLHint/issues/413) * **attr-no-unnecessary-whitespace:** fix when equals symbol in value [#405](https://github.com/htmlhint/HTMLHint/issues/405) * GitHub token ## 0.13.0 *(2020-05-18)* [Section titled “0.13.0 (2020-05-18)”](#0130-2020-05-18) * add prettier and eslint [#388](https://github.com/htmlhint/HTMLHint/issues/388) * add semantic release test [#399](https://github.com/htmlhint/HTMLHint/issues/399) * ignore `PULL_REQUEST_TEMPLATE.md` * use yml in semantic.yml * Add tags checking rule - allows specify rules for any tag and validate that [#384](https://github.com/htmlhint/HTMLHint/issues/384) * added attr-no-unnecessary-whitespace rule [#385](https://github.com/htmlhint/HTMLHint/issues/385) * new rule: input-requires-label - All inputs require a label [#159](https://github.com/htmlhint/HTMLHint/issues/159) * new website for htmlhint.com [#395](https://github.com/htmlhint/HTMLHint/issues/395) ## 0.9.14 *(2016-5-2)* [Section titled “0.9.14 (2016-5-2)”](#0914-2016-5-2) add: 1. cli: support hint for url 2. attr-lowercase: add test case ## 0.9.13 *(2016-5-1)* [Section titled “0.9.13 (2016-5-1)”](#0913-2016-5-1) add: 1. change cli parameter: `--plugin` to `--rulesdir` 2. add formatter directory support 3. add formatters: compact, markdown 4. add cli parameter:`--nocolor`, disable color in cli 5. space-tab-mixed-disabled plugin: add space length require 6. add empty elements: track,command,source,keygen,wbr 7. add hint stdin for cli fix: 1. report error evidence if tag attrs include `\r\n` 2. space-tab-mixed-disabled issue [#119](https://github.com/htmlhint/HTMLHint/issues/119) 3. attr name support all w3c defined characters improve: 1. Parse inline ruleset after default ruleset ## 0.9.10 *(2015-10-12)* [Section titled “0.9.10 (2015-10-12)”](#0910-2015-10-12) add: 1. attr-unsafe-chars(rule): show unsafe code in message 2. support glob pattern for cli 3. support format as custom: json, junit, checkstyle 4. support plugin: `htmlhint --plugin ./plugins/` 5. add rule: inline-style-disabled 6. add rule: inline-script-disabled fix: 1. title-require(rule): report error when `test` 2. title-require(rule): report error when `` ## 0.9.9 *(2015-10-9)* [Section titled “0.9.9 (2015-10-9)”](#099-2015-10-9) add: 1. add config loaded message to cli log 2. support async for cli fix: 1. close issue: [#79](https://github.com/htmlhint/HTMLHint/issues/79), fix exit with 0 when hint errors 2. fix end event col 3. attr-unsafe-chars(rule): exclude `\r\n` ## 0.9.8 *(2015-10-7)* [Section titled “0.9.8 (2015-10-7)”](#098-2015-10-7) add: 1. Search `.htmlhintrc` in parent directory 2. Allow comments in json 3. Support hint any file without `.html` or `.htm` extension, just like: `htmlhint test.xhtml` 4. Support json raw format in cli 5. tag-pair(rule): Show the line of the start tag 6. space-tab-mixed-disabled(rule): Support space and tab mode, for check only space or tab 7. Make cli logs more clear to people 8. add rule: title-require, `` must be present in `<head>` tag. fix: 1. Fix issue: #77 `<link rel=icon><link rel=icon>` 2. Made the descriptions and error messages of rules more clear to people 3. head-script-disabled(rule): No head not result error ## 0.9.7 *(2015-3-8)* [Section titled “0.9.7 (2015-3-8)”](#097-2015-3-8) fix: 1. fix ‘No such file’ issue on mac 2. head-script-disabled: not match template script ## 0.9.6 *(2014-6-18)* [Section titled “0.9.6 (2014-6-18)”](#096-2014-6-18) add: 1. add rule: attr-no-duplication 2. add rule: space-tab-mixed-disabled 3. add rule: id-class-ad-disabled 4. add rule: href-abs-or-rel 5. add rule: attr-unsafe-chars 6. add default rule: attr-no-duplication 7. add inline ruleset support 8. add test spec: Set false to rule 9. add point: load default ruleset when use empty ruleset ## 0.9.4 *(2013-9-27)* [Section titled “0.9.4 (2013-9-27)”](#094-2013-9-27) 1. add rule: src-not-empty fix: 1. fix attr-value-double-quotes rule: `<img src=''>` should result error ## 0.9.3 *(2013-5-24)* [Section titled “0.9.3 (2013-5-24)”](#093-2013-5-24) add: 1. add ruleid to csslint message fix: 1. fix csslint rule: del undefined of raw 2. fix parser for: `<div class=\"foo\"\"><a><span\">` ## 0.9.2 *(2013-4-6)* [Section titled “0.9.2 (2013-4-6)”](#092-2013-4-6) add: 1. add rule: csslint 2. add rule: jshint 3. add rule: id-unique 4. add cli ## 0.9.1 *(2013-3-23)* [Section titled “0.9.1 (2013-3-23)”](#091-2013-3-23) add: 1. add rule: attr-lowercase 2. add rule: attr-value-double-quotes 3. add rule: attr-value-not-empty 4. add rule: doctype-first 5. add rule: doctype-html5 6. add rule: head-script-disabled 7. add rule: id-class-value 8. add rule: img-alt-require 9. add rule: spec-char-escape 10. add rule: style-disabled 11. add rule: tagname-lowercase 12. add rule: tag-pair 13. add rule: tag-self-close --- # Configuration > How to configure HTMLHint using a configuration file, command line options, or inline comments. By default, HTMLHint looks for a `.htmlhintrc` file in the current directory and all parent directories, and applies its rules when parsing a file: ```sh htmlhint index.html ``` To provide a custom configuration file to the command, use the `--config` option: ```sh htmlhint --config htmlhint.conf index.html ``` Custom rules can also be specified individually, via the `--rules` option: ```sh htmlhint --rules tag-pair,id-class-value=underline index.html ``` Finally, rules can be specified inline directly in the HTML document: <!-- prettier-ignore --> ```html <!-- htmlhint tag-pair,id-class-value:underline --> <html> <head>...</head> <body>...</body> </html> ``` ## Disabling Rules Inline [Section titled “Disabling Rules Inline”](#disabling-rules-inline) You can disable specific rules or all rules for specific lines in your HTML using HTML comments. This is useful when you need to temporarily disable linting for a particular section of code. ### Disable All Rules [Section titled “Disable All Rules”](#disable-all-rules) To disable all HTMLHint rules for the following lines until re-enabled: <!-- prettier-ignore --> ```html <!-- htmlhint-disable --> <div class="foo">Lorem</div> <div class="bar">Ipsum</div> <!-- htmlhint-enable --> <div class="baz">Dolor</div> ``` ### Disable for Next Line [Section titled “Disable for Next Line”](#disable-for-next-line) To disable all rules for just the next line: <!-- prettier-ignore --> ```html <!-- htmlhint-disable-next-line --> <div class="foo">Lorem</div> <div class="bar">Ipsum</div> ``` ### Disable Specific Rules [Section titled “Disable Specific Rules”](#disable-specific-rules) To disable specific rules for the following lines: <!-- prettier-ignore --> ```html <!-- htmlhint-disable attr-lowercase --> <div CLASS="foo">Lorem</div> <div CLASS="bar">Ipsum</div> <!-- htmlhint-enable --> <div class="baz">Dolor</div> ``` ### Disable Specific Rules for Next Line [Section titled “Disable Specific Rules for Next Line”](#disable-specific-rules-for-next-line) To disable specific rules for just the next line: <!-- prettier-ignore --> ```html <!-- htmlhint-disable-next-line attr-lowercase --> <div CLASS="foo">Lorem</div> <div class="bar">Ipsum</div> ``` ### Disable Multiple Rules [Section titled “Disable Multiple Rules”](#disable-multiple-rules) You can disable multiple rules by listing them separated by spaces: <!-- prettier-ignore --> ```html <!-- htmlhint-disable attr-lowercase tagname-lowercase --> <DIV CLASS="foo">Lorem</DIV> <div class="bar">Ipsum</div> ``` ## Example configuration file [Section titled “Example configuration file”](#example-configuration-file) An example configuration file (with all rules disabled): ```json { "alt-require": false, "attr-lowercase": false, "attr-no-duplication": false, "attr-no-unnecessary-whitespace": false, "attr-sorted": false, "attr-unsafe-chars": false, "attr-value-double-quotes": false, "attr-value-no-duplication": false, "attr-value-not-empty": false, "attr-value-single-quotes": false, "attr-whitespace": false, "button-type-require": false, "doctype-first": false, "doctype-html5": false, "empty-tag-not-self-closed": false, "form-method-require": false, "frame-title-require": false, "h1-require": false, "head-script-disabled": false, "href-abs-or-rel": false, "html-lang-require": false, "id-class-ad-disabled": false, "id-class-value": false, "id-unique": false, "inline-script-disabled": false, "inline-style-disabled": false, "input-requires-label": false, "link-rel-canonical-require": false, "main-require": false, "meta-charset-require": false, "meta-description-require": false, "meta-viewport-require": false, "script-disabled": false, "space-tab-mixed-disabled": false, "spec-char-escape": false, "src-not-empty": false, "style-disabled": false, "tag-no-obsolete": false, "tag-pair": false, "tag-self-close": false, "tagname-lowercase": false, "tagname-specialchars": false, "tags-check": false, "title-require": false } ``` ## VS Code Configuration [Section titled “VS Code Configuration”](#vs-code-configuration) To have your configuration file recognized by editors with JSON schema support, you can add the following to VS Code settings (`.vscode/settings.json`). This will enable autocompletion and validation for the `.htmlhintrc` file. ```json { "json.schemas": [ { "fileMatch": ["/.htmlhintrc"], "url": "https://json.schemastore.org/htmlhint.json" } ] } ``` Note: if you have the [VS Code extension](/vs-code-extension/) installed, it will automatically recognize the `.htmlhintrc` file without needing to add this configuration. --- # Getting Started > How to set up HTMLHint in your project by adding it as a dev dependency and configuring it. 1\. Use npm or yarn to install HTMLHint: * npm `npm install --save-dev htmlhint` * yarn `yarn add --dev htmlhint` 2\. Create a `.htmlhintrc` configuration file in the root of your project with `htmlhint --init`. This will create a file with default rules. You can customize it as needed. For example, you can use the following configuration to enforce some common best practices: ```json { "alt-require": true, "attr-lowercase": true, "attr-no-duplication": true, "attr-value-double-quotes": true, "attr-value-no-duplication": true, "button-type-require": true, "doctype-first": true, "doctype-html5": true, "frame-title-require": true, "h1-require": true, "html-lang-require": true, "id-unique": true, "input-requires-label": true, "main-require": true, "meta-charset-require": true, "meta-description-require": true, "meta-viewport-require": true, "spec-char-escape": true, "src-not-empty": true, "tag-no-obsolete": true, "tag-pair": true, "tagname-lowercase": true, "title-require": true } ``` 3\. Run HTMLHint on, for example, all the HTML files in your project: ```shell npx htmlhint "**/*.html" ``` --- # Other integrations > Other integrations built and maintained by the HTMLHint organization and some by the community. Other integrations built and maintained by the HTMLHint organization and some by the community. * [chai-htmlhint](https://github.com/htmlhint/chai-htmlhint) - Extends Chai with assertions for HTMLHint. --- # Task runners > Task runner integrations built and maintained by HTMLHint organization and the community. Task runner integrations built and maintained by HTMLHint organization and the community. ## CLI [Section titled “CLI”](#cli) * [grunt-htmlhint-inline](https://github.com/htmlhint/grunt-htmlhint-inline) - Grunt plugin for linting inline HTML. * [grunt-htmlhint](https://github.com/htmlhint/grunt-htmlhint) - Grunt plugin for HTMLHint. * [gulp-htmlhint-inline](https://github.com/htmlhint/gulp-htmlhint-inline) - Gulp plugin for linting inline HTML. * [htmlhint-loader](https://github.com/htmlhint/htmlhint-loader) - webpack loader for HTMLHint. ## GitHub Actions [Section titled “GitHub Actions”](#github-actions) * [Super-Linter](https://github.com/github/super-linter) - A combination of linters, including HTMLHint. * [MegaLinter](https://megalinter.io/latest/) - Aggregates 70+ linters for CI or local run, [including HTMLHint](https://oxsecurity.github.io/megalinter/latest/descriptors/html_htmlhint/#readme) --- # List of rules > A complete list of all the rules for HTMLHint ## Doctype and Head [Section titled “Doctype and Head”](#doctype-and-head) * [`doctype-first`](doctype-first/): `<doctype>` must be declared first. * [`doctype-html5`](doctype-html5/): `<doctype>` must be HTML5. * [`head-script-disabled`](head-script-disabled/): The `<script>` tag cannot be used in `<head>` tag. * [`html-lang-require`](html-lang-require/): The HTML lang attribute is required. * [`meta-charset-require`](meta-charset-require/): `<meta charset="">` must be present in `<head>` tag. * [`meta-description-require`](meta-description-require/): `<meta name="description">` with non-blank content must be present in `<head>` tag. * [`meta-viewport-require`](meta-viewport-require/): `<meta name="viewport">` with non-blank content must be present in `<head>` tag. * [`link-rel-canonical-require`](link-rel-canonical-require/): `<link rel="canonical">` with non-blank href must be present in `<head>` tag. * [`script-disabled`](script-disabled/): `<script>` tags cannot be used. * [`style-disabled`](style-disabled/): `<style>` tags cannot be used. * [`title-require`](title-require/): `<title>` must be present in `<head>` tag. ## Attributes [Section titled “Attributes”](#attributes) * [`alt-require`](alt-require/): The alt attribute of an img element must be present and alt attribute of area\[href] and input\[type=image] must have a value. * [`attr-lowercase`](attr-lowercase/): All attribute names must be in lowercase. * [`attr-no-duplication`](attr-no-duplication/): Elements cannot have duplicate attributes. * [`attr-no-unnecessary-whitespace`](attr-no-unnecessary-whitespace/): No spaces between attribute names and values. * [`attr-sorted`](attr-sorted/): Attributes should be sorted in order. * [`attr-unsafe-chars`](attr-unsafe-chars/): Attribute values cannot contain unsafe chars. * [`attr-value-double-quotes`](attr-value-double-quotes/): Attribute values must be in double quotes. * [`attr-value-no-duplication`](attr-value-no-duplication/): Attribute values should not contain duplicates. * [`attr-value-not-empty`](attr-value-not-empty/): All attributes must have values. * [`attr-value-single-quotes`](attr-value-single-quotes/): Attribute values must be in single quotes. * [`attr-whitespace`](attr-whitespace/): No leading or trailing spaces in attribute values. * [`button-type-require`](button-type-require/): The type attribute of a button element must be present with a valid value: “button”, “submit”, or “reset”. * [`form-method-require`](form-method-require/): The method attribute of a form element must be present with a valid value: “get”, “post”, or “dialog”. * [`input-requires-label`](input-requires-label/): All \[ input ] tags must have a corresponding \[ label ] tag. ## Tags [Section titled “Tags”](#tags) * [`empty-tag-not-self-closed`](empty-tag-not-self-closed/): The empty tag should not be closed by self. * [`frame-title-require`](frame-title-require/): A `<frame>` or `<iframe>` element must have an accessible name. * [`h1-require`](h1-require/): A document must have at least one `<h1>` element. * [`href-abs-or-rel`](href-abs-or-rel/): An href attribute must be either absolute or relative. * [`main-require`](main-require/): A document must have at least one `<main>` element in the `<body>` tag. * [`src-not-empty`](src-not-empty/): The src attribute of an img(script,link) must have a value. * [`tag-no-obsolete`](tag-no-obsolete/): Disallows the use of obsolete HTML tags. * [`tag-pair`](tag-pair/): Tag must be paired. * [`tag-self-close`](tag-self-close/): Empty tags must be self closed. * [`tagname-lowercase`](tagname-lowercase/): All HTML element names must be in lowercase. * [`tagname-specialchars`](tagname-specialchars/): Tag names can only contain letters, numbers, ”-”, ”:” or ”\_”. * [`tags-check`](tags-check/): Allowing specify rules for any tag and validate that ## ID [Section titled “ID”](#id) * [`id-class-ad-disabled`](id-class-ad-disabled/): The id and class attributes cannot use the ad keyword, it will be blocked by adblock software. * [`id-class-value`](id-class-value/): The id and class attribute values must meet the specified rules. * [`id-unique`](id-unique/): The value of id attributes must be unique. ## Inline [Section titled “Inline”](#inline) * [`inline-script-disabled`](inline-script-disabled/): Inline script cannot be used. * [`inline-style-disabled`](inline-style-disabled/): Inline style cannot be used. ## Formatting [Section titled “Formatting”](#formatting) * [`space-tab-mixed-disabled`](space-tab-mixed-disabled/): Do not mix tabs and spaces for indentation. * [`spec-char-escape`](spec-char-escape/): Special characters must be escaped. --- # alt-require > Requires alt attributes on images and relevant elements to improve accessibility and SEO. Alt of `img` must be present and alt of `area[href]` and `input[type=image]` must be set with a value. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <img src="test.png" alt="test" /> <input type="image" alt="test" /> <area shape="circle" coords="180,139,14" href="test.html" alt="test" /> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <img src="test.png" /> <input type="image" /> <area shape="circle" coords="180,139,14" href="test.html" /> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) The alt attribute is used to provide alternative text for images, which helps improve accessibility for users who cannot see the image. It also helps with SEO by providing context for the image. --- # attr-lowercase > Enforces all attribute names in HTML to be lowercase for consistency and standards compliance. Attribute name must be lowercase. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule * `['fooBar', 'Test']`: enable rule except for the given attribute names. All SVG camelCase properties are included, for example `viewBox` ### Example [Section titled “Example”](#example) ```json { ... "attr-lowercase": ['fooBar'] ... } ``` ### The following pattern is **not** considered a rule violation: [Section titled “The following pattern is not considered a rule violation:”](#the-following-pattern-is-not-considered-a-rule-violation) ```html <img src="test.png" alt="test" /> <!-- known SVG attributes are ignored --> <svg width="200" height="200" viewBox="0 0 200 200" /> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <img SRC="test.png" ALT="test" /> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) Lowercase attribute names are required for HTML5 compliance and to ensure consistency across different HTML elements. --- # attr-no-duplication > Prevents duplicate attributes in a single HTML element to ensure valid and clean markup. The same attribute can’t be specified twice. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <img src="a.png" /> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <img src="a.png" src="b.png" /> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) Duplicate attributes can cause unexpected behavior and make the code harder to read and maintain. --- # attr-no-unnecessary-whitespace > Disallows unnecessary spaces between attribute names and values in HTML elements. No spaces between attribute names and values. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <div title="a"></div> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <div title = "a"></div> <div title= "a"></div> <div title ="a"></div> ``` --- # attr-sorted > Enforces a specific order for attributes in HTML elements to improve readability and consistency. Attributes should be sorted in the following order: * `class` * `id` * `name` * `src` * `for` * `type` * `href` * `value` * `title` * `alt` * `role` Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <div img="image" meta="meta" font="font"></div> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <div type="type" img="image" id="id" font="font"></div> ``` --- # attr-unsafe-chars > Disallows unsafe characters in attribute values to prevent rendering and security issues. Attribute value cannot use unsafe chars. regexp: `/[\u0000-\u0009\u000b\u000c\u000e-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/` Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <li> <a href="https://vimeo.com/album/1951235/video/56931059">Sud Web 2012</a> </li> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <li> <a href="https://vimeo.com/album/1951235/video/56931059\u0009" >Sud Web 2012</a > </li> ``` Tip The unsafe chars is in the tail of the href attribute. --- # attr-value-double-quotes > Requires attribute values in HTML to be enclosed in double quotes for consistency and standards compliance. Attribute value must be closed by double quotes. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <a href="" title="abc"></a> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <a href='' title='abc'></a> ``` --- # attr-value-no-duplication > Prevents duplicate values within the same attribute to ensure clean and efficient markup. Class attributes should not contain duplicate values. Other attributes can be checked via configuration. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule with default attributes (only class) * `['attr1', 'attr2', ...]`: specify custom list of attributes to check * `false`: disable rule ## Default attributes checked [Section titled “Default attributes checked”](#default-attributes-checked) By default, this rule only checks the `class` attribute for duplicate values: * `class` - CSS class names should not be repeated Other attributes can be checked by providing a custom configuration. ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <div class="container fluid small">Content</div> ``` ```html <!-- data-attributes not checked by default --> <input data-attribute="apple banana apple"> ``` ### The following patterns are considered rule violations: [Section titled “The following patterns are considered rule violations:”](#the-following-patterns-are-considered-rule-violations) ```html <div class="d-none small d-none">Content</div> ``` ## Why does this rule exist? [Section titled “Why does this rule exist?”](#why-does-this-rule-exist) Having duplicate values in class attributes can: * Make the markup unnecessarily verbose * Cause confusion during development * Lead to inefficient CSS specificity calculations * Indicate potential copy-paste errors or oversight This rule helps maintain clean, efficient markup by catching these duplicates early. ## Custom configuration [Section titled “Custom configuration”](#custom-configuration) You can customize which attributes to check by providing an array: ```json { "attr-value-no-duplication": ["class", "id", "name", "role"] } ``` ```json { "attr-value-no-duplication": ["data-test", "aria-label", "custom-attr"] } ``` This allows you to focus on attributes specific to your project needs. --- # attr-value-not-empty > Ensures all attributes have non-empty values to prevent invalid or ambiguous HTML. Attribute must set value. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <input type="button" disabled="disabled" /> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <input type="button" disabled /> ``` --- # attr-value-single-quotes > Requires attribute values in HTML to be enclosed in single quotes for consistency. Attribute value must closed by single quotes. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <a href='' title='abc'></a> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <a href="" title="abc"></a> ``` --- # attr-whitespace > Disallows leading or trailing spaces inside attribute values to ensure clean and valid HTML. No leading or trailing spaces inside attribute values. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <div title="a"></div> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <div title=" a"></div> <div title="a "></div> <div title=" a "></div> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) Leading or trailing spaces inside attribute values can cause unexpected behavior and make the code harder to read and maintain. --- # button-type-require > Requires button elements to have a valid type attribute for better browser compatibility and user experience. The type attribute of a `<button>` element must be present with a valid value: “button”, “submit”, or “reset”. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <button type="button">Click me</button> <button type="submit">Submit form</button> <button type="reset">Reset form</button> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <button>No type specified</button> <button type="invalid">Invalid type</button> ``` ## Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) HTML buttons default to `type="submit"` when used within a form if no type is specified, which can lead to unexpected form submissions. Explicitly setting the type attribute makes the button’s behavior predictable and clear to both developers and users. The HTML specification requires that button elements have one of three valid types: * `button`: A generic button with no default behavior * `submit`: Submits the form data to the server (default) * `reset`: Resets all form controls to their initial values This rule helps ensure that buttons have explicit, valid types for better browser compatibility and user experience. --- # doctype-first > Ensures the doctype declaration appears before any non-comment content in HTML documents. Doctype must be declared before any non-comment content. Comments and whitespace are allowed before the DOCTYPE declaration. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <!DOCTYPE html> <html></html> ``` ```html <!-- Comment before doctype --> <!DOCTYPE html> <html></html> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <html></html> ``` ```html <div>Content before doctype</div> <!DOCTYPE html> <html></html> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) The DOCTYPE declaration is required for HTML5 compliance and to ensure that the document is parsed correctly. --- # doctype-html5 > Ensures the doctype is HTML5. Doctype must be HTML5. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following pattern is **not** considered a rule violations [Section titled “The following pattern is not considered a rule violations”](#the-following-pattern-is-not-considered-a-rule-violations) ```html <!DOCTYPE html> <html></html> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "https://www.w3.org/TR/html4/strict.dtd"> <html></html> ``` ## Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) The DOCTYPE declaration is required for HTML5 compliance and to ensure that the document is parsed correctly. Further reading: [MDN Web Docs - Doctype](https://developer.mozilla.org/en-US/docs/Glossary/Doctype) --- # empty-tag-not-self-closed > Ensures empty HTML tags are not self-closed, following HTML standards for void elements. The empty tag should not be closed by self. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <br> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <br /> ``` Note This rule is incompatible with Prettier. If you use Prettier, you should disable this rule. --- # form-method-require > Requires form elements to have a valid method attribute for better security and user experience. The method attribute of a `<form>` element must be present with a valid value: “get”, “post”, or “dialog”. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <form method="get"></form> <form method="post"></form> <form method="dialog"></form> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <form>No method specified</form> <form method="invalid">Invalid method</form> ``` ## Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) The absence of the method attribute means the form will use the default `GET` method. With `GET`, form data is included in the URL (e.g., `?username=john&password=secret`), which can expose sensitive information in browser history, logs, or the network request. The HTML specification requires that form elements have one of three valid methods: * `get`: Appends form data to the URL (default, but not recommended for sensitive data) * `post`: Sends form data in the request body (more secure for sensitive data) * `dialog`: Used for dialog forms (HTML5 feature) This rule helps ensure that forms have explicit, valid methods for better security and user experience. --- # frame-title-require > Requires that frame and iframe elements have an accessible name for screen readers and assistive technologies. A `<frame>` or `<iframe>` element must have an accessible name. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <iframe src="content.html" aria-label="Interactive content"></iframe> <iframe src="content.html" aria-labelledby="frame-heading"></iframe> <iframe src="content.html" title="Embedded content"></iframe> <iframe src="content.html" role="presentation"></iframe> <frame src="content.html" title="Navigation frame"> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <iframe src="content.html"></iframe> <iframe src="content.html" aria-label=""></iframe> <iframe src="content.html" title=""></iframe> <frame src="content.html"> ``` ## Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) The `<frame>` or `<iframe>` element must have an accessible name to help screen readers and assistive technologies understand the content of the frame or iframe. Further reading: [Axe Rules - frame-title](https://dequeuniversity.com/rules/axe/4.8/frame-title) --- # h1-require > Ensures that an HTML document contains at least one `<h1>` element for proper document structure and accessibility. A H1 heading element is required in HTML documents. The heading can not be empty. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <html><body><h1>Title</h1></body></html> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <html><body><p>No heading</p></body></html> ``` ```html <html><body><h1></h1></body></html> ``` ```html <html><body><h1> </h1></body></html> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) The `<h1>` element is the main heading of the page and is used to provide a clear and concise title for the page. It is also used to help with SEO by providing a clear and concise title for the page. --- # head-script-disabled > Disallows the use of <script> tags within the <head> section of HTML documents. The `<script>` tag can not be used in head. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule (disallow all scripts in head) * `false`: disable rule * `"allow-non-blocking"`: allow non-blocking scripts (modules, deferred, and async scripts) in head ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) #### Default behavior (`true`) [Section titled “Default behavior (true)”](#default-behavior-true) ```html <body> <script src="test.js"></script> </body> ``` ```html <head> <script type="text/template"> <div>Template content</div> </script> </head> ``` #### With `"allow-non-blocking"` option [Section titled “With "allow-non-blocking" option”](#with-allow-non-blocking-option) ```html <head> <script type="module" src="module.js"></script> </head> ``` ```html <head> <script defer src="deferred.js"></script> </head> ``` ```html <head> <script async src="analytics.js"></script> </head> ``` ```html <head> <script type="module"> import { init } from './app.js'; init(); </script> </head> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) #### Default behavior (`true`) [Section titled “Default behavior (true)”](#default-behavior-true-1) ```html <head> <script src="test.js"></script> </head> ``` ```html <head> <script type="module" src="module.js"></script> </head> ``` #### With `"allow-non-blocking"` option [Section titled “With "allow-non-blocking" option”](#with-allow-non-blocking-option-1) ```html <head> <script src="test.js"></script> </head> ``` ```html <head> <script type="text/javascript"> console.log('blocking script'); </script> </head> ``` ## Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) Scripts in the `<head>` section traditionally block HTML parsing and rendering, which can negatively impact page load performance. However, modern JavaScript features like ES6 modules (`type="module"`), the `defer` attribute, and the `async` attribute allow scripts to be non-blocking, making them safe to place in the head without performance penalties. For more information, see: * [MDN: Script element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) * [MDN: defer attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#defer) * [MDN: async attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#async) * [MDN: JavaScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) --- # href-abs-or-rel > Enforces href attributes to be either absolute or relative URLs as specified in the configuration. Href must be absolute or relative. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `abs`: absolute mode * `rel`: relative mode * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html abs: <a href="https://htmlhint.com/">test1</a> <a href="https://github.com/">test2</a> rel: <a href="test.html">test1</a> <a href="../test.html">test2</a> ``` --- # html-lang-require > Requires the lang attribute on the <html> element to ensure proper language declaration for accessibility and SEO. The lang attribute of an `<html>` element must be present and should be valid. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following pattern is **not** considered rule violations [Section titled “The following pattern is not considered rule violations”](#the-following-pattern-is-not-considered-rule-violations) ```html <html lang="en"></html> ``` ### The following patterns are considered a rule violations [Section titled “The following patterns are considered a rule violations”](#the-following-patterns-are-considered-a-rule-violations) ```html <!-- missing lang tag --> <html></html> ``` ```html <!-- empty lang tag --> <html lang=""></html> ``` ```html <!-- invalid BCP 47 lang value --> <html lang="-"></html> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) The lang attribute is used to declare the language of the document, which helps with SEO and accessibility. --- # id-class-ad-disabled > Prevents the use of 'ad' in id or class attributes to avoid issues with ad blockers. Id and class can not use ad keyword, it will blocked by adblock software. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <div id="adcontainer"></div> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <div id="ad-container"></div> <div id="ad_container"></div> ``` ## Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) Using `ad` in `id` or `class` attributes can cause elements to be hidden by ad-blocking software, which may break the layout or hide important content. --- # id-class-value > Enforces specific naming conventions for id and class attribute values in HTML elements. Id and class value must meet some rules: underline, dash, hump. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `underline`: underline mode ( aaa\_bb ) * `dash`: enable rule ( aaa-bbb ) * `hump`: enable rule ( aaaBbb ) * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html underline: <div id="aaa_bbb"> dash: <div id="aaa-bbb"> hump: <div id="aaaBbb"> ``` --- # id-unique > Ensures all id attributes in an HTML document are unique to prevent conflicts and unexpected behavior. ID attributes must be unique in the document. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <div id="id1"></div><div id="id2"></div> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <div id="id1"></div><div id="id1"></div> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) Duplicate ID attributes can cause unexpected behavior and make the code harder to read and maintain. Further reading: [Axe Rules - duplicate-id](https://dequeuniversity.com/rules/axe/4.1/duplicate-id) --- # inline-script-disabled > Disallows the use of inline JavaScript in HTML elements for improved security and maintainability. Inline script cannot be used. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are considered violations [Section titled “The following patterns are considered violations”](#the-following-patterns-are-considered-violations) ```html <img src="test.gif" onclick="alert(1);"> <img src="javascript:alert(1)"> <a href="javascript:alert(1)">test1</a> ``` --- # inline-style-disabled > Disallows the use of inline style attributes to promote separation of content and presentation. Inline style cannot be used. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <div style="color:red"></div> ``` ## Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) Inline styles can make the code harder to read and maintain. They also make it harder to override styles with CSS. --- # input-requires-label > Requires every <input> element to have an associated <label> for accessibility compliance. All `<input>` tags must have a corresponding `<label>` tag. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <input type="password"> <input id="some-id" type="password" /> <label for="some-other-id"/> <input id="some-id" type="password" /> <label for=""/> <input type="password" /> <label for="something"/> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <label for="some-id"/><input id="some-id" type="password" /> <input id="some-id" type="password" /> <label for="some-id"/> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) This rule ensures that the input element has a corresponding label element for accessibility compliance. Further reading: [Axe Rules - input elements must have labels](https://dequeuniversity.com/rules/axe/4.1/label) --- # link-rel-canonical-require > Ensures every HTML document includes a canonical link tag within the head element for better SEO and duplicate content management. A `<link rel="canonical">` with non-blank href must be present in `<head>` tag. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <!-- Valid canonical link with absolute URL --> <html><head><link rel="canonical" href="https://example.com/dresses/green-dresses"></head></html> <!-- Valid canonical link with relative URL --> <html><head><link rel="canonical" href="/dresses/green-dresses"></head></html> <!-- Valid canonical link with query parameters --> <html><head><link rel="canonical" href="https://example.com/dresses/green-dresses?color=green&size=m"></head></html> <!-- Valid canonical link with fragment --> <html><head><link rel="canonical" href="https://example.com/dresses/green-dresses#section1"></head></html> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <!-- Missing canonical link --> <html><head></head></html> <!-- Empty href attribute --> <html><head><link rel="canonical" href=""></head></html> <!-- Whitespace-only href attribute --> <html><head><link rel="canonical" href=" "></head></html> <!-- Missing href attribute --> <html><head><link rel="canonical"></head></html> ``` ## Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) While it’s generally not critical to specify a canonical preference for your URLs, there are several reasons why you would want to explicitly tell search engines about a canonical page in a set of duplicate or similar pages: * **Specify preferred URL**: Tell search engines which URL you want people to see in search results * **Consolidate signals**: Help search engines consolidate signals from similar pages into a single, preferred URL * **Simplify tracking**: Get consolidated metrics for specific content across multiple URLs * **Optimize crawling**: Prevent search engines from wasting time crawling duplicate content --- # main-require > Ensures that an HTML document contains a `<main>` element within the `<body>` tag for proper document structure and accessibility. A `<main>` element is required within the `<body>` tag of HTML documents. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <html><body><main>Content</main></body></html> ``` ```html <html><body><header>Header</header><main>Content</main><footer>Footer</footer></body></html> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <html><body><p>No main tag</p></body></html> ``` ```html <html><body><header>Header</header><footer>Footer</footer></body></html> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) This rule ensures that the document has a clear and accessible structure, which is important for both users and screen readers. Further reading: [Axe Rules - landmark-one-main](https://dequeuniversity.com/rules/axe/4.9/landmark-one-main) --- # meta-charset-require > Ensures every HTML document includes a meta charset tag within the head element for proper character encoding. A `<meta charset="">` must be present in `<head>` tag. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <html><head><meta charset="utf-8"></head></html> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <!-- Missing meta charset --> <html><head></head></html> <!-- Empty meta charset value --> <html><head><meta charset=""></head></html> <!-- Whitespace-only meta charset value --> <html><head><meta charset=" "></head></html> ``` --- # meta-description-require > Ensures every HTML document includes a non-blank meta description tag within the head element for better SEO. A `<meta name="description">` with non-blank content must be present in `<head>` tag. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <html><head><meta name="description" content="A description of the page"></head></html> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <!-- Missing meta description --> <html><head></head></html> <!-- Empty meta description content --> <html><head><meta name="description" content=""></head></html> <!-- Whitespace-only meta description content --> <html><head><meta name="description" content=" "></head></html> <!-- Meta description outside head tag --> <html><meta name="description" content="A description"><head></head></html> ``` ## Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) The `<meta name="description">` tag is used to provide a description of the page, which helps with SEO. Further reading: * [MDN Web Docs - Setting a document meta description](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/content#setting_a_document_meta_description) * [Google Search Central - Meta descriptions](https://developers.google.com/search/docs/appearance/snippet#meta-descriptions) --- # meta-viewport-require > Ensures every HTML document includes a meta viewport tag within the head element for proper responsive design. A `<meta name="viewport">` must be present in `<head>` tag. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <html><head><meta name="viewport" content="width=device-width, initial-scale=1"></head></html> ``` ### The following patterns are considered rule violations [Section titled “The following patterns are considered rule violations”](#the-following-patterns-are-considered-rule-violations) ```html <!-- Missing meta viewport --> <html><head></head></html> <!-- Empty meta viewport content --> <html><head><meta name="viewport" content=""></head></html> <!-- Whitespace-only meta viewport content --> <html><head><meta name="viewport" content=" "></head></html> ``` ## Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) The `<meta name="viewport">` tag is used to control the viewport of the page, which helps with responsive design. --- # script-disabled > Disallows the use of <script> tags in HTML documents for security and maintainability. The `<script>` tag can not be used anywhere in the document. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <body> </body> ``` ### The following patterns are considered violations [Section titled “The following patterns are considered violations”](#the-following-patterns-are-considered-violations) ```html <head> <script src="test.js"></script> </head> ``` ```html <body> <script src="test.js"></script> </body> ``` --- # space-tab-mixed-disabled > Prevents mixing spaces and tabs for indentation at the beginning of lines to ensure consistent formatting. Blank-space (space and tab) characters should not be mixed in the beginning of any line. Level: Warning ## Config values [Section titled “Config values”](#config-values) * `space`: space mode (only spaces are valid for indentation) * `space4`: space mode and require 4 space characters * `tab`: tab mode (only tab characters are valid for indentation) * `false`: disable rule ### Example [Section titled “Example”](#example) ```json { ... "space-tab-mixed-disabled": space4 ... } ``` ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html  <img src="tab.png" /> 33333333<img src="space.png" /> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html 333<img src="tab_before_space.png" /> 3333 <img src="space_before_tab.png" /> ``` Note In the examples above, spaces and tabs are represented by `3` and ``, respectively, to make the difference visible. --- # spec-char-escape > Requires special characters in HTML to be properly escaped to prevent rendering issues. Special characters must be escaped. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered violations [Section titled “The following patterns are not considered violations”](#the-following-patterns-are-not-considered-violations) ```html <span>aaa>bbb<ccc</span> <span>Steinway & Sons, Q&A</span> <span>Steinway & Sons, Q&A</span> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <span>aaa>bbb<ccc</span> ``` ## Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) Special HTML characters like `<`, `>`, and `&` must be escaped to prevent them from being interpreted as HTML tags or entities. This avoids rendering issues and potential cross-site scripting (XSS) vulnerabilities. --- # src-not-empty > Requires the src attribute of img, script, and link elements to have a non-empty value. Src of img(script, link) must set value. Empty of src will visit current page twice. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <img src="test.png" /> <script src="test.js"></script> <link href="test.css" type="text/css" /> <iframe src="test.html"> ``` ### The following patterns are considered violations [Section titled “The following patterns are considered violations”](#the-following-patterns-are-considered-violations) ```html <img src /> <script src=""></script> <script src></script> <link href="" type="text/css" /> <link href type="text/css" /> <iframe src=""> <iframe src> ``` --- # style-disabled > Disallows the use of <style> tags in HTML to enforce separation of content and presentation. Style tag can not be use. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are considered violations [Section titled “The following patterns are considered violations”](#the-following-patterns-are-considered-violations) ```html <head><style type="text/css"></style></head> <body><style type="text/css"></style></body> ``` --- # tag-no-obsolete > Disallows the use of obsolete HTML tags that are no longer supported in modern browsers. Disallows the use of obsolete HTML tags. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ## Description [Section titled “Description”](#description) This rule prevents the use of HTML tags that have been deprecated and are considered obsolete in HTML5. ### Obsolete tags include: [Section titled “Obsolete tags include:”](#obsolete-tags-include) `acronym`, `applet`, `basefont`, `bgsound`, `big`, `blink`, `center`, `dir`, `font`, `frame`, `frameset`, `isindex`, `keygen`, `listing`, `marquee`, `menuitem`, `multicol`, `nextid`, `nobr`, `noembed`, `noframes`, `plaintext`, `rb`, `rtc`, `spacer`, `strike`, `tt`, `xmp` ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <div>Content</div> <span>Text</span> <p>Paragraph</p> ``` ### The following patterns are considered rule violations: [Section titled “The following patterns are considered rule violations:”](#the-following-patterns-are-considered-rule-violations) ```html <center>Centered text</center> <font color="red">Red text</font> <marquee>Scrolling text</marquee> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) These tags are no longer supported by modern browsers and should be replaced with appropriate alternatives. --- # tag-pair > Ensures that all HTML tags are properly paired with corresponding opening and closing tags. Tag must be paired. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <ul><li></li></ul> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <ul><li></ul> <ul></li></ul> ``` --- # tag-self-close > Requires proper use of self-closing tags for void elements to maintain valid HTML structure. Self-closing tags, also known as void elements, are HTML elements that do not require a separate closing tag. These tags are self-contained and are typically used for elements that do not have any content between an opening and closing tag. Self-closing tags help keep the HTML structure clean and concise. This rule is especially relevant for XHTML or projects requiring strict HTML syntax. Level: Warning ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following pattern is **not** considered a violations [Section titled “The following pattern is not considered a violations”](#the-following-pattern-is-not-considered-a-violations) ```html <meta charset="UTF-8" /> ``` ### The following pattern is considered a violation [Section titled “The following pattern is considered a violation”](#the-following-pattern-is-considered-a-violation) ```html <meta charset="UTF-8"> ``` --- # tagname-lowercase > Enforces all HTML tag names to be lowercase for consistency and standards compliance. Tagname must be lowercase. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule * `['clipPath', 'data-Test']`: enable rule except for the given tag names. All SVG camelCase elements are included, for example `linearGradient`, `foreignObject` ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <span><div> ``` SVG elements with camelCase names (e.g. `linearGradient`, `foreignObject`) are allowed: ```html <svg><linearGradient /><foreignObject /><textPath /></svg> ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html <SPAN><BR> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) Lowercase tagnames typically have higher compression rates compared to uppercase tagnames allowing for slightly faster page loads. Lowercase tagnames are also more readable and easier to understand. --- # tagname-specialchars > Ensures HTML tag names only contain allowed characters such as letters, numbers, hyphens, colons, or underscores. Tagname must not contain any characters beside letters, numbers, ”-”, ”:” or ”\_”. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <a href=""></a><span>test</span> ``` ### The following patterns are considered violation: [Section titled “The following patterns are considered violation:”](#the-following-patterns-are-considered-violation) ```html <@ href="link"></@> <$pan>aab</$pan> ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) Tagnames should only contain allowed characters to ensure consistency and readability. Further reading: [HTML5 Specification - Tag names](https://html.spec.whatwg.org/multipage/syntax.html#syntax-tag-name) --- # tags-check > Checks for correct usage of self-closing tags and required or excluded tags in HTML elements. Check if particular tags are self-closing or must include or exclude particular tags. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule * `{}:` configuration object, mapping values of tags to their respective configuration. Tags configuration can have properties of: `selfclosing` If an element is or is not self-closing, when it otherwise should be. Level: `warn` `attrsRequired` If an element is missing an attribute that should exist. Level: Error `redundantAttrs` If an element has an attribute that is not necessary. Level: Error `attrsOptional` If an element has an attribute that is not included in the allowable set. Level: Error ### Example [Section titled “Example”](#example) ```json { ... "tags-check": { "a": { "selfclosing": true, "attrsRequired": ["href", "title"], "redundantAttrs": ["alt"], ``` --- # title-require > Ensures every HTML document includes a <title> tag within the <head> for accessibility and SEO. `<title>` must be present in `<head>` tag. Level: Error ## Config value [Section titled “Config value”](#config-value) * `true`: enable rule * `false`: disable rule ### The following patterns are **not** considered rule violations [Section titled “The following patterns are not considered rule violations”](#the-following-patterns-are-not-considered-rule-violations) ```html <html><head><title>test ``` ### The following pattern is considered a rule violation: [Section titled “The following pattern is considered a rule violation:”](#the-following-pattern-is-considered-a-rule-violation) ```html ``` ### Why this rule is important [Section titled “Why this rule is important”](#why-this-rule-is-important) The `` element is used to provide a title for the document, which helps with SEO and accessibility. --- # Command-Line Interface (CLI) > Use HTMLHint from the command line to lint your HTML files. There are several options available to customize the behavior of the linter. You can use HTMLHint on the command-line. For example: ```shell npx htmlhint index.html ``` Use `npx htmlhint --help` to print the CLI documentation. ## Options [Section titled “Options”](#options) In addition to the [standard options](/usage/options/), the CLI accepts: ### `--color, --no-color` [Section titled “--color, --no-color”](#--color---no-color) Force enabling/disabling of color. ### `--init` [Section titled “--init”](#--init) Create a new HTMLHint configuration file (`.htmlhintrc`) in the current directory with default rules. If a configuration file already exists, this command will exit successfully without making changes. ```shell npx htmlhint --init ``` ### `--list, -l` [Section titled “--list, -l”](#--list--l) Show all the rules available ### `--rules, -r` [Section titled “--rules, -r”](#--rules--r) Set all of the rules available ### `--rulesdir, -R` [Section titled “--rulesdir, -R”](#--rulesdir--r) Load custom rules from file or folder. See the [custom rules documentation](/usage/custom-rules/) for detailed information on creating and using custom rules. ```shell --- # Load a single custom rule file npx htmlhint --rulesdir ./my-custom-rule.js index.html --- # Load all custom rules from a directory npx htmlhint --rulesdir ./custom-rules/ index.html ``` ### `--version, -V` [Section titled “--version, -V”](#--version--v) Show the currently installed version of HTMLHint. --- # Custom Rules > Learn how to create and use custom rules to extend HTMLHint's functionality for your specific needs. HTMLHint allows you to create custom rules to extend its functionality for your specific needs. Custom rules can be loaded using the `--rulesdir` option and follow the same pattern as built-in rules. ## Creating Custom Rules [Section titled “Creating Custom Rules”](#creating-custom-rules) Custom rules are JavaScript modules that export a function. The function receives the `HTMLHint` instance as a parameter and should register the custom rule using `HTMLHint.addRule()`. ### Basic Custom Rule Structure [Section titled “Basic Custom Rule Structure”](#basic-custom-rule-structure) my-custom-rule.js ```javascript module.exports = function(HTMLHint) { HTMLHint.addRule({ id: 'my-custom-rule', description: 'This is my custom rule description', init: function(parser, reporter, options) { // Rule implementation goes here } }); }; ``` ### Rule Object Properties [Section titled “Rule Object Properties”](#rule-object-properties) Each custom rule should have the following properties: * **`id`** (string): Unique identifier for the rule. This is used in configuration files and command line options. * **`description`** (string): Human-readable description of what the rule does. This appears in the `--list` output. * **`init`** (function): Function that initializes the rule with the parser and reporter. ### The `init` Function [Section titled “The init Function”](#the-init-function) The `init` function is where your rule logic goes. It receives three parameters: * **`parser`**: The HTML parser instance that provides events as it parses the HTML * **`reporter`**: The reporter instance for generating warnings, errors, or info messages * **`options`**: Rule-specific options from the configuration ### Important: Using Arrow Functions [Section titled “Important: Using Arrow Functions”](#important-using-arrow-functions) When adding event listeners, **always use arrow functions** instead of function expressions to ensure the correct `this` context is maintained when calling reporter methods: ```javascript // ✅ Correct - Arrow function preserves 'this' context parser.addListener('tagstart', (event) => { reporter.warn('Message', event.line, event.col, this, event.raw); }); // ❌ Incorrect - Function expression loses 'this' context parser.addListener('tagstart', function(event) { reporter.warn('Message', event.line, event.col, this, event.raw); // 'this' is parser, not rule }); ``` ## Example Custom Rules [Section titled “Example Custom Rules”](#example-custom-rules) ### Example 1: Simple Tag Check [Section titled “Example 1: Simple Tag Check”](#example-1-simple-tag-check) This rule warns when a specific tag is used: no-div-tags.js ```javascript module.exports = function(HTMLHint) { HTMLHint.addRule({ id: 'no-div-tags', description: 'Div tags are not allowed', init: function(parser, reporter, options) { parser.addListener('tagstart', (event) => { const tagName = event.tagName.toLowerCase(); if (tagName === 'div') { reporter.warn( 'Div tags are not allowed. Use semantic HTML elements instead.', event.line, event.col, this, event.raw ); } }); } }); }; ``` ### Example 2: Attribute Validation [Section titled “Example 2: Attribute Validation”](#example-2-attribute-validation) This rule checks for specific attribute patterns: data-attributes-required.js ```javascript module.exports = function(HTMLHint) { HTMLHint.addRule({ id: 'data-attributes-required', description: 'Elements with class "component" must have a data-component attribute', init: function(parser, reporter, options) { parser.addListener('tagstart', (event) => { const tagName = event.tagName.toLowerCase(); const mapAttrs = parser.getMapAttrs(event.attrs); // Check if element has class "component" if (mapAttrs.class && mapAttrs.class.includes('component')) { // Check if it has data-component attribute if (!mapAttrs['data-component']) { reporter.warn( 'Elements with class "component" must have a data-component attribute', event.line, event.col, this, event.raw ); } } }); } }); }; ``` ### Example 3: Complex Validation with Options [Section titled “Example 3: Complex Validation with Options”](#example-3-complex-validation-with-options) This rule accepts configuration options: max-attributes.js ```javascript module.exports = function(HTMLHint) { HTMLHint.addRule({ id: 'max-attributes', description: 'Elements should not have more than the specified number of attributes', init: function(parser, reporter, options) { const maxAttrs = options || 5; // Default to 5 if no options provided parser.addListener('tagstart', (event) => { const attrCount = event.attrs.length; if (attrCount > maxAttrs) { reporter.warn( `Element has ${attrCount} attributes, but maximum allowed is ${maxAttrs}`, event.line, event.col, this, event.raw ); } }); } }); }; ``` ## Using Custom Rules [Section titled “Using Custom Rules”](#using-custom-rules) ### Loading Custom Rules [Section titled “Loading Custom Rules”](#loading-custom-rules) Use the `--rulesdir` option to load custom rules: ```shell --- # Load a single custom rule file npx htmlhint --rulesdir ./my-custom-rule.js index.html --- # Load all custom rules from a directory npx htmlhint --rulesdir ./custom-rules/ index.html ``` ### Enabling Custom Rules [Section titled “Enabling Custom Rules”](#enabling-custom-rules) After loading custom rules, you can enable them in several ways: #### In Configuration File [Section titled “In Configuration File”](#in-configuration-file) ```json { "no-div-tags": true, "data-attributes-required": true, "max-attributes": 3 } ``` #### Via Command Line [Section titled “Via Command Line”](#via-command-line) ```shell npx htmlhint --rulesdir ./custom-rules/ --rules no-div-tags,data-attributes-required,max-attributes:3 index.html ``` #### Inline in HTML [Section titled “Inline in HTML”](#inline-in-html) ```html <!-- htmlhint no-div-tags:true,data-attributes-required:true --> <html lang="en"> <body> <div class="component">This will trigger warnings</div> </body> </html> ``` ## Parser Events [Section titled “Parser Events”](#parser-events) The HTML parser provides several events you can listen to: * **`tagstart`**: Fired when a start tag is encountered * **`tagend`**: Fired when an end tag is encountered * **`text`**: Fired when text content is encountered * **`comment`**: Fired when a comment is encountered * **`cdata`**: Fired when CDATA is encountered * **`doctype`**: Fired when a DOCTYPE declaration is encountered ### Event Object Properties [Section titled “Event Object Properties”](#event-object-properties) Event objects typically contain: * **`tagName`**: The name of the tag * **`attrs`**: Array of attributes * **`line`**: Line number where the event occurred * **`col`**: Column number where the event occurred * **`raw`**: The raw HTML string for this element ## Reporter Methods [Section titled “Reporter Methods”](#reporter-methods) The reporter provides three methods for generating messages: * **`reporter.warn(message, line, col, rule, raw)`**: Creates a warning message * **`reporter.error(message, line, col, rule, raw)`**: Creates an error message * **`reporter.info(message, line, col, rule, raw)`**: Creates an info message ## Best Practices [Section titled “Best Practices”](#best-practices) 1. **Use arrow functions**: Always use arrow functions for event listeners to preserve the correct `this` context 2. **Use descriptive rule IDs**: Choose clear, descriptive names for your rules 3. **Provide helpful error messages**: Make error messages actionable and informative 4. **Handle options gracefully**: Always provide sensible defaults for rule options 5. **Test your rules**: Create test cases to ensure your rules work correctly 6. **Follow existing patterns**: Look at built-in rules for examples of good practices 7. **Document your rules**: Include clear descriptions and examples ## Directory Structure [Section titled “Directory Structure”](#directory-structure) When organizing multiple custom rules, you can use a directory structure: ```plaintext custom-rules/ ├── accessibility/ │ ├── aria-required.js │ └── semantic-headings.js ├── performance/ │ ├── image-optimization.js │ └── script-loading.js └── style/ ├── class-naming.js └── attribute-order.js ``` HTMLHint will recursively find all `.js` files in the specified directory and load them as custom rules. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) * **Rule not loading**: Check that your file exports a function and calls `HTMLHint.addRule()` * **Rule not running**: Ensure the rule is enabled in your configuration * **Parser errors**: Verify that you’re using the correct event names and object properties * **Silent failures**: Custom rules that fail to load are silently ignored - check your JavaScript syntax * **Incorrect rule reporting**: Make sure you’re using arrow functions for event listeners to preserve the `this` context --- # GitHub Code Scanning > Get HTMLHint to run on every pull request with GitHub Code Scanning. Thanks to the newly added SARIF formatter, HTMLHint can now be integrated with [GitHub Code Scanning](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/uploading-a-sarif-file-to-github) to automatically check your HTML code. ![Screenshot of the HTMLHint GitHub Code Scanning Integration](/img/htmlhint-github-code-scanning.png) This integration can help maintain code quality and ensures that HTML standards are met across your projects. Fixing issues will automatically remove the warnings from the Code Scanning tab in GitHub. ## Setting Up GitHub Code Scanning [Section titled “Setting Up GitHub Code Scanning”](#setting-up-github-code-scanning) To set up HTMLHint with GitHub Code Scanning, you need to create a workflow file in your repository. This file will define the steps to run HTMLHint on your HTML files whenever a pull request is made. 1. **Create a Workflow File**: In your repository, create a directory named `.github/workflows` if it doesn’t already exist. Inside this directory, create a file named `htmlhint.yml`. 2. **Define the Workflow**: Add the following content to `htmlhint.yml`: ```yaml name: HTMLHint (SARIF) Code Scanning on: pull_request: branches: - main workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: Set up Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 # If you need a website build script, include the steps here - name: Run HTMLHint (SARIF) run: npx htmlhint . --format sarif || true # Continue even if HTMLHint finds issues - name: Upload SARIF file uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 with: sarif_file: website/htmlhint.sarif category: HTMLHint if: always() ``` For a real-world example, you can see the Upload SARIF steps in the workflow for the HTMLHint website in the [HTMLHint GitHub repository](https://github.com/htmlhint/HTMLHint/blob/main/.github/workflows/website.yml#L39). Make sure to adjust the `sarif_file` path to match where HTMLHint outputs the SARIF file in your project. Note For private and internal repositories, code scanning is available when GitHub Code Security features are enabled for the repository. If you see the error GitHub Code Security or GitHub Advanced Security must be enabled for this repository to use code scanning, check that GitHub Code Security is enabled. For more information, see [Managing security and analysis settings for your repository](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-security-and-analysis-settings-for-your-repository). --- # Options > Options for configuring HTMLHint config files, formatters, and more. ## `configFile` [Section titled “configFile”](#configfile) CLI flag: `--config` Path to a JSON file that contains your [configuration object](/configuration/). Use this option if you don’t want HTMLHint to search for a configuration file. The path should be either absolute or relative to the directory that your process is running from (`process.cwd()`). ## `format` [Section titled “format”](#format) CLI flags: `--format, -f` Specify the formatter to format your results. Options are: * `checkstyle` * `compact` * `html` * `json` (default for Node API) * `junit` * `markdown` * `sarif` * `unix` ## `ignore` [Section titled “ignore”](#ignore) CLI flags: `--ignore, -i` A list of patterns of files or folders to ignore. For example, `--ignore="**/folder/**,**/folder_two/**"` ## `rulesdir` [Section titled “rulesdir”](#rulesdir) CLI flags: `--rulesdir, -R` Load custom rules from a file or directory. This allows you to extend HTMLHint with your own custom rules. ### Usage [Section titled “Usage”](#usage) ```shell --- # Load a single custom rule file npx htmlhint --rulesdir ./my-custom-rule.js index.html --- # Load all custom rules from a directory (recursively finds all .js files) npx htmlhint --rulesdir ./custom-rules/ index.html ``` ### Custom Rule Format [Section titled “Custom Rule Format”](#custom-rule-format) Custom rules should be JavaScript modules that export a function. The function receives the `HTMLHint` instance as a parameter and should register the custom rule using `HTMLHint.addRule()`. #### Example Custom Rule [Section titled “Example Custom Rule”](#example-custom-rule) my-custom-rule.js ```javascript module.exports = function(HTMLHint) { HTMLHint.addRule({ id: 'my-custom-rule', description: 'This is my custom rule description', init: function(parser, reporter, options) { // Rule implementation - Note: Use arrow functions for event listeners parser.addListener('tagstart', (event) => { const tagName = event.tagName.toLowerCase(); if (tagName === 'div') { reporter.warn( 'Custom rule: div tags are not allowed', event.line, event.col, this, event.raw ); } }); } }); }; ``` **Important**: Always use arrow functions for event listeners to ensure the correct `this` context is maintained when calling reporter methods. #### Using Custom Rules [Section titled “Using Custom Rules”](#using-custom-rules) After loading custom rules with `--rulesdir`, you can enable them in your configuration: ```json { "my-custom-rule": true } ``` Or via command line: ```shell npx htmlhint --rulesdir ./custom-rules/ --rules my-custom-rule index.html ``` ### Directory Loading [Section titled “Directory Loading”](#directory-loading) When specifying a directory, HTMLHint will: 1. Recursively search for all `.js` files in the directory 2. Load each file as a custom rule module 3. Skip any files that fail to load (errors are silently ignored) This makes it easy to organize multiple custom rules in a single directory structure. For detailed information on creating custom rules, see the [Custom Rules documentation](/usage/custom-rules/). --- # Visual Studio Code Extension > Get realtime linting feedback of your HTML in VS Code with the HTMLHint extension. ![Screenshot of the HTMLHint Extension for Visual Studio Code](/img/htmlhint-vscode-extension.png) Get realtime linting feedback in Visual Studio Code with the HTMLHint extension. This extension provides a seamless integration of HTMLHint into your development workflow, allowing you to catch HTML issues as you type. The HTMLHint extension will attempt to use the locally installed HTMLHint module (the project-specific module if present, or a globally installed HTMLHint module). If a locally installed HTMLHint isn’t available, the extension will use the embedded version (current version 1.8.0). ## Download [Section titled “Download”](#download) [VS Code Marketplace ](https://marketplace.visualstudio.com/items?itemName=HTMLHint.vscode-htmlhint) [Open VSX Registry ](https://open-vsx.org/extension/HTMLHint/vscode-htmlhint) The code is available on [GitHub](https://github.com/htmlhint/vscode-htmlhint).