Modal avagy tartalom előtérbe kerülése

Mi a cél?

Egy olyan felugró ablak elkészítése, mely megjelenésekor fókuszba kerül, azaz a TAB gomb is csak a modal-on belül érvényesül, a környezete elhalványul és ha a bezáró gombra vagy a környzetére kattintunk akkor tűnik el. Tipikus példa a hamburger menü megvalósítására.

DEMO (a képre kattintva indul)

Modal

A HTML template

Csak azért van három indítógomb, hogy gyakoroljuk ugyanazon eseményfigyelő több gombra való felírását, ugyanazon modal fog feljönni. A tabindex negatív értékkel az adott gomb a TAB használatakor nem fog fókuszba kerülni, kimarad. A tabindex = 0 azt jelenti, hogy a TAB megnyomásakor a főkusz erre az elemre kerül. A tabindex pozitív értékei irányíthatnák a további sorrendet, de ezek használata nem ajánlott és nekem nem is működött. A példában az Okey és a Cancel gombra való kattintás is bezárja a modalt.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Modal</title> <link rel="stylesheet" href="./css/style.css"> </head> <body> <div class="backdrop fade-in"></div> <button class="btn-any" tabindex="-1">Első modal</button> <button class="btn-any" tabindex="-1">Második modal</button> <button class="btn-any" tabindex="-1">Harmadik modal</button> <div class="modal fade-in"> <div class="modal__close" tabindex="0"> <div class="modal__close--bar1" tabindex="0"> <div class="modal__close--bar2"></div> </div> </div> <h3 class="modal__title">CSSSript.com</h3> <p class="modal__content">Lorem ipsum dolor sit amet consectetur adipisicing elit. Eius perspiciatis deleniti, blanditiis ullam dolor assumenda commodi rem, beatae modi nam neque possimus odit nobis molestias excepturi eum ratione eaque deserunt libero nihil odio? Esse cupiditate sed quaerat, sunt earum perspiciatis quis. Molestiae expedita maiores voluptate assumenda blanditiis nemo repellendus ipsum iusto quia delectus. Illum consequuntur earum excepturi eos voluptas doloribus adipisci possimus quis, facilis ex nulla, sequi numquam dolore iusto! Alias cum quia a vero. </p> <div class="modal__buttons"> <button class="btn-modal btn-yes">Okey</button> <button class="btn-modal btn-no">Cancel</button> </div> </div> <script src="./js/main.js"></script> </body> </html>

A CSS stílus

A modal bezáró gombot CSS-el generáljuk és abszolut pozicionálással tesszük a modal jobb felső sarkába.

* { margin: 0; padding: 0; } *, *::before, *::after { box-sizing: inherit; } html { box-sizing: border-box; } body { min-height: 100vh; position: relative; } .modal { padding: 1rem; border: 2px solid lightgray; box-shadow: 0 4px 8px rgba(0,0,0,0.1); position: relative; display: none; z-index: 6; background-color: cornsilk; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 100%; } .modal__title { margin-top: 1rem; } .modal__content { padding: 1rem 0; } .modal__buttons { display: flex; justify-content: flex-end; } .btn-modal { padding: 0.75rem 1.5rem; margin: 0.5rem; border: none; color: white; border-radius: 2px; cursor: pointer; transition: all 0.3s; } .btn-modal:hover { scale: 1.05; } .btn-any { background-color: blueviolet; padding: 0.75rem 1.5rem; margin: 0.5rem; border: none; color: white; border-radius: 2px; cursor: pointer; transition: all 0.3s; } .btn-yes { background-color: lightgreen; } .btn-yes:hover { background-color: lime; } .btn-no { background-color: lightsalmon; } .btn-no:hover { background-color: red; } .modal__close { position: absolute; top: 0; right: 0; cursor: pointer; border: none; width: 2rem; height: 2rem; display: flex; flex-direction: column; justify-content: center; align-items: center; } .modal__close--bar1, .modal__close--bar2 { width: 20px; height: 2px; background-color: #000; } .modal__close--bar1 { transform: rotate(45deg); } .modal__close--bar2 { transform: rotate(90deg); } .modal__close--bar1:hover, .modal__close--bar2:hover { scale: 1.1; } .backdrop { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100vh; background: rgba(0, 0, 0, 0.5); z-index: 5; } .fade-in { animation-name: fadeInOpacity; animation-iteration-count: 1; animation-timing-function: ease-in; animation-duration: .3s; } .fade-out { animation-name: fadeOutOpacity; animation-iteration-count: 1; animation-timing-function: ease-in; animation-duration: .3s; } @keyframes fadeInOpacity { 0% { opacity: 0; } 100% { opacity: 1; } } @keyframes fadeOutOpacity { 0% { opacity: 1; } 100% { opacity: 0; } } @media(min-width: 560px) { .modal { width: 50%; } }

A Javascript logika

Felírjuk a DOM elemeket, NodeList-eket.

const buttons = document.querySelectorAll('.btn-any'); const modal = document.querySelector('.modal'); const backdrop = document.querySelector('.backdrop'); const modalButtons = document.querySelectorAll('.btn-modal'); const close = document.querySelector('.modal__close');

Felírjuk az eseményfigyelőket.

for (let i = 0; i < buttons.length; i++) { modalOpen(i); } function modalOpen(i) { buttons[i].addEventListener('click', () => { backdrop.classList.remove('fade-out'); modal.classList.remove('fade-out'); modal.style.display = 'block'; backdrop.style.display = 'block'; }); };

A modalhoz hozzáadjuk a TAB eseményfigyelőjét, mely a modal záró gombja az Okey és a Cancel gombok között váltogatja a TAB mozgását. A TAB klaviatúra kódja a 9-es.

modal.addEventListener('keydown', (e) => { e.preventDefault(); if (e.keyCode === 9 && document.activeElement === close) { modalButtons[0].focus(); } else if (e.keyCode === 9 && document.activeElement === modalButtons[0]) { modalButtons[1].focus(); } else if (e.keyCode === 9 && document.activeElement === modalButtons[1]) { close.focus(); } })

A modal eltűnésére egy külön függvényt írunk.

function fadeOut() { backdrop.classList.add('fade-out'); modal.classList.add('fade-out'); setTimeout(() => { backdrop.style.display = 'none'; modal.style.display = 'none'; }, 300) }

A modal eltűnésére felírjuk az eseményfigyelőket.

for (let i = 0; i < modalButtons.length; i++) { modalButtons[i].addEventListener('click', () => { fadeOut(); }) } close.addEventListener('click', () => { fadeOut(); }) backdrop.addEventListener('click', () => { fadeOut(); })

A teljes kód itt található.