HTML & CSS
Article

Write Better Markup with HTML Inspector

By Louis Lazaris

We often see quite a bit of discussion of optimization techniques for various areas of front-end development. One area that probably gets more overlooked than it should is HTML.

I’m certainly not a member of the ‘clean, non-presentational markup’ camp. But I do think consistency in markup is needed, especially when working on code that many developers are going to touch.

In this post, I’ll introduce a neat little tool that I’ve revisited recently that I think many development teams would do well to consider using: HTML Inspector by Philip Walton.

What is HTML Inspector?

As Philip explains on the repo’s README, it’s:

a highly-customizable, code quality tool to help you (and your team) write better markup. It aims to find a balance between the uncompromisingly strict W3C validator and having absolutely no rules at all (the unfortunate reality for most of us).

Although I somewhat disagree with Philip’s statement that the W3C validator is “uncompromisingly strict” (doesn’t he remember XHTML?), I certainly agree that many teams of developers likely lack a set of logical in-house standards to keep their markup maintainable and up to date.

After running HTML inspector, you’ll get a series of messages in your browser’s developer tools console, letting you know what issues in your HTML you should consider addressing.

HTML Inspector console warnings

You can see an example of HTML Inspector’s output in the image above, which is taken from a test I ran on one of my older projects, which I knew would likely have some questionable markup.

Install and Run HTML Inspector

If you’re doing testing on your own non-production code, you can simply include the HTML Inspector script in any of your pages, at the bottom, then run it by calling the primary method. Below is a brief description of the install methods, and then I’ll explain an even better method to get it to run on any website, remote or local.

To install and use via the command-line, you can use NPM, which requires PhantomJS:

npm install -g html-inspector

Or you can install with Bower for use in the browser:

bower install html-inspector

If you choose to download the tool manually, all you need to do is grab a copy of html-inspector.js from the project’s root directory, including it at the bottom of your document after all other scripts have loaded. Then you need to execute it, as shown below:

<script src="js/html-inspector.js"></script>
<script>
  HTMLInspector.inspect();
</script>

But unless you’re customizing the script, you don’t need to do any of the above. You can run it on any remote or local website in a few seconds, in any browser that has developer tools installed.

Open your browser’s developer tools console and run the following commands:

var htmlInsp = document.createElement('script');
htmlInsp.src = '//cdnjs.cloudflare.com/ajax/libs/html-inspector/0.8.1/html-inspector.js';
document.body.appendChild(htmlInsp);

After those are executed, you can then run the following in the console:

HTMLInspector.inspect();

Note: As pointed out in the comments, you have to run the final line as a separate command, after executing the first three lines, for this to work.

This script uses the HTML Inspector code as hosted on cdnjs.

In fact, I’ll make it even easier for you; you can create a bookmarklet with the code in this Gist. Once you have the bookmarklet added to your bookmarks bar, execute it on any website, open the console, then run HTMLInspector.inspect().

Try it on a really old project or pretty much any WordPress site if you want to see the kinds of warnings it spits out by default.

Of course, if you decide to customize HTML Inspector, you’ll need to download it and run your own configured version. So once you have your version ready, you can do the same as I’ve described above, but with a modified source URL.

HTML Inspector: The Great Parts

Here are some of the great things about this tool:

  • It’s one of a kind; I haven’t seen another tool that’s still active that’s comparable in terms of HTML linting. (If you know of one, let me know in the comments!)
  • Like other similar tools for CSS and JavaScript, you can customize it to only warn you for the rules you like.
  • You can write your own rules, which is probably the best feature of all.
  • No dependencies (note that the original blog post says it requires jQuery, but that was fixed about a week later).
  • It runs on the live DOM in the browser, not merely on the initial static HTML. This is great because it allows you to test on markup that gets added and modified dynamically by other scripts on the page.

A Great Tool for Dev Teams

As Philip explains on the aforementioned launch post, a great benefit to using HTML Inspector comes on teams where you might have a number of developers join for a short period of time (e.g. interns and new hires).

So imagine a new, less experienced developer working on your projects for three months, as a summer intern or something. It might normally take such an employee the full three months to get used to your way of writing code. But with HTML Inspector, all you need to do is have your customized rules in place. The new developer then just needs to run HTML Inspector with your custom rules, then read the warnings in the console and make any necessary adjustments to his code.

Changing the Defaults

There are two ways to customize HTML Inspector: Changing the default values in the config settings or (as mentioned) writing your own rules. Let’s look first at the default settings.

Running HTMLInspector.inspect() with the default setup executes the tool with the default values. The inspect() method takes an optional config object to change these. You can override the values by doing something like this:

HTMLInspector.inspect({
  domRoot: "main",
  excludeRules: ["validate-elements", "validate-attributes"],
  excludeElements: ["svg", "span", "input"],
  onComplete: function(errors) {
    errors.forEach(function(error) {
      console.warn(error.message, error.context)
    }
  }
});

Here I’ve decided not to validate elements or attributes and I’ve told the tool to exclude certain elements from being inspected.

For full details on modifying these defaults, check out the pertinent sections in the README file on the GitHub repo:

Writing Custom Rules

As mentioned, you might not agree with HTML Inspector’s default inspection warnings. If that’s the case, or if you want to add to those, the most powerful part of the tool is the ability to write your own rules.

You can do this using the following structure:

HTMLInspector.rules.add(name, [config], func)

The README gives the example of a dev team that previously used two specific data-* attribute namespaces that are now internally deprecated in favor of another method. Here’s how the code would look:

HTMLInspector.rules.add(
  "deprecated-data-prefixes",
  {
    deprecated: ["foo", "bar"]
  },
  function(listener, reporter, config) {

    // register a handler for the `attribute` event
    listener.on('attribute', function(name, value, element) {

      var prefix = /data-([a-z]+)/.test(name) && RegExp.$1

      // return if there's no data prefix
      if (!prefix) return

      // loop through each of the deprecated names from the
      // config array and compare them to the prefix.
      // Warn if they're the same
      config.deprecated.forEach(function(item) {
        if (item === prefix) {
          reporter.warn(
            "deprecated-data-prefixes",
            "The 'data-" + item + "' prefix is deprecated.",
            element
          )
        }
      })
    }
  )
});

(Take note that Philip is a madman and thus doesn’t use semi-colons at the end of lines!)

I’ve only scratched the surface of what’s possible with custom rules. I’m hoping to find some time to delve deeper into custom rules later on, and maybe I’ll write about it. In the meantime you can check out the relevant parts of the README for more info:

Conclusion

As is true of many developer tools, you’ll need a modern browser for HTML Inspector to work (for example, the browser needs to support ES5 methods, the CSSOM, and console.warn()).

As mentioned, I haven’t seen too many tools like this one (besides a regular validator). There was a general HTML Lint tool that seems to have disappeared. But other than that, I can’t remember another tool like this one – and certainly not one that’s as customizable and that runs on a live DOM.

If you’ve tried out HTML Inspector or know of another similar tool, feel free to let us know in the discussion.

Free Guide:

7 Habits of Successful CTOs

"What makes a great CTO?" Engineering skills? Business savvy? An innate tendency to channel a mythical creature (ahem, unicorn)? All of the above? Discover the top traits of the most successful CTOs in this free guide.

Comments
DoctorG

I get the following error "Object doesn't support property or method 'keys' "
Line 1535 of html-inspector.js is where this occurs.
How do I resolve this?

louislazaris

@DoctorG - What browser are you using?

EDIT: Object.keys() is supported pretty much everywhere. See this article on MDN.

Are you using Firefox 3.5 or IE8 or something like that? You can see a similar discussion on this in one of the closed issues on the GitHub repo.

DoctorG

I was running the script inside Homesite using Internet Explorer.
When I run it outside Homesite using Mozilla, it runs OK but does nothing.
I guess I just don't know how to use this tool.

louislazaris

After you run the script, you also have to call the method: HTMLInspector.inspect() to see the output in the console. You can run that in the console, or else just throw it at the bottom of your HTML, in a script tag, after you include the html-inspector.js script. Hope that helps.

muhamedhashem

var htmlInsp = document.createElement('script');
htmlInsp.src = '//cdnjs.cloudflare.com/ajax/libs/html-inspector/0.8.1/html-inspector.js';
document.body.appendChild(htmlInsp);
HTMLInspector.inspect();

when i run it directly in console in any browser i got an error
ReferenceError: HTMLInspector is not defined

is there anything need to be configured before or not

louislazaris

Oh I just realized, you have to run the first three lines by themselves, and then call the last line on a separate command. I didn't realize that at first, as I assumed that everyone would type the commands one line at a time.

I'll edit the article to reflect this. I should be able to explain more technically why it doesn't work when you paste the lines all together, but basically, the script that the code is creating isn't in the DOM until you execute the commands, so you have to execute the last line separately.

boriskaiser

@muhamedhashem & @louislazaris
You can use this snippet:

function _loadScript(url, callback) {
    // Adding the script tag to the head as suggested before
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;

    // Then bind the event to the callback function.
    // There are several events for cross browser compatibility.
    script.onreadystatechange = callback;
    script.onload = callback;

    // Fire the loading
    head.appendChild(script);
}

var HTMLInspector = {
  url: '//cdnjs.cloudflare.com/ajax/libs/html-inspector/0.8.1/html-inspector.js',
  init: function () {
    HTMLInspector.inspect();
  }
};

_loadScript(HTMLInspector.url, HTMLInspector.init);

I use it as a snippet in Chrome. It's pretty handy.
Snippet: https://gist.github.com/boriskaiser/d3835111498ae0ea09f2
Screenshot: http://i.imgur.com/laD3yxt.png

batia

While I am not against this type of projects (and the good things that they are Open Source and free), I'd rather use the professional-level validator that is compiled and updated with the latest rules to follow the standards and has excellent interface. I use the CSE HTML Validator v.12 (https://www.htmlvalidator.com). And there is nothing better, so far. Yes, it costs few bucks but every cent spent on software pays off.

AMA3_

What would be the best way to use this as part of a grunt build process?

louislazaris

@AMA3_

Which part? The running of the script? Or the correcting of the errors/warnings? I'm not sure if the latter could be automated, because the warnings would really depend on the markup. I guess it's possible, but it would be a pretty complex grunt task to write in order to do that. I don't know if that would be practical unless you had a really strict markup structure -- but even that would be difficult, in my opinion. But maybe someone else (or the author of the tool) has a better idea.

AMA3_

Running the script. I currently use grunt-html for linting but this sounds like it would do a more thorough job, maybe combined with grunt-html to cover everything.

louislazaris

@AMA3_

Use @boriskaiser's script as a bookmarklet (see his earlier comment). It works perfectly, just one click and the readout will be in the console. I think that's as good as anything, and I don't think a Grunt task is necessary.

Recommended
Sponsors
Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in Front-end, once a week, for free.