Beispiel:CSS Menu9.html

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche
<!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 &hellip;
				<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>