16.3 Reusable HTML Templates: Partials & Includes
In large web projects, repeating the same HTML (headers, footers, navigation bars, widgets) in multiple pages leads to maintenance nightmares. Reusable templates (aka “partials” or “includes”) allow you to define a snippet once and embed it in many pages. This promotes:
- DRY (Don’t Repeat Yourself)
- Maintainability – one change propagates everywhere
- Consistency of look & feel
- Separation of concerns – structure vs. data
1. Server-Side Includes (SSI)
SSI is supported by web servers like Apache or Nginx. You place special directives in HTML files, and the server replaces them with external snippets before delivering to the client.
1.1. Apache SSI Example
<!-- Above directive tells Apache: * virtual: path relative to document root * include the contents of header.html -->
1.2. Nginx SSI Example
<!--
In nginx.conf, enable ssi on location:
location / {
ssi on;
}
-->
2. Server-Side Templating Engines
Languages like PHP, Node.js, Ruby offer templating engines that let you write templates with placeholders for data and partials for repeated HTML.
2.1. PHP include/require
<!-- index.php --> <?php include 'includes/header.php'; ?> <main> <h2>Welcome</h2> <p>This is homepage.</p> </main> <?php include 'includes/footer.php'; ?> <!-- includes/header.php --> <!DOCTYPE html> <html> <head><title>My Site</title></head> <body> <nav>…</nav>
2.2. EJS (Embedded JavaScript Templates)
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<%- include('partials/header') %>
<main>
<%- body %>
</main>
<%- include('partials/footer') %>
</body>
</html>
<% layout('layout', { title: 'Home', body: 'Welcome to the site!' }) %>
2.3. Handlebars
<!DOCTYPE html>
<html>
<head><title>{{title}}</title></head>
<body>
{{> header}} <!-- partial called 'header' -->
<main>
{{{body}}}
</main>
{{> footer}}
</body>
</html>
3. Client-Side Includes & Templates
When you can’t or don’t want server-side processing, you can fetch snippets via JavaScript or use the HTML5 <template> element.
3.1. HTML5 <template> Tag
<!-- index.html -->
<template id='card-template'>
<div class='card'>
<h3></h3>
<p></p>
</div>
</template>
<div id='cards-container'></div>
<script>
// Sample data
const items = [
{ title:'First', text:'Lorem ipsum' },
{ title:'Second', text:'Dolor sit' }
];
const tpl = document.getElementById('card-template');
const container = document.getElementById('cards-container');
items.forEach(item => {
const clone = tpl.content.cloneNode(true);
clone.querySelector('.title').textContent = item.title;
clone.querySelector('.text').textContent = item.text;
container.appendChild(clone);
});
</script>
3.2. Fetch External Snippet
<!-- index.html -->
<div id='nav-placeholder'></div>
<script>
fetch('/includes/nav.html')
.then(res => res.text())
.then(html => {
document.getElementById('nav-placeholder').innerHTML = html;
});
</script>
4. Web Components
Web Components let you define custom HTML elements with their own template and Shadow DOM.
<!-- my-component.js -->
const template = document.createElement('template');
template.innerHTML = `
<style>
.badge { background: red; color: white; padding: 2px 4px; }
</style>
<span class='badge'><slot>Badge</slot></span>
`;
class BadgeElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({mode:'open'});
shadow.appendChild(template.content.cloneNode(true));
}
}
customElements.define('my-badge', BadgeElement);
<!-- Usage in HTML -->
<script src='my-component.js'></script>
<my-badge>New</my-badge>
5. Pros & Cons Comparison
| Method | Pros | Cons |
|---|---|---|
| SSI (Apache/Nginx) | Simple, no code | Limited logic, server config required |
| Server-Side Templating | Powerful, full logic, data binding | Requires server environment |
| HTML5 <template> | Pure HTML & JS, no build step | Needs JavaScript, potential FOUC |
| Fetch Includes | Works on any static host | Overhead of network request |
| Web Components | Encapsulation, reusability | Browser support & polyfills |
6. Best Practices
- Choose server vs client approach based on SEO and performance needs.
- Keep partials small & logically grouped (header, footer, widgets).
- Use clear naming conventions (e.g.,
_header.html). - Cache static includes when possible to reduce requests.
- Version control your template files separately for easier tracking.
Leave a Reply
You must be logged in to post a comment.