In the last article on this topic I explained the concept of page decor and mentioned options for implementing it. In this article I will provide an introduction to HTMLDecor.js which provides a javascript solution.


This page uses HTMLDecor.js so I'll use it to demonstrate.

Without HTMLDecor the page is just the HTML content of this article. You can see the undecorated page by appending a ?nodecor query to the page URL.

The decor is defined in a normal HTML file which is independent of this page and therefore can be modified without changing the HTML of this page.

HTMLDecor merges the decor into the undecorated page resulting in what you are viewing now.

Currently this isn't particularly impressive because the decor is very simple. But when I do get around to providing a more feature-rich decor I won't need to update this page at all. I could even give this page an expiry date of one year from now and still be able to update the decor at any time.

How it works

The merging principle for HTMLDecor is that the decor provides generic page layout, styles and meta-data, and the page provides content and, if necessary, more specific styles and meta-data.

In the merged <head>, tags from the decor document are inserted ahead of the existing tags from the page. This means that stylesheets from the decor have lower priority. If there is a clash between the decor and the page then the decor loses, so that <title> and <meta> tags won't be inserted if they already exist in the page.

Merging the page and decor <body> sections is basically two steps:

  1. insert the complete content of the decor body into the start of the page body
  2. for each original node of the page body:
    • if it is an element with @id, and the id matches that of a target-element in the decor body, then move the element into the decor, replacing the target-element.
    • otherwise, remove the node from the document.



The <head> of this page looks like:

  <script src="/HTMLDecor.js"></script>
  <link rel="meeko-decor" type="text/html" href="/blog/decor.html" />
  <title>HTML Decor II</title>
  <link rel="stylesheet" href="/nodecor.css" title="nodecor" />
I've rearranged and removed some tags so only the relevant HTML is shown.

Let's look at the <head> line-by-line.

<script src="/HTMLDecor.js"></script>

This line includes the HTMLDecor script in the page.

<link rel="meeko-decor" type="text/html" href="/blog/decor.html" />

This line links to the decor file. The HTMLDecor script looks for the first <link> tag with @rel="meeko-decor". The type of decor file should be declared as text/html.

<title>HTML Decor II</title>

Because this page already has a title, the title from the decor document will be ignored.

<link rel="stylesheet" href="/nodecor.css" title="nodecor" />

Any stylesheet in the page, whether <link rel="stylesheet" /> or <style>, that has @title="nodecor" will be removed from the page when decor has been successfully loaded. This allows some basic styles to be applied to the page in the case when decor can't be loaded, or if scripting is disabled in the browser.


The <body> of this page looks like:

  <div role="navigation">
      <a href="/" title="Home"></a> /
      <a href="/blog/">Blog</a>
  <div role="main" id="main">
    Main content here

There are two child-elements of the <body>, but the first one has no @id, so it will be removed from the page, while the second child - @id="main" - will be relocated to where-ever the matching decor element is placed.

Although the first child is removed by HTMLDecor, it is not irrelevant - it will still be seen in browsers when scripting is disabled, and it is processed by search-engines. I would suggest providing links to the site and section of the site in which the page is located. This prevents search-engines, etc arriving at the page and finding it to be a dead-end.

What about <script> ?

To understand how scripts are handled, you need some insight into how decor documents are loaded. Firstly, the decor is fetched with XMLHttpRequest. Then there is some pre-processing to handle various issues (including the option to disable scripts). The decor HTML is written into an iframe (which takes care of HTML parsing). Lastly the decor is merged into the page.

Scripts within the page are not handled by HTMLDecor. The only consideration is how they interact with content, styles and scripts from the decor document.

Scripts in the decor document are handled by the following rules:

Future articles will deal with tips and best-practises for using HTMLDecor.

Other stuff

Project page

HTMLDecor has a project page at github. The README page contains a few more details.


At this stage, installation involves downloading the HTMLDecor script from

There is also a test page associated with this installation which provides a simple demonstration of HTMLDecor in action. View it with and without decor.


HTMLDecor is available under MPL 2.0.

See the MPL 2.0 FAQ for your obligations if you intend to modify or distribute HTMLDecor or part thereof.