The dawn of HTML5 brought about a whole bunch of new elments. However, like CSS3, the specification is still relatively new and many of the browsers are slow to adopt the new elements. Elements such as <header>, <footer>, <nav>, <section>, <progress>, <template>, <aside>, <article>, and <canvas> do not possess widespread browser support just yet. Despite this level of inconsistent support, you should not be deterred from using these new tags, but it may be pertinent to be aware of their availability.

HTML Interfaces

It is the standardization of the HTMLElement object interface and the inherent hierarchy that makes it possible to reliably resolve an element’s type and therefore support. Included in the hierarchy is the HTMLUnknownElement interface which acts as a catch-all for invalid HTML elements. In other words, any element you define for which there is no associated interface in the HTMLElement hierarchy, will default to an instance of the generic HTMLUnknownElement interface. This is true whether you create the element via document.createElement or explicitly write it in your markup. This means we can leverage Object.prototype.toString to divulge an element’s internal [[Class]] property to ascertain if it is an unknown element:

function isElementSupported(tag){
    var element = document.createElement(tag);
    return Object.prototype.toString.call(element) !== '[object HTMLUnknownElement]';
}

Browser support for the interface is good as well, according to MDN, the HTMLUnknownElement interface is implemented on all the stock desktop and mobile browsers. Unfortunately, it seems IE8 and less does not support this, instead implementing a HTMLGenericElement interface.

Bear in mind that it may still be prudent to employ more complicated feature tests to determine support for the actual functionality of an element, such as the case with support for specific formats and codecs of the video and audio elements.

Inconsistencies

Unfortunately, there are inconsistencies with some elements and their associated interfaces. Some elements that are actually supported (or at least reported to be), inherit from the HTMLUnknownElement interface. For example, according to MDN and caniuse.com, the time element has been supported in Chrome since version 33. Yet its internal [[Class]] property points to the HTMLUnknownElement interface instead of the HTMLTimeElement interface as it should. As such, the datetime attribute inherent to the time element doesn’t exist:

'dateTime' in document.querySelector('time'); // false

All indications would suggest the time element does not exist in Chrome, despite what is being reported. In fact, even though the HTMLTimeElement interface is clearly defined within the specification, only Firefox 22+ has actually implemented it thus far. Opera had included it in version 11.50 only to remove it in version 15. It would seem the time element is in a state of limbo as different browsers decide how they want to implement it. Because of this, it may be too soon for the method above. However, moving forward, I would expect browsers to adhere to the specification and include the HTMLTimeElement interface.

Conclusion

Thanks to HTML interfaces, we can now learn from where elements are derived and the capabilities they inherit. Despite a few false negatives, I would expect this method to be a reliable solution for determining element support in the future, eliminating less reliable element inferences. You can see how your browser stacks up by viewing this CodePen. For the latest version of this code, please refer to the project on GitHub.