It’s extremely surprising to me that HTML has never had any way to include other HTML files within it. Nor does there seem to be anything on the horizon that addresses it. I’m talking about straight up includes, like taking a chunk of HTML and plopping it right into another. For example the use case for much of the entire internet, an included header and footer for all pages:
...
<body>
<include src="./header.html"></include>
Content
<include src="./footer.html"></include>
</body>
...
That’s not real, by the way. I just wish it was.
People have been looking to other languages to solve this problem for them forever. It’s HTML preprocessing, in a sense. Long before we were preprocessing our CSS, we were using tools to manipulate our HTML. And we still are, because the idea of includes is useful on pretty much every website in the world.
Use PHP
Can you use PHP instead?
...
<body>
<?php include "./header.html" ?>
Content
<?php include "./footer.html" ?>
</body>
...
This will perform the include at the server level, making the request for it happen at the file system level on the server, so it should be far quicker than a client-side solution.
Use Gulp
What’s even faster than a server-side include? If the include is preprocessed before it’s even on the server. Gulp has a variety of processors that can do this. One is gulp-file-include.
That would look like this:
...
<body>
@@include('./header.html')
Content
@@include('./footer.html')
</body>
...
And you’d process it like:
var fileinclude = require('gulp-file-include'),
gulp = require('gulp');
gulp.task('fileinclude', function() {
gulp.src(['index.html'])
.pipe(fileinclude({
prefix: '@@',
basepath: '@file'
}))
.pipe(gulp.dest('./'));
});
Looks like this particular plugin has fancy features where you can pass in variables to the includes, making it possible to make little data-driven components.
Use Grunt
This is what the grunt-bake plugin does. You’d configure Grunt to process your HTML:
grunt.initConfig({
bake: {
your_target: {
files: {
"dist/index.html": "app/index.html",
}
}
}
});
Then your HTML can use this special syntax for includes:
...
<body>
<!--(bake header.html)-->
Content
<!--(bake footer.html)-->
</body>
...
Use Handlebars
Handlebars has partials.
You register them:
Handlebars.registerPartial('myPartial', '{{name}}')
Then use them:
{{> myPartial }}
There is also fancy features of this that allow for evaluation and passing data. You’ll still need a processor to run it, probably something like gulp-handlebars.
Speaking of templating languages which make use of curly braces… Mustache has them, too.
Use Pug
Pug is an HTML preprocessor that has a whole new syntax for HTML that is a bit more terse. It’s got includes though.
...
body
include ./header.html"
p Content
include ./footer.html"
...
Then you run it with something like gulp-pug.
Use Nunjucks
I love me some Nunjucks! Nunjucks has includes. You’d do it like this:
...
<body>
{% include "./header.html" %}
Content
{% include "./footer.html" %}
</body>
...
If you put that in a file called index.njk
, you could process it with a simple Node script into index.html like this:
const nunjucks = require("nunjucks");
const fs = require("fs");
fs.writeFile("index.html", nunjucks.render("index.njk"), function(err, data) {
if (err) console.log(err);
console.log("Compiled the Nunjucks, captain.");
});
Or process it with something like gulp-nunjucks.
11ty has Nunjucks built-in, along with many of the other mentioned so far. Might be good for you if you’re actually building a little site.
Use Ajax
Say you had…
<body>
<header></header>
Content.
<footer></footer>
</body>
You could fetch the contents for the header and footer from respective files and dump the contents in.
fetch("./header.html")
.then(response => {
return response.text()
})
.then(data => {
document.querySelector("header").innerHTML = data;
});
fetch("./footer.html")
.then(response => {
return response.text()
})
.then(data => {
document.querySelector("footer").innerHTML = data;
});
Speaking of JavaScript… If you’re building your site using a JavaScript framework of just about any kind, building through components is kind of the main deal there and breaking parts you want to include in other files should be no problem. Some kind of import Header from "./header.js";
and <Header />
is the territory you’d be in in React land.
Use iframes
You could do this:
<body>
<iframe src="./header.html"></iframe>
Content.
<iframe src="./footer.html"></iframe>
</body>
But the content in those iframes does not share the same DOM, so it’s a bit weird, not to mention slow and awkward to style (since iframes don’t know the heights of their contents).
Scott Jehl documented a cool idea though: You can have the iframe inject the content of itself onto the parent page then remove itself.
<body>
<iframe src="header.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"></iframe>
Content.
<iframe src="footer.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"></iframe>
</body>
Kolya Korruptis wrote in with this adaptation which will include more than the first child of the body in case your HTML file has that:
<iframe src="included.html" onload="this.insertAdjacentHTML('afterend', (this.contentDocument.body||this.contentDocument).innerHTML);this.remove()"></iframe>
Use Jekyll
Jekyll is a Ruby-based static site generator with includes. You keep your includes in the /_includes/
folder, then:
<body>
{% include header.html %}
Content.
{% include footer.html %}
</body>
Jekyll is a big one, so I’m calling it out here, but there are a ton of static site generators and I’d wager any of them can do includes.
Use Sergey
OK, I’ll call out one more SSG because it’s new and super focused. Sergey has a web components style format:
<body>
<sergey-import src="header" />
Content.
<sergey-import src="footer" />
</body>
You’d name the files header.html
and footer.html
and put them in /includes/
and then it’ll make a build with the includes processed when you run the npm script it has you do.
Use Apache SSI
Apache, a super duper common web server, can do includes. You do it like this:
<body>
<!--#include file="./header.html" -->
Content
<!--#include file="./footer.html" -->
</body>
But you need the right Apache configuration to allow stuff. I tried my best to get a working demo going but didn’t have much luck.
I tried using .htaccess
within a folder on an Apache server and flipping on what I thought was the right stuff:
Options +Includes
AddType text/html .html
AddOutputFilter INCLUDES .html
I’m sure there is some way to get it working though, and if you do, it’s kinda neat that it needs zero other dependencies.
Use CodeKit
Mac only, but CodeKit has a special language called Kit it processes where 90% of the point of it is HTML includes. It uses special HTML comments:
...
<body>
<!-- @import "./header.html" -->
Content
<!-- @import "./footer.html" -->
</body>
...
Use Dreamweaver
Lol jk. But it really is a thing. DWTs, baby.
Holy Crap
That’s a lot of ways, isn’t it?
Like I said at the top, it’s very surprising to me that HTML itself hasn’t addressed this directly. Not that I think it would be a great idea for performance to have <include>
statements that trigger network requests all over our code, but it seems in-line with the platform. Using ES6 imports directly without bundling isn’t a great idea always either, but we have them. @import
ing CSS within CSS isn’t a great idea always, but we have it. If the platform had a native syntax, perhaps other tooling would key off that, much like JavaScript bundlers support the ES6 import format.
What about the Webpack HTML plugin? I use it for my portfolio and it does a pretty solid job considering variables and includes!
Laugh, but Dreamweaver templates are the single biggest thing I miss about web dev circa 2001. Dead simple, flexible, WYSIWYG previews, and no brittle dependencies or weird build errors.
In the interest of completeness, I have done this with jQuery before. (I’m sure it counts as ‘use AJAX’, but still.)
Woa, dreamweaver made the list but no SHTML, sad.
You could also use pHTML if you want it to feel native.
https://github.com/phtmlorg/phtml-include
Doesn’t Apache SSI require the HTML files to use a .shtml extension?
The default extension is .shtml but you can add this line to your .htaccess file if you prefer to stick to .html:
AddHandler server-parsed .html
SSI: Server Side Include
Server Side Includes (SSIs) are PERL language-based commands that allow information to be gathered from the server. PERL and CGI have been around since the inception of the Internet and all these other high level languages are based on PERL’s capabilities.
The concept is to use the server to gather and post information. That way you are not dealing with browser version problems. The thing that is being included is included before it gets to the browser so versions never come into play.
Most UNIX servers are set up to run SSI. Those on WindowsNT-based servers might have to go with ASP to get a lot of these effects, but check first before you decide you can’t run these commands. You might be able to.
Formore info check out:
https://www.htmlgoodies.com/beyond/webmaster/article.php/3473341/SSI-The-Include-Command.htm
SSI was my go-to for a long time. I used it with Apache, IIS and Nginx. You really need control of the server to guarantee configuration though. Later in the grunt days I used bake and nunjuks. These days it’s all React. Makes you wonder if React would be a thing had your include tag existed from the start…
NHTML imports were supposed to be the original way to take care of this. Imports were party of the web components proposal, but browsers weren’t implementing the standard.
https://www.html5rocks.com/tutorials/webcomponents/imports/
Actually, the first example you posted it’s almost real. I’ve used that exact syntax in a project that uses Parcel as a bundler. It’s super easy to setup and all you have to do is
parcel build index.html
and you’re good to go.You can get the server side includes to work by using
include virtual
instead ofinclude file
here’s an article I wrote about this
https://www.chromestatus.com/feature/5144752345317376 it exists actually, but it’s being obliterated in Chrome in June because it never got full support. Cheers.
HTML imports are very cool and I know it makes a lot of people sad that they are basically dead.
But also, I’m 99% sure they were never intended to just slap a chunk of HTML into another HTML document like an include does.
If doing emails uses MJML. https://mjml.io/documentation/#mj-include
Imports didn’t get full support from Mozilla because the spec had problems.
One of the biggest issues was that you still needed to write Javascript to get them working — and at the point where you’re using Javascript, you might as well just polyfill your own import component. Mozilla felt like in light of the fact that imports with Javascript are pretty easy to do, and in light of the fact that there’s disagreement in the community about what the “best” way to do them is, it was better to take a Progressive Web approach and wait and see how the community evolved.
I think it was absolutely the right decision to reject them. What Chris is talking about is something much simpler and more transparent that can be used without diving into web components.
If you are running a cache server like varnish then you can use esi. With esi you not only can build your web pages as components but the components can be on different servers.
Wow loved to see the are so many ways to include files… Specially the iframe option with self destruction..
Ever heard of frames, frameset?
You missed out “with Web Components”: https://www.github.com/gustafnk/h-include
Also
https://github.com/github/include-fragment-element
Yes there are lots of way to preprocess this on the server. But unfortunately there is no HTML standard way of doing this integrated into the language itself. And that’s the real issue. Sure you can do it in a server framework, sure you can do it with AJAX, sure you can do it via an apache hack – but the real thing is still lacking. You don’t have a native HTML import inside the HTML language. There is no way to compose two pages into one. And that’s sad.
I thought of this the other day, and how important it would be in the component-driven world of front end frameworks. It’ll help with re-usability and modularization, and all natively. How interesting would that be?
Nice. It’s probably worth adding that the PHP option can also be used as a client side technique similar to grunt/gulp etc.
From what I remember HTML imports were supposed to do the job and they’re actually dying a death by deprecation…
I’m pretty sure that Jekyll’s
include
magic is compliments of Liquid, so you shouldn’t need the entire generator if that’s all you want.Another cool method is using web components.
Define a custom element i.e.
<my-header>
write the template code and include the javascript.
I really like them
Wow cool!
I’ve really enjoyed using file-include in my NPM scripts the past couple years but have recently become a fan of using Handlebars with Panini like Foundation uses in their advanced build options.
Is there any talk amongst the working groups or vendors as to why there is no native solution?
For Codekit Kit language includes, Prepros supports this on Mac and Windows.
Another way to include HTML using Gulp or Grunt is with the processhtml plugin. The syntax uses HTML comments:
It also has the advantage of including different files per environment. For example, you may want to use minified HTML for production.
FYI, for the PHP include option to work you will need to have told your web server to process .html files as if they were PHP. How this is achieved depends very much on your server set-up but regardless of that, it will adversely affect performance since where before your server was just grabbing and returning a text document, now it has to spawn a PHP thread and process the HTML as if it were PHP code. Even for a simple task like this, it will inevitably consume more CPU/memory resources for every page — even if your page contains no PHP at all, it will still be parsed by PHP.
If you’re using Apache then for a simple include like this SSIs are a far better option. Not sure what your issue might have been (although using .htaccess will only work if the underlying Apache configuration allows for it), but I’ve used it very successfully in the past. It’s highly optimised and therefore (in my experience) has negligible impact on performance.
Love the article Chris. It is kinda annoying, that would probably make our lives much easier, probably CMS usage would drop significantly, I remember I used Drupal or WordPress tens of times instead just HTML because I was in between, didn’t quite needed to the whole forests with the banana but still lack the features HTML offers. Also, the frameworks were too much for such a tiny project… Hope one day…
Cheers!
I use this for simple menus at the top of pages:
Works well for simple pages.
Hi Chris, thank you for all the great articles, I’ve learned a lot through them!
You probably already know that it’s possible to use the syntax you describe in your top example:
<include src="path_to/partial_file.html></include>
using posthtml Include Plugin.How about PostHTML? https://github.com/posthtml/posthtml-include
I’m embarrassed to admit that my portfolio site that I originally developed back in around 2002 (and has barely been updated since) used/uses shtml. https://www.yourhtmlsource.com/sitemanagement/includes.html
It was surpassingly easy for me to set up and use exactly like you mention for headers and footers.
Use a PWA to cache the header/footer.
How do you highlight the currently ‘selected’ top level menu? Parse the header for the current URL and add a class? It would be nice to see that built into a PWA solution.
There is another way i have used before.
First– save the file with .inc extension.
Secont–go to web server and create or update the support for .Inc extension and rendering engine html in this case. This also can be done using ht.access or web.config file.
do npm scripts please!!
You can also use a template engine like smarty. Some web shops I know use this method.
https://www.smarty.net/docs/en/language.function.include.tpl
Is there any reason to believe an HTML include would out perform other methods? I’m not sure I understand why someone would need this for static HTML.
Back in the day of ASP we used SSI (Server Side Includes)
What happened to SSI?
Can we use CSS ?
p:first-child{
content:”Add Text here…”;
}
Twig! More powerful than Handlebars/Mustache but still very easy to use (very similar syntax).
To get SSI running on Apache, you want to use this in your .htaccess configuration:
Options +Includes
AddHandler server-parsed .shtml
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
If someone wants to parse regular .html files, it’s better to use XBitHack (unless you’re running Apache on Windows, of course):
XBitHack on
…along with:
chmod +x somepage.html
….for files you want parsed. Keep in mind: “This directive only affects files associated with the MIME-type text/html.” Make sure your installation of Apache actually has mod_include installed and enabled, mod_expires as well to avoid issues with SSI when using certain directives.
Bringing includes to html in less than 1kb of javascript
https://github.com/Paul-Browne/HTMLInclude
If you want a native alternative, see this discussion: https://github.com/whatwg/html/issues/2791
IIS can do SSI’s as well. I’ve been using SSI’s on apache and IIS for years. The implementation in IIS is more flexible: you can access files that are higher up the filetree with relative paths(../../../otherdirectory/file.shtm), while apache needs absolute paths for that (/otherdirectory/file.shtml)
Oh man! thank you so much, I finally able to include HTML snippets statically. Gulp was my favourite option and it works perfectly.
Huge fan of CodeKit’s
.kit
language. I use it via Gulp…gulp-kit
. Highly recommend it for simple static sites.There used to be a thing called shtml that did this too.
Perfect! I managed to get it working right away using the html include on apache with the .htaccess code you created. i am working on a flat site at the moment and this worked a treat!
document.write did the trick for me. No libraries, frameworks, server side thingies.
Hi:
It still appears that the original question has not be answered: Is there a simple way to include an html file within an html file? I’ve been hand coding html for 25 years so what I do is fairly basic but adequate my needs and my users’ needs. Call me a Luddite, fine. ;-)
But one would think as is noted in the start of this thread that this would be part of html 0.01.
Something equivalent to “img src picture.gif” but for html. ;-)
Second best would be a concrete example rather than just code snippets without context because one assumes everyone knows what the ?!#% is being implied.
I want something like: “html src file.html” that basically inherits the parameters of the calling html document so it drops in as though the text were inserted at that spot. Essentially calling blocks of text from multiple Web pages so they don’t need to be duplicated and maintained individually inside the main html document.
Thanks,
— sam