Layout Base Code
Tired of having to update all of you HTML files every time you update your layout? Here's a solution. We'll be using JavaScript to load a header and footer on every page. We'll also take care of active links and relative paths.
Keep in mind that users who have deactivated JavaScript in their browser will not be able to navigate your site.
If you have questions or feedback regarding the tutorial, please use the comment section at the end of the page! Don't be shy; I know it's frustrating when you're stuck, and I'd love to help.
What it will do
Your header and footer HTML will be in a single JavaScript file, so you'll only need to update it once.
HTML in your .html file:
<body>
<main>
your page here...
</main>
</body>
HTML rendered in the browser (the script automatically adds the header and footer):
<body>
<header>...</header>
<main>
your page here...
</main>
<footer>...</footer>
</body>
You can see the code in action here.
Tutorial
Step 1: The JS code
Create a javascript file (e.g. layout.js
) in the root of your project, and insert the following code:
// initLayout() is called once the DOM (the HTML content of your website) has been loaded.
document.addEventListener("DOMContentLoaded", function () {
// The layout will be loaded on all pages that do NOT have the "no-layout" class in the <body> element.
if (document.body.classList.contains("no-layout")) return;
// Inserting your header and footer:
document.body.insertAdjacentHTML("afterbegin", headerEl);
document.body.insertAdjacentHTML("beforeend", footerEl);
// Other initializations:
initActiveLinks();
// your code here...
});
/* ********************************* */
/**
* F U N C T I O N S
*/
function initActiveLinks() {
// This function adds the class "active" to any link that links to the current page.
// This is helpful for styling the active menu item.
const pathname = window.location.pathname;
[...document.querySelectorAll("a")].forEach((el) => {
const elHref = el.getAttribute("href").replace(".html", "").replace("/public", "");
if (pathname == "/") {
// homepage
if (elHref == "/" || elHref == "/index.html") el.classList.add("active");
} else {
// other pages
if (window.location.href.includes(elHref)) el.classList.add("active");
}
});
}
function getNestingString() {
// This function prepares the "nesting" variable for your header and footer (see below).
// Only change this function if you know what you're doing.
const currentUrl = window.location.href.replace("http://", "").replace("https://", "").replace("/public/", "/");
const numberOfSlahes = currentUrl.split("/").length - 1;
if (numberOfSlahes == 1) return ".";
if (numberOfSlahes == 2) return "..";
return ".." + "/..".repeat(numberOfSlahes - 2);
}
/* ********************************* */
/**
* H T M L
*/
const nesting = getNestingString();
/**
Use ${nesting} to output a . or .. or ../.. etc according to the current page's folder depth.
Example:
<img src="${nesting}/images/example.jpg" />
will output
<img src="./images/example.jpg" /> on a page that isn't in any folder.
<img src="../images/example.jpg" /> on a page that is in a folder.
<img src="../../images/example.jpg" /> on a page that is in a sub-folder.
etc.
*/
// Insert your header HTML inside these ``. You can use HTML as usual.
// You don't need to use the <header> element, but I recommend it.
const headerEl = `
<header>Header...</header>
`;
// Insert your footer HTML inside these ``. You can use HTML as usual.
// You don't need to use the <footer> element, but I recommend it.
const footerEl = `
<footer>Footer...</footer>
`;
Step 2: Load the JS
Load that javascript file on every page.
Show me how
- For your index file, or any other page that is not in a folder:
<script src="layout.js"></script>
- For any file that is in a folder:
<script src="../layout.js"></script>
- For files that are in a subfolder use
../../layout.js
, and so on. (add another ../ for every subfolder)
This line should be inserted into the head of your HTML file (before </head>).
Step 3: Paste your header/footer into the JavaScript file.
Paste your header and footer inbetween the ticks (``) of the variables headerEl and footerEl.
Use ${nesting}
to output a . or .. or ../.. etc according to the current page's folder depth. This is helpful when you want to use relative paths to images.
Example:
const headerEl = `<img src="${nesting}/images/example.jpg" />`;
... will output:
<img src="./images/example.jpg" />
on a page that isn't in any folder<img src="../images/example.jpg" />
on a page that is in a folder<img src="../../images/example.jpg" />
on a page that is in a sub-folder.- etc.
Step 4: Prepare your pages.
Remove your header and footer from the html files of your pages - They will be added via JavaScript. Make sure all page content is in a wrapper, I suggest using <main>
or <div>
:
<body>
<main>
your page here...
</main>
</body>
Step 5: Style
Now, style your layout with CSS like you would normally do.
My code adds the class "active" to any links that are linked to the current page. This makes it easy to style active menu links. Just make a CSS rule that checks for the "active" class,
e.g. .active { font-weight:bold; }
Done!
If you have page on which your layout should not be loaded, give the <body>
element the "no-layout" class.
I spend hours of my free time writing these tutorials that I publish for free. If you'd like to say thanks, please share this tutorial with others and/or buy me a coffee!
Comments
Leave your questions, problems, suggestions, requests and thanks here!
To share very long code or error messages with me, please upload it to pastebin (or a similar site) and include the link. This is to make sure you don't hit the max character limit on comments.