Beispiel:CSS Menu9.html
Aus SELFHTML-Wiki
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Menü 9</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">
<span class="visually-hidden">Untermenü aufklappen</span>
<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');
event.target.parentNode.childNodes.classList.toggle('visible');
}
});
document.addEventListener('mouseover', (event) => {
if (!event.target.classList.contains('visible')) {
hideSubmenu();
}
});
document.addEventListener('keyup', (event) => {
if (event.key === 'Escape') {
hideSubmenu();
}
if ((event.key === 'Tab') && (!event.target.closest('.visible')) ) {
hideSubmenu();
}
});
function hideSubmenu() {
let buttons = document.querySelectorAll('[aria-expanded="true"]');
buttons.forEach(function(button) {
button.setAttribute('aria-expanded', 'false');
});
let elements = document.querySelectorAll('.visible');
elements.forEach(function(element) {
element.classList.remove('visible');
});
}
}
const cssRules = `
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;
}
nav ul {
position:relative;
}
nav li {
margin: 0.25em;
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: 12em;
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 ul ul{
position: absolute;
left: 7em;
/* top: 0em; */
}
nav ul ul ul li {
width: 10em;
}
nav ul li {
display: block;
}
/* Show the submenu on hover, but not when nav li button:hover */
nav li:hover > ul {
visibility: visible;
height: auto;
}
nav li button:hover ~ ul {
visibility: hidden;
height: 0;
}
nav li button:hover ~ ul.visible,
.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;
}`;
const stylesheet = document.createElement('style');
stylesheet.textContent = cssRules;
stylesheet.id = 'CSS-for-dropdown-navigation';
document.querySelector('html > head').appendChild(stylesheet);
});
</script>
<style>
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>
<h1>Menü 9: Kopiervorlage</h1>
<nav>
<ul>
<li><a href="#">Seite 1</a></li>
<li><a href="#">Seite 2</a>
<ul>
<li><a href="#2a">Seite 2a</a>
<ul>
<li><a href="#2aI">Seite 2aI</a></li>
<li><a href="#2aII">Seite 2aII</a></li>
</ul>
</li>
<li><a href="#2b">Seite 2b</a></li>
</ul>
</li>
<li aria-current="page"><a href="#">aktuelle Seite</a></li>
<li><a href="#">Seite 4</a>
<ul>
<li><a href="#4a">Seite 4a</a></li>
<li><a href="#4b">Seite 4b</a></li>
<li><a href="#4c">Seite 4c</a></li>
</ul>
</li>
<li><a href="#">Seite 5</a></li>
</ul>
</nav>
<p>Dieses Beispiel erweitert die CSS-basierte Variante um einige Zusatzfunktionen, die das Dropdown-Menü für alle benutzbar machen.</p>
<p>Ziele sind:</p>
<ol>
<li> <b>HTML</b>: verschachtelte Listen mit bis zu drei Ebenen ohne Klassen
<li> <b>CSS</b>: Auf schmalen Viewports vertikal - auf genügend breiten Viewports horizontal angeordnet.
<li> <b>JavaScript</b> Bedienung mit Maus, Touch und Tastatur
<ul>
<li>Jedes Listenelement mit einer Unterliste enthält zwei UI-Elemente:<ul>
<li>den eigentlichen Link auf eine Unterseite und …
<li>einen dynamisch erzeugten Button zum Öffnen/Schließen des Untermenüs.</li></ul>
</li>
<li>Links und Buttons können mit der Tab-Taste <kbd>↹ </kbd>angetabbt und dann mit<kbd>⏎</kbd> oder <kbd>Space</kbd> ausgewählt werden.
<br>(<kbd>Shift</kbd>+<kbd>↹</kbd> führt zurück!) </li>
<li><kbd>ESC</kbd> schließt das aufgeklappte Menü</li>
</ul></li>
</ol>
<p>Kopiere das JavaScript in eine eigene Datei und binde sie in jeder Seite deiner Webpräsenz ein.</p>
</body>
</html>