HTML-validate

Offline HTML5 validator. Validates either a full document or a smaller (incomplete) template, e.g. from an AngularJS or Vue.js component.

Learn more

Features

Fragments and components

In addition to validating plain .html files HTML-validate can also validate sources inside .js components (or any other source) by extracting HTML fragments (transforming).

Neither .html files or component fragments need to be a complete document (e.g. doctype is not required).

Transformed sources can also be postprocessed to handle data-bindings from different frameworks, e.g. :id will still be understood the same way id would.

Learn more about transforming sources.

Offline

Many validators will behind the scene upload the markup to online services such as W3C. HTML-validate performs all validation locally, no markup leaves your machine, providing a faster and more secure response which can easily be integrated with tools and IDEs.

This means your source code is safe and is never leaked outside of your organization.

Strict parsing

When rendering a document it is useful to try to correct malformed markup but a validator should be strict. No corrections, assumptions or guessing is done. If the markup is invalid the parser will tell you so.

By ensuring the markup is strictly valid it reduces the amount of bugs where different browsers autocorrect the markup differently (this is especially true for mobile browsers).

HTML5 content model

Each element is matched against metadata for deeper logic and analysis such as whenever an element is allowed in the current context or if a required element is missing.

  • permitted ancestors and descendants
  • permitted order and occurrences
  • deprecated elements and attributes
  • flow ("block"), phrasing ("inline") etc

Learn more about writing element metadata for custom components.

Accessibility tests

Validates technical aspects of A11Y guidelines such as WCAG 2.2.

Extendable

Write your own element metadata, rules and/or business logic.

Write your own shareable configurations or plugins.

Learn more about writing rules and writing plugins.

Frameworks

First-class support for:

Examples

Content model

<footer>
  <fieldset>
    <p>Lorem ipsum dolor sit amet</p>
    <legend>Consectetur adipiscing elit</legend>
  </fieldset>

  <main>
    <blink>(c) 2018 Initech</blink>
  </main>

</footer>
error: Element <legend> must be used before <p> in this context (element-permitted-order) at inline:4:6:
  2 |   <fieldset>
  3 |     <p>Lorem ipsum dolor sit amet</p>
> 4 |     <legend>Consectetur adipiscing elit</legend>
    |      ^^^^^^
  5 |   </fieldset>
  6 |
  7 |   <main>


error: <main> element is not permitted as a descendant of <footer> (element-permitted-content) at inline:7:4:
   5 |   </fieldset>
   6 |
>  7 |   <main>
     |    ^^^^
   8 |     <blink>(c) 2018 Initech</blink>
   9 |   </main>
  10 |


error: <blink> is deprecated (deprecated) at inline:8:6:
   6 |
   7 |   <main>
>  8 |     <blink>(c) 2018 Initech</blink>
     |      ^^^^^
   9 |   </main>
  10 |
  11 | </footer>


3 errors found.

Accessibility

<img src="logo.png">
<button onclick="myFunction();">Click me!</button>

<div class="field-wrapper">
  <strong>Name: </strong>
  <input type="text" name="name">
</div>
error: <img> is missing required "alt" attribute (wcag/h37) at inline:1:2:
> 1 | <img src="logo.png">
    |  ^^^
  2 | <button onclick="myFunction();">Click me!</button>
  3 |
  4 | <div class="field-wrapper">


error: <button> is missing recommended "type" attribute (no-implicit-button-type) at inline:2:2:
  1 | <img src="logo.png">
> 2 | <button onclick="myFunction();">Click me!</button>
    |  ^^^^^^
  3 |
  4 | <div class="field-wrapper">
  5 |   <strong>Name: </strong>


error: <input> element does not have a <label> (input-missing-label) at inline:6:4:
  4 | <div class="field-wrapper">
  5 |   <strong>Name: </strong>
> 6 |   <input type="text" name="name">
    |    ^^^^^
  7 | </div>


3 errors found.

Custom components

<my-inline>
  <my-block></my-block>
  <my-deprecated></my-deprecated>
</my-inline>
error: <my-block> element is not permitted as content under <my-inline> (element-permitted-content) at inline:2:4:
  1 | <my-inline>
> 2 |   <my-block></my-block>
    |    ^^^^^^^^
  3 |   <my-deprecated></my-deprecated>
  4 | </my-inline>


error: <my-deprecated> is deprecated: replaced with <my-other> (deprecated) at inline:3:4:
  1 | <my-inline>
  2 |   <my-block></my-block>
> 3 |   <my-deprecated></my-deprecated>
    |    ^^^^^^^^^^^^^
  4 | </my-inline>


2 errors found.