Skip to content

Instantly share code, notes, and snippets.

@mmarienko
Last active April 11, 2023 22:11
Show Gist options
  • Save mmarienko/9341c52e0b120ecd81ba1684c472e460 to your computer and use it in GitHub Desktop.
Save mmarienko/9341c52e0b120ecd81ba1684c472e460 to your computer and use it in GitHub Desktop.
Modal windows plugin by vanilla JS
new class Modals {
constructor() {
this.init();
this.addListenersOpen();
this.addListenersClose();
this.addListenerHash();
}
init() {
const modal = document.querySelector(`[data-modal="${window.location.hash}"]`);
if (window.location.hash && modal) {
modal.classList.add('active');
this._hideScroll();
} else {
document.querySelectorAll(`[data-modal]`).forEach(modal => {
modal.classList.remove('active');
});
}
}
addListenersOpen() {
document.querySelectorAll('a[data-modal-open]').forEach(trigger => {
trigger.addEventListener('click', this.openModal.bind(this));
});
}
addListenersClose() {
document.querySelectorAll('[data-modal-close]').forEach(trigger => {
trigger.addEventListener('click', this.closeModal.bind(this));
});
}
addListenerHash() {
window.addEventListener('hashchange', this.init.bind(this));
}
openModal(event) {
event.preventDefault();
const trigger = event.target.closest('[data-modal-open]');
const modal = document.querySelector(`[data-modal="${trigger.hash}"]`);
if (modal) {
modal.classList.add('active');
this._hideScroll();
} else {
console.error(`The modal window by id '${id}' not found!`);
}
window.location.hash = trigger.hash;
sessionStorage.setItem("last-url", event?.oldURL);
}
closeModal(event) {
event.preventDefault();
const modal = event.target.closest('[data-modal]');
if (modal) {
modal.classList.remove('active');
this._visibleScroll();
const lastUrl = sessionStorage.getItem("last-url");
if (lastUrl.indexOf('#') == -1) {
history.pushState("", document.title, window.location.pathname + window.location.search);
} else {
const lastHash = lastUrl.substr(lastUrl.indexOf('#'));
window.location.hash = lastHash;
}
} else {
console.error(`The modal window by id '${id}' not found!`);
}
}
_hideScroll() {
const scrollWidth = window.innerWidth - document.body.offsetWidth;
if (scrollWidth) {
document.querySelectorAll('[data-modal-fixed]').forEach(element => {
element.style.paddingRight = `${scrollWidth}px`;
});
document.body.style.paddingRight = `${scrollWidth}px`;
}
document.body.style.overflow = 'hidden';
}
_visibleScroll() {
document.querySelectorAll('[data-modal-fixed]').forEach(element => {
element.style.paddingRight = '0';
});
document.body.style.paddingRight = '0';
document.body.style.overflow = 'visible';
}
};
<html>
<body>
<header data-modal-fixed> <!-- if menu is position: fixed -->
<nav aria-label="navigation">
<ul>
<li>Home</li>
<li>News</li>
<li>About</li>
<ul>
</nav>
</header>
<main>
<a href="#modal-1" data-modal-open>Open modal window</a>
</main>
<div class="modal" data-modal="#modal-1">
<div data-modal-close class="modal__area"></div>
<div class="modal__body">
<div class="modal__content">
<button data-modal-close class="modal__close" aria-label="Close modal window"> ✖ </button>
Content
</div>
</div>
</div>
</body>
</html>
.modal {
position: fixed;
width: 100%;
height: 100%;
background-color: rgba(#000, 0.7);
top: 0;
left: 0;
opacity: 0;
visibility: hidden;
overflow-y: auto;
overflow-x: hidden;
z-index: 100;
transition: all 0.5s ease-in-out;
&.active {
opacity: 1;
visibility: visible;
.modal__content {
opacity: 1;
transform: translate(0, 0);
}
}
&__area {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
&__body {
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 40px 20px;
}
&__content {
width: 100%;
max-width: 1000px;
background: #fff;
margin: 0 auto;
transition: all 0.3s ease-in-out;
opacity: 0;
transform: translate(0px, -100%);
padding: 20px 15px;
}
&__close {
position: absolute;
right: 10px;
top: 10px;
z-index: 101;
}
}

This is plugin which makes work with layout your project easier.

Anything you need is set needed data-attributes.

  • data-modal-open - link for open modal (necessarily to set a unique identificator in href).
  • data-modal-close - button for close modal.
  • data-modal - unique identificator.
  • data-modal-fixed - needed for fixed menu and the same blocks which depended by scrollbar.
@mmarienko
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment