I have some tabs defined in HTML, and am using JavaScript to switch between the active tab content when the corresponding tab button is clicked. The clicking works fine, and the tabs look like this:
Now I want to be able to use a unique link so that I can navigate to the HTML page using a hash, and have it load with the correct tab being already active.
For example, if I navigate to the link site.com/projects/#engineering then it should open the engineering tab of the HTML page (most existing answers I have seen are using jQuery).
document.addEventListener("DOMContentLoaded", function() {
const buttons = document.querySelectorAll(".tab-button"); // Retrieve all tab buttons
const contents = document.querySelectorAll(".tab-content"); // Retrieve all tab contents
// A function which deactivates all buttons and contents
function deactivateAll() {
buttons.forEach(btn => btn.classList.remove("active"));
contents.forEach(content => content.classList.remove("active"));
}
// Add an event listener for each button.
// If a button is clicked, then deactivate all buttons, and add the clicked button to the "active" state list.
buttons.forEach(button => {
button.addEventListener("click", () => {
deactivateAll();
button.classList.add("active");
document.getElementById(button.dataset.tab).classList.add("active");
});
});
// Activate first tab by default
if (buttons.length) {
buttons[0].click();
}
});
.tab-buttons {
display: inline-flex;
flex-wrap: wrap;
}
.tab-button {
background: #eaeaea;
border: none;
}
.tab-button.active {
background: #333;
color: white;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
<!-- Tab buttons -->
<div class="tab-buttons">
<button class="tab-button" data-tab="electronics"> Electronics </button>
<button class="tab-button" data-tab="engineering"> Engineering </button>
</div>
<!-- Tab content sections -->
<div class="tab-contents">
<div class="tab-content" id="electronics">
<ul>
<li> Electronics Post 1 </li>
<li> Electronics Post 2 </li>
</ul>
</div>
<div class="tab-content" id="engineering">
<ul>
<li> Engineering Post 1 </li>
<li> Engineering Post 2 </li>
<li> Engineering Post 3 </li>
</ul>
</div>
</div>
When using a hash on the URL you can make use of the :target pseudo-class in CSS.
document.addEventListener("DOMContentLoaded", function() {
// Retrieve the parent element to all tab buttons
const buttons = document.querySelector(".tab-buttons");
// find out if a hash is already in place, and test if a button
// has a matching tab name, if no button, set the first button as
// the initial tab
let initialhash = location.hash.substring(1);
let initialbutton = buttons.querySelector(`[data-tab = "${initialhash}"]`);
if (!initialbutton) {
location.hash = buttons.querySelector('.tab-button').dataset.tab;
}
buttons.addEventListener('click', e => {
// test if it is a button that was clicked
if (e.target.dataset.tab) {
location.hash = e.target.dataset.tab;
}
});
});
.tab-content {
display: none;
}
.tab-content:target {
display: block;
}
.tab-button {
background-color: white;
color: black;
border-width: 1px 1px 0;
border-radius: .5em .5em 0 0;
}
body:has(.tab-content#electronics:target) .tab-buttons>[data-tab="electronics"],
body:has(.tab-content#engineering:target) .tab-buttons>[data-tab="engineering"] {
background-color: darkgray;
color: white;
}
.tab-content {
border: solid thin black;
}
<!-- Tab buttons -->
<div class="tab-buttons">
<button class="tab-button" data-tab="electronics"> Electronics </button>
<button class="tab-button" data-tab="engineering"> Engineering </button>
</div>
<!-- Tab content sections -->
<div class="tab-contents">
<div class="tab-content" id="electronics">
<ul>
<li> Electronics Post 1 </li>
<li> Electronics Post 2 </li>
</ul>
</div>
<div class="tab-content" id="engineering">
<ul>
<li> Engineering Post 1 </li>
<li> Engineering Post 2 </li>
<li> Engineering Post 3 </li>
</ul>
</div>
</div>