I am trying to make a github pages site without a static site template/builder. I want to put the navigation in a separate file so if I make a change I don't need to copy them to all the other html files. I have gotten jQuery to do this BUT it messes up the layout compared to when I just place the nav bar in index.html and I cannot understand why.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="/CSS/styles.css" media="all">
<title>Soup's website</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<!-- jquery library -->
</head>
<body>
<div id="nav-placeholder"></div>
<div class="header">
<t>header</t>
</div>
<div class="row">
<div class="column side" style="background-color:#bbb;">Column right</div>
<div class="column middle" style="background-color:#ccc;">Column mid</div>
</div>
<div class="footer">
<t>footer</t>
</div>
<script>
$(function(){
$("#nav-placeholder").load("nav.html");
});
</script>
<script src="/Javascript/customscript.js"></script>
</body>
</html>
nav.html
<nav class="navbar">
<div class="hamburger" onclick="toggleMenu()">
☰ <!-- (three horizontal lines) -->
</div>
<ul class="menu">
<li><a href="/index.html">Home</a></li>
<li><a href="/projects/index.html">Projects</a></li>
<li><a href="/template.html">template</a></li>
</ul>
</nav>
customscript.js
// Function to toggle the dropdown menu on mobile
function toggleMenu() {
const menu = document.querySelector('.menu');
menu.classList.toggle('show');
}
styles.css
/* default css */
body {
font-family: Arial, sans-serif;
font-size: 20px;
background-color: #b90000;
display:grid;
min-height: 100vh; /* always fill fiewport */
grid-template-rows: auto 1fr auto;
padding: 0;
margin: 0;
box-sizing: border-box; /* this probably makes it harder but will be a pain to change */
}
.header {
background-color: #f1f1f1;
margin-top: 65px; /* to accomodate navbar */
padding: 3px; /* to visually balance navbar shadow */
text-align: center;
}
.footer {
background-color: #f1f1f1;
position: relative;
bottom: 0;
text-align: center;
}
/*Navbar*//*#region*/
.navbar {
position: fixed; /* to viewport, need to add margin-top to header to accomodate */
top: 0;
left: 0;
width: 100%;
min-height:65px; /* needs to accomodate mobile dropdown */
background-color: #091c38;
box-shadow: 0px 2px 2px 1px rgb(16, 191, 214); /* x y blur spread */
display: flex;
justify-content: start;
z-index: 1000; /*display order*/
}
/* Menu that will be put in navbar */
.menu {
list-style-type: none; /* no list bullet points */
margin: 0;
padding: 10px;
display: flex;
justify-content: center;
}
/*menu list items*/
.menu li {
padding: 10px 20px;
}
/*menu links/text*/
.menu a {
font-size: 20px;
color: white;
text-decoration: none; /* no link underlines */
}
/*menu links/text hover*/
.menu a:hover {
color: #30fcfc;
outline: rgb(16, 191, 214) solid 5px;
outline-offset: 5px;
border-radius: 2%;
}
/* Hamburger dropdown Icon */
.hamburger {
display: none; /* Hide the hamburger icon by default */
cursor: pointer; /* change pointer when hovering */
font-size: 43px;
color: rgb(255, 255, 255);
top: 0;
left: 12px;
position: fixed; /* DO NOT MESS WITH THE BORGER IT WILL BORK THE ENTIRE NAV BAR */
z-index: 1001; /* Make sure the hamburger stays on top of other content */
}
/*#endregion*/
/*content columns*//*#region*/
.column {
float: right;
}
/* Left and right column */
.column.side {
width: 25%;
}
.column.middle {
width: 75%;
}
/* Clear floats after the columns dunno if this does anything
.row:after {
content: "";
display: table;
clear: both;
}*/
/*#endregion*/
/* Mobile-specific changes *//*#region*/
@media (max-width: 600px) {
/* Hide the menu by default on mobile and switch direction for dropdown*/
.menu {
display: none;
flex-direction: column;
width: 100%;
}
/* Show the hamburger icon on small screens */
.hamburger {
display:block;
}
/* Show menu dropdown when the "show" class is added by script*/
.menu.show {
display: flex;
}
/* mobile menu list items settings*/
.menu li {
padding-left: 0px;
width: 100%; /* Make menu items take full width */
text-align: center; /* Center the text */
}
/* make content colums full width so they stack instead */
.column.side, .column.middle {
width: 100%;
}
}
/*#endregion*/
Instead of the row class (content colums) being placed right below the header they are placed at the bottom of the page. I have mainly been trying to do this by different methods rather than tinkering with the css
When calling
.load()
using a URL without a suffixed selector expression, the content is passed to.html()
prior to scripts being removed. This executes the script blocks before they are discarded. If.load()
is called with a selector expression appended to the URL, however, the scripts are stripped out prior to the DOM being updated, and thus are not executed.
I would advise the following for your customscript.js file.
// Function to toggle the dropdown menu on mobile
function toggleMenu() {
$('.menu').toggleClass('show');
}
$("body").on("click", "div.hamburger", toggleMenu);
When a
selector
is provided, the event handler is referred to as delegated. The handler is not called when the event occurs directly on the bound element, but only for descendants (inner elements) that match the selector. jQuery bubbles the event from the event target up to the element where the handler is attached (i.e., innermost to outermost element) and runs the handler for any elements along that path matching the selector.
Event handlers are bound only to the currently selected elements; they must exist at the time your code makes the call to
.on()
. To ensure the elements are present and can be selected, place scripts after the elements in the HTML markup or perform event binding inside a document ready handler. Alternatively, use delegated event handlers to attach event handlers.