An Introduction to HTML Imports (Tutorial)
HTML Imports are a way to include external HTML documents and web components on a page without making an Ajax request or loading an iframe. Because of this capability, HTML Imports may lead to better page load times, new opportunities to reuse code, and easier integrations with some popular services like Google Maps.
At the time of writing, the HTML Imports technology is a W3C working draft, meaning that it is not yet a web standard and is not yet supported in all browsers. HTML Imports, however, can be used safely on a web page today with a polyfill like the one in Polymer.
HTML Imports for Reuse, Syndication
Philosophically, software developers, including web developers, are taught not to repeat themselves, but rather to organize code in models, objects, functions, or similar so that there is a single point of truth and an easy way to reuse components. Thanks to developers Dave Thomas and Andrew Hunt, this approach is generally called DRY development or DRY programming, meaning “don’t repeat yourself.”
In a way, HTML Imports support DRY development. Here is an example. Imagine that you have three messages that are repeated on several web pages, perhaps even web pages on different domains. Rather than copying and pasting or retyping these messages for each page or project, they could be included using the HTML Imports feature.
Here is the HTML for a file called messages.html
:
<div class="message-success">
<h2>Success</h2>
<p>Whatever you just did worked.</p>
</div>
<div class="message-failure">
<h2>Failure</h2>
<p>What a disappointment.</p>
</div>
<div class="message-ego-boost">
<h2>You are amazing.</h2>
</div>
To reuse the content from messages.html
, first include the document via HTML Imports. This amounts to adding a <link>
element with its rel
attribute set to “import” and its href
pointed at messages.html
, like this:
<link rel="import" href="messages.html">
We can write a short bit of JavaScript that accesses the imported messages.html
document and loads the “success” message on the page. Each of the other messages could also be loaded in the same way or all together depending on how one wanted to use them. Here’s the code:
var htmlImport = document.querySelector('link[rel="import"]');
var htmlDoc = htmlImport.import;
var htmlMessage = htmlDoc.querySelector('.message-success');
document.body.appendChild(htmlMessage.cloneNode(true));
The script completes four tasks:
- Selecting the link element
- Importing the external HTML document
- Selecting a section (node) of the imported DOM
- Adding a duplicate of the selected node to the current page
Just like that, the success message is now included on the page, similar to how an Ajax request works.
This example is, of course, overly simplified and would not be a very practical use for HTML Imports in a live application given that the success message, as written, was four lines of HTML and using HTML Imports to load it took seven lines of code. But if the content in messages.html
had been significantly more complex with, perhaps, a few hundred lines of HTML with supporting JavaScript and CSS, it would have still taken HTML Imports just seven lines of code to load it.
As a second imports reuse example, consider how scripting languages are often used to load reusable content into a page. The example below comes from the single.php
file of the Underscores starter theme for WordPress:
<?php
/**
* The template for displaying all single posts.
*
* @package _s
*/
get_header(); ?>
<div id="primary" class="content-area">
<main id="main" class="site-main" role="main">
<?php while ( have_posts() ) : the_post(); ?>
<?php get_template_part( 'content', 'single' ); ?>
<?php _s_post_nav(); ?>
<?php
// If comments are open or we have at least one comment, load up the comment template
if ( comments_open() || '0' != get_comments_number() ) :
comments_template();
endif;
?>
<?php endwhile; // end of the loop. ?>
</main><!-- #main -->
</div><!-- #primary -->
<?php get_sidebar(); ?>
<?php get_footer(); ?>
Notice, there are several places in the single.php
code example were external resources are referenced and used, including to get the page header, load a template, load post navigation, load a sidebar, and load the footer.
The way that the PHP script is calling outside resources is analogous to how HTML Imports might be used to add content and features to a page. This point may become more clear when one considers that HTML Imports are part of the HTML Web Components draft.
Web Components have four building blocks, if you will. Eric Bidelman, who works in developer relations at Google and presented the Web Components talk at Googio I/O in 2013 and 2014, described these blocks:
- Shadow DOM – provides DOM and style encapsulation.
- HTML Templates – are inert chunks of clonable DOM elements that serve as a scaffold or blueprint.
- Custom Elements – expand HTML’s existing vocabulary and extend DOM objects.
- HTML Imports – allow web components to be packaged, shared, distributed, and reused.
With web components in mind, you might be able to imagine how you could use HTML Imports to load significant features and functions to any HTML page. Here are some theoretical web components that HTML Imports could load for you.
- Checkout with PayPal – drop an
<x-paypal-express key="6827364828736" callback="some.html">
tag on the page, passing a nested HTML form, and you may be able to add secure checkout to any page. - Email Subscription Form – Using HTML Imports, adding an email subscription form might be as simple as importing an external HTML document and adding an
<email-subscribe>
tag. - Google Maps – a frequently used HTML Imports example is adding a Google Map with a simple custom element
<google-map lat="37.790" long="-122.390">. This works, of course, only after HTML Imports has loaded the document defining this custom tag.
All of these examples rely on HTML Imports for inclusion.
A third example of how HTML Imports might help web and app developers comes from Bidelman, who suggested that Imports might more effectively load some frameworks or other bundles of HTML and associated resources.
In his specific example, Bidleman loaded Bootstrap with its many files and dependencies in a single bundle.
<link rel="import" href="bootstrap.html">
The source called bootstrap.html
would look similar to what you would find in the <head>
of a Bootstrap-powered site:
<link rel="stylesheet" href="bootstrap.css">
<link rel="stylesheet" href="fonts.css">
<script src="jquery.js"></script>
<script src="bootstrap.js"></script>
<script src="bootstrap-tooltip.js"></script>
<script src="bootstrap-dropdown.js"></script>
Browser Support for HTML Imports
As mentioned above, there is presently little browser support for HTML Imports, with only Chrome 36+, Chrome 37+ for Android, and Opera 23+ offering native support by default. Firefox 32+ does support HTML Imports, but only if the user enables them in about:config
.
There are polyfills that will make the feature available in nearly any browser. Perhaps, the most robust is the aforementioned Polymer Imports polyfill.