我正在尝试建立一个响应式和可访问的导航。为此,我使用了 <details>
和 <summary>
的子页面导航。附例 并根据我的需要编辑了代码。
我玩了一会儿,根据需要有了移动版。然而,我在非移动版的下拉菜单的定位上遇到了一个问题。
在链接的例子中,下拉菜单直接出现在各自的父项下。据我所知,这是通过使用以下方法实现的 position: absolute
.当我在我的改编版本中尝试这样做时,下拉菜单移动到了导航栏的左上角,如果我改变了定位,项目就会正确地对齐,但是,它们并没有作为下拉菜单出现,而是作为新的线条出现。因此,它们移动了整个导航栏。
谁能发现我的错误所在?
我在下面添加了所有代码。我没有修改javascript中的任何内容,只是把它添加到这里,这样运行代码片段就能真正重现问题。
非常感谢你的帮助
window.addEventListener("DOMContentLoaded",function() {
"use strict"
// Das Navigationselement
var navele = document.querySelector("#sitenav");
if(!navele) return;
// // Polyfill für IE und Edge -> muss noch ausgelagert werden
// var native_details = ('open' in document.createElement("details"));
// if (!native_details) {
// var script = document.createElement('script');
// script.src = "details-polyfill.js";
// document.getElementsByTagName('head')[0].appendChild(script);
// }
// Alle details und summary
var details = navele.querySelectorAll("details");
var summary = navele.querySelectorAll("summary");
// Fokussierbares Element hinter Navigation legen, für focusin-Event
var span = document.createElement("span");
span.tabIndex = 0;
navele.appendChild(span);
// Fürs css Klasse "withjs" setzen
sitenav.className += " withjs";
// Auf Seitenbreite reagieren und bei breiten Viewports Klasse "large" setzen
var format;
var mq = window.matchMedia("screen and (min-width:45em)");
mq.addListener(mq_handler);
mq_handler();
function mq_handler() {
if(mq.matches) {
details[0].setAttribute('open', 'open');
summary[0].setAttribute('hidden', 'hidden');
format = "large";
sitenav.className += " large"
gridcontainer.className += " large"
}
else {
details[0].removeAttribute('open');
summary[0].removeAttribute('hidden');
format = "small";
sitenav.className = sitenav.className.replace(" large","");
gridcontainer.className = gridcontainer.className.replace(" large","");
}
}
// Eventhandler
window.addEventListener('click', klickhandler);
window.addEventListener('touchstart', klickhandler);
window.addEventListener('keydown', keyhandler);
window.addEventListener('focusin', focusinhandler);
// Aktion bei Klick, Touch und Tastendruck auf summary
function klickhandler(e) {
if (e.target.nodeName.toLowerCase() === 'summary') {
// Bei Betätigung des summary andere Submenüs schließen
closeAllwithout([e.target.parentNode,details[0]]);
}
else {
// Bei Klick oder Touch außerhalb der Navigation alle Submenüs schließen
if(!childOf(e.target,details[0])) closeAllwithout([]);
}
}
// Bei Taste ESC alle Submenüs schließen
function keyhandler(e) {
if(e.keyCode == 27) closeAllwithout([]);
}
// Bei Verlassen mit Tabulator, also bei Fokus außerhalb der Navigation, alle Submenüs schließen
function focusinhandler(e) {
if(!childOf(e.target,details[0])) closeAllwithout([]);
}
// Alle Submenüs schließen, bis auf Elemente in nc
function closeAllwithout(nc) {
for(var i=1;i<details.length;i++) if(nc.indexOf(details[i]) == -1) details[i].removeAttribute('open');
if(format == "small" && details[0].hasAttribute("open") && nc.indexOf(details[0]) == -1) {
details[0].removeAttribute('open');
summary[0].focus();
}
}
// Ermitteln, ob child ein Kindelement von parent ist
function childOf(child, parent) {
while((child = child.parentNode) && child!==parent);
return !!child;
}
});
body {
margin-right: 1em;
margin-left: 1em;
margin-top: 0;
margin-bottom: 0;
background-color: lightgrey;
}
#gridcontainer {
background-color: white;
display: grid;
grid-template-areas:
'header header'
'navdetails navdetails'
'maintext maintext'
'pic pic'
'foot foot';
}
#gridcontainer.large {
display: grid;
grid-template-areas:
'header header header'
'maintext maintext pic'
'foot foot foot';
}
header {
grid-row: 1 / span 1;
height: 2em;
}
main {
grid-area: maintext;
color: black;
font: 1.25em/1.3 Arial, sans-serif;
padding: 0.5em;
align-self: start;
}
aside {
grid-area: pic;
padding: 0.5em;
align-self: center;
justify-self: center;
}
footer {
grid-area: foot;
font: 0.8em/1.3 Arial, sans-serif, grey;
padding: 0.5em;
box-shadow: 0em 0em 1em 0.5em rgb(192, 192, 192);
display: flex;
flex-direction: row;
justify-content: center;
}
/* Footer */
footer a {
padding: 0.5em;
color: rgb(137, 147, 124);
text-decoration: none;
}
/* Text */
article {
font: 1em/1.3 Arial, sans-serif;
max-width: 100%;
}
h1 {
font: 2.5em/1.3 Arial, sans-serif, bold;
margin-left: 0.2em;
}
h2 {
color: rgb(117, 72, 94);
font: 1.5em/1.3 Arial black, sans-serif;
}
/* Pictures */
img {
max-width: 100%;
}
#logo {
grid-area: logo;
padding: .2em;
color: rgb(14, 28, 54)
}
nav {
grid-area: navi;
color: rgb(14, 28, 54);
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
height: max-content;
}
/* ################# Allgemeine Einstellungen und Einstellungen für schmale Viewports ##################### */
#sitenav *, #sitenav a {
color: rgb(14, 28, 54);
margin: 0;
background-color: white;
}
#sitenav ul {
list-style-type: none;
}
#sitenav ul ul {
padding-left: .5em;
padding-right: 0;
margin-right: 0;
}
#sitenav li a, #sitenav li summary {
display: flex;
flex-direction: row-reverse;
padding: .5em;
line-height: 1.4em;
justify-content: flex-end;
white-space: nowrap;
text-decoration: none;
}
#sitenav li a:hover, #sitenav li summary:hover, #sitenav li a:focus, #sitenav li summary:focus {
background-color: lightgrey;
}
#sitenav ul details:not([open]) summary::after {
content: ' ►';
}
#sitenav ul details[open] summary::after {
content: ' ◄';
}
#sitenav > details:not([open]) > summary::before {
content: "☰";
font-size: 1.9em;
padding: .5em;
}
#sitenav > details[open] > summary::before {
content: "×";
font-size: 2.3em;
padding: .5em;
}
#sitenav > details {
max-width: -webkit-max-content;
max-width: -moz-max-content;
max-width: max-content;
}
#sitenav > details > ul {
margin: 0;
padding: 0;
}
#sitenav summary {
cursor: pointer;
}
#sitenav summary::-webkit-details-marker {
display: none;
}
#sitenav summary {
list-style-type: none;
}
#sitenav > details > ul > li[aria-current] {
border-left: 2px solid black;
}
#sitenav {
position: fixed;
top: 0;
right: 1em;
left: 1em;
background-color: white;
}
#sitenav ul {
position: fixed;
right: 1em;
left: 1em;
top: 4.2em;
}
#sitenav ul ul {
position: relative;
right: 0;
left: 0;
top: 0;
}
/* ########################## Einstellungen für breite Viewports ######################################### */
#sitenav.large > details > ul , #sitenav.large > details > ul > li {
display: flex;
flex-direction: row;
/* margin: 0; */
}
#sitenav.large ul details:not([open]) summary::after {
content: ' ▼';
}
#sitenav.large ul details[open] summary::after {
content: ' ▲';
}
#sitenav.large > details > ul > li[aria-current] {
border-bottom: 2px solid black;
border-left: none;
}
#sitenav.large li a, #sitenav.large li summary {
display: flex;
flex-direction: row;
justify-content: start;
}
#sitenav.large ul {
position: sticky;
right: 0;
top: 1.7em;
}
#sitenav.large.withjs ul ul {
position: absolute;
max-width: -webkit-max-content;
max-width: -moz-max-content;
max-width: max-content;
margin-left: -.5em;
margin-right: 0;
margin-top: 1.1em;
padding-left: .5em;
border-radius: 0 0 .5em .5em;
}
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
<![endif]-->
<link rel="stylesheet" href="style/style.css">
<title>Yoga Loccum</title>
</head>
<body>
<div id="gridcontainer">
<header>
<nav id="sitenav">
<h1 id="logo">Pagelogo</h1>
<details>
<summary> </summary>
<ul>
<li aria-current="page"><a href="#">Startseite</a></li>
<li><a href="/">Page 1</a></li>
<li>
<details>
<summary>Page 2</summary>
<ul>
<li><a href="/">Page 2.1</a></li>
<li><a href="/">Page 2.2</a></li>
</ul>
</details>
</li>
<li>
<details>
<summary>Page 3</summary>
<ul>
<li><a href="/">Page 3.1</a></li>
<li><a href="/">Page 3.2</a></li>
</ul>
</details>
</li>
</ul>
</details>
</nav>
</header>
<main id="maintext">
<h2>Welcome</h2>
<article>
<p> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </p>
<p> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </p>
</article>
</main>
<aside id="addpic">
Here will be a picture
</aside>
<footer>
<a tabindex="0" aria-current="page" id="active">Startseite</a>
<a href=/>Impressum</a>
</footer>
</div>
<script src="JavaScript/menu.js"></script>
</body>
</html>
经过一些尝试,我意识到我已经非常接近答案了。为了重置两个下拉菜单的位置,所需要的就是添加 left: auto;
和 right: auto;
的附加属性。#sitenav.large ul ul