Search code examples
htmlcsspositioncss-positionabsolute

Position absolute not working with details summary in navigation bar


I'm trying to build a responsive and accessible navigation. To do so, I'm using <details> and <summary> for subpage navigation. I started out using the linked example and edited the code to my needs.

I played around with it for a while and have the mobile version as needed. However, I'm running into a problem with the positioning of the dropdowns in the non-mobile version.

In the linked example, the dropdowns appear directly under the respective parent item. As far as I can see, this is achieved by using position: absolute. When trying this in my adapted version, the dropdown moves to the upper left corner of the navigation bar. If I change the positioning, the items are aligned correctly, however, they don't appear as a dropwdown but rather as new lines. Thereby, they move the whole navigation bar.

Can someone spot where my mistake lies?

I've added all code below. I haven't changed anything in the javascript and just added it here so running the code snippet will actually reproduce the problem.

Thanks a lot for any help in advance!

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>


Solution

  • After some trying around, I realised I was pretty close to the answer. To reset the position of the two dropdowns, all that was needed was to add left: auto; and right: auto; as additional attributes for #sitenav.large ul ul