You can make use of a hashchange
-event!
Make a check-hash function and call it initially, so that loading the URL with the hash has the same behavior as changing the hash when already on-page.
You could create an array holding the IDs of the elements that should "listen" for such a hashchange
, and give them a specific class (e.g. .hash-selected
) when their ID equals the hash.
const hashes = ["#popup"]; // List of IDs that are "listening"
let lastHash = "";
function checkHash() {
if (hashes.includes(lastHash)) // Remove class from last selected element
document.querySelector(lastHash).classList.remove("hash-selected");
if (hashes.includes(location.hash)) // Add class to current selected element
document.querySelector(location.hash).classList.add("hash-selected");
// Save current hash as 'lastHash' for first if-statement when calling 'checkHash()' again
lastHash = location.hash;
}
checkHash(); // Initial function-call for same behavior on "page-open"
window.addEventListener("hashchange", () => checkHash());
body {margin: 0}
#popup {
position: absolute;
border-bottom: 1px solid black;
width: 100%;
transform: translateY(-100%);
background: lightgreen;
}
#popup.hash-selected {transform: translateY(0)}
<div id="popup">
<p>Some sample text</p>
<a href="#">Close</a>
</div>
<a href="#popup">Open popup</a>
We could even easily fill the hashes
-array with IDs of elements that have a specific class, like .hash-listen
:
const hashes = [];
for (let el of document.querySelectorAll(".hash-listen"))
hashes.push("#" + el.id);
// ...
Sidenote
To remove hashchanges from the browser-history, you should take a look at this answer that demonstrates the history.replaceState()
-function.