Beispiel:CSS Menu8.html
<!DOCTYPE html> <html lang="de"> <head>
<meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" media="screen" href="./Beispiel:SELFHTML-Beispiel-Grundlayout.css">
<title>Menü 8</title> <script> document.addEventListener('DOMContentLoaded', function () {
dropdownExtension();
function dropdownExtension () {
const submenus = document.querySelectorAll('nav li > ul');
for(let submenu of submenus) {
submenu.classList.add('submenu');
submenu.insertAdjacentHTML('beforebegin', `
<button aria-expanded="false">
Untermenü aufklappen
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1'>
<path d='M0.3,0.1 0.3,0.9 0.8,0.5z' />
</svg>
</button>
`);
}
document.documentElement.addEventListener('click', event => {
if (event.target.tagName == 'BUTTON' && event.target.hasAttribute('aria-expanded')) {
event.target.setAttribute('aria-expanded', event.target.getAttribute('aria-expanded') != 'true');
event.target.nextElementSibling.classList.toggle('visible');
}
});
document.addEventListener('keyup', (event) => { if (event.key === 'Escape') { hideSubmenu(); }
if ((event.key === 'Tab') && (!event.target.closest('.visible')) ) {
hideSubmenu(); } });
function hideSubmenu() { let elements = document.querySelectorAll('.visible'); elements.forEach(function(element) { element.classList.remove('visible'); }); let buttons = document.querySelectorAll('[aria-expanded="true"]'); buttons.forEach(function(button) { button.setAttribute('aria-expanded', 'false'); }); } }
}); </script> <style> nav > ul {
list-style:none;
// Safari hack, see https://www.scottohara.me/blog/2019/01/12/lists-and-safari.html list-style: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'/%3E");
margin: 0; padding: 0; display: flex; flex-direction: column; position:relative;
}
nav li {
margin: 0.5em; padding: 0; font-size: 1.5rem; flex: 1 1 0%; position: relative;
}
@media (min-width: 45em) {
nav > ul { flex-direction: row;
height: 3em;
} nav li { flex: 1;
flex-basis: 15em;
flex-grow: 0; flex-shrink: 0;
font-size: 1em;
}
}
nav a {
display: block; padding: 0.4em; text-decoration: none; font-weight: bold; text-align: center; border: thin solid var(--background-color); border-radius: .5em; color: var(--link-color); --link-color: gold; background-color: var(--background-color); transition: all .25s ease-in; position: relative;
}
nav li[aria-current] a {
background-color: var(--accent2-color); color: var(--accent1-color);
}
nav a:focus,
nav a:hover,
nav li[aria-current] a:focus,
nav li[aria-current] a:hover {
color: var(--background-color); background-color: var(--accent1-color);
}
/* submenu navigation links */ nav ul ul {
visibility: hidden; height: 0; z-index: 1000;
} nav ul li {
display: block; /* width: 15em; */
}
/** Show the submenu on hover, focus **/ /* nav li:hover ul {
visibility: visible; height: auto;
} nav li:focus-within > ul, */ .visible {
visibility: visible; height: auto;
}
[aria-expanded] { position: absolute; right: 0.5em; top: 0.25em; width:2em; height:2em; padding: 0; color: var(--accent1-color); background: var(--background-color); /* damit er bei nav a:focus noch sichtbar ist */ outline:transparent; border: thin solid var(--background-color); border-radius: 0.3em; }
[aria-expanded] svg { pointer-events: none;
fill: var(--accent1-color);
border-radius: 0.3em; z-index:10; }
nav li:hover [aria-expanded] svg { background: var(--accent1-color); fill: var(--background-color); }
nav li:focus [aria-expanded] svg { background: var(--background-color);
fill: var(--accent1-color);
}
[aria-expanded]:focus svg, [aria-expanded]:hover svg{
fill: var(--background-color);
background: var(--accent1-color);
}
[aria-expanded="true"] svg {
transform: translate(0,0) rotate(90deg);
}
.visually-hidden, [visually-hidden="true"] { position: absolute !important; clip-path: rect(1px, 1px, 1px, 1px) !important; padding: 0 !important; border: 0 !important; height: 1px !important; width: 1px !important; overflow: hidden !important; }
- root {
--background-color: midnightblue; --accent1-color: gold; --accent2-color: darkred; --text-color: black; }
kbd {
background: #f9f9f9 linear-gradient(to bottom, #eee, #f9f9f9, #eee) repeat scroll 0 0; border: thin solid #aaa; border-radius: 2px; box-shadow: 1px 2px 2px #ddd; font-family: inherit; font-size: 0.9em; padding: 0 0.5em;
} </style>
</head>
<body>
Menü 8: Buttons erzeugen und Submenüs verstecken
<nav>
- <a href="#">Seite 1</a>
- <a href="#">Seite 2</a>
- <a href="#2a">Seite 2a</a>
- <a href="#2aI">Seite 2aI</a>
- <a href="#2aII">Seite 2aII</a>
- <a href="#2b">Seite 2b</a>
- <a href="#2a">Seite 2a</a>
- <a href="#">aktuelle Seite</a>
- <a href="#">Seite 4</a>
- <a href="#4a">Seite 4a</a>
- <a href="#4b">Seite 4b</a>
- <a href="#4c">Seite 4c</a>
- <a href="#">Seite 5</a>
- <a href="#">Seite 6</a>
</nav>
Dieses Beispiel erweitert die CSS-basierte Variante um einige Zusatzfunktionen, die das Dropdown-Menü für alle benutzbar machen.
Ziele sind:
- HTML: verschachtelte Listen mit bis zu drei Ebenen ohne Klassen
- CSS: Auf schmalen Viewports vertikal - auf genügend breiten Viewports horizontal angeordnet.
- JavaScript Bedienung mit Maus, Touch und Tastatur
- Jedes Listenelement mit einer Unterliste enthält zwei UI-Elemente:
- den eigentlichen Link auf eine Unterseite und …
- einen dynamisch erzeugten Button zum Öffnen/Schließen des Untermenüs.
- Links und Buttons können mit der Tab-Taste ↹ angetabbt und dann mit⏎ oder Space ausgewählt werden. (Shift+↹ führt zurück!)
- ESC schließt das aufgeklappte Menü
- Jedes Listenelement mit einer Unterliste enthält zwei UI-Elemente:
Um die Funktionsweise der Tastenbedienung zu demonstrieren,
wurden die CSS-Regelsätze für li:hover ul
auskommentiert.
Für ganz Ungeduldige gibt es eine <a href="https://wiki.selfhtml.org/wiki/Navigation/Dropdown-Men%C3%BC#Kopiervorlage_f.C3.BCr_Ungeduldige">Kopiervorlage</a>.
</body> </html>