Issue
I am currently attempting to create a navbar at the top of my personal site. In the animation that makes the drop-down menu visible, it pans down from the top of the screen, passing in front of the entire navbar. I want the drop-down menu to be rendered behind the entire header so it doesn't cover anything up while panning down.
I've included a code snippet below that shows what is happening (the CSS is slightly simplified, but mostly the same).
I've tried many combinations of z-index
and position
attributes, but have not yet been able to get the drop-down menu to render behind the header. From what I have seen, a negative z-index
on .dropdown-content
allows it to be stacked behind nav
, but never behind header
. Is there any changes I can make to have this behavior?
Note also that a positive z-index
is required for the header
since it has positioning: sticky
; without it, other elements in my site will show overtop of the it.
body {
background-color: navy;
}
header {
z-index: 10;
top: 0;
position: sticky;
background-color: #141414de;
color: #fff;
}
nav {
display: inline-block;
text-align: left;
margin: 0 auto;
min-width: 50%;
}
nav a, nav button {
transition: color 0.15s ease-in-out, border-color 0.15s ease-in-out;
display: inline-block;
color: #858585;
text-decoration: none;
padding: 20px 5px;
margin: 0 10px;
border: none;
border-top: 3px solid transparent;
background-color: transparent;
font-size: 1rem;
}
nav a.active {
color: #fff;
border-top: 3px solid #afafaf;
}
nav>a:not(.active):hover {
color: #ffffff;
border-color: #686868;
}
.dropdown {
display: inline-block;
}
.dropdown-content {
z-index: -10;
display: block;
visibility: hidden;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
transition: transform 1s ease-in-out, visibility 1s ease-in-out;
transform: translateY(-200%);
}
.dropdown:hover .dropdown-content {
visibility: visible;
transform: translateY(0);
}
<header>
<nav>
<a href="index.html" class="active">Home</a>
<div class="dropdown">
<button>About</button>
<div class="dropdown-content">
<a href="about.html#education">Education</a>
<a href="about.html#experience">Experience</a>
<a href="about.html#skills">Skills</a>
</div>
</div>
<a href="contact.html">Contact</a>
</nav>
</header>
Solution
I had this same problem yesterday! I discovered the following solution.
We need to separate the visual styles from the positional styles. By adding a position
to your header you are pull that element forward in the stacking order, which prevents a z-index from showing behind it.
To correct this we just need to add an additional wrapper to separate the visual and positional styles.
body {
background-color: navy;
}
header {
z-index: 10;
top: 0;
position: sticky;
/* Removed visual styles and left only positional styles */
}
/* Moved visual styles to the new wrapper div */
.header-style {
background-color: #141414de;
color: #fff;
}
nav a, nav button {
transition: color 0.15s ease-in-out, border-color 0.15s ease-in-out;
display: inline-block;
color: #858585;
text-decoration: none;
padding: 20px 5px;
margin: 0 10px;
border: none;
border-top: 3px solid transparent;
background-color: transparent;
font-size: 1rem;
}
nav a.active {
color: #fff;
border-top: 3px solid #afafaf;
}
nav>a:not(.active):hover {
color: #ffffff;
border-color: #686868;
}
.dropdown {
display: inline-block;
}
.dropdown-content {
z-index: -1; /* Set Z-Index to be more reasonable */
display: block;
visibility: hidden;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
transition: transform 1s ease-in-out, visibility 1s;
transform: translateY(-200%);
}
.dropdown:hover .dropdown-content {
visibility: visible;
transform: translateY(0);
}
main {
background-color: #141414de;
color: white;
margin-top: 1em;
padding: 0.5em;
}
p:first-child {
margin-top: 0;
}
p:last-child {
margin-bottom: 0;
}
<header>
<!-- New Wrapper Div Added -->
<div class="header-style">
<nav>
<a href="index.html" class="active">Home</a>
<div class="dropdown">
<button>About</button>
<div class="dropdown-content">
<a href="about.html#education">Education</a>
<a href="about.html#experience">Experience</a>
<a href="about.html#skills">Skills</a>
</div>
</div>
<a href="contact.html">Contact</a>
</nav>
</div>
</header>
<main>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed egestas rhoncus nulla. Phasellus sed justo non diam pretium sagittis sit amet sit amet lectus. Ut tempus lectus in egestas scelerisque. Cras in lobortis dui, a interdum lacus. Praesent rhoncus feugiat libero id iaculis. Maecenas eu erat at ex auctor consequat sit amet et arcu. Morbi et mauris vel ipsum molestie venenatis. Cras luctus cursus ex non porttitor. Etiam at euismod nunc, eu maximus libero. Sed et nisi et ex consequat vestibulum vitae at nisi. Quisque mollis dui nec turpis efficitur imperdiet. Suspendisse sed metus ut dolor ornare dapibus. Etiam eu nulla ut dui rhoncus viverra et sit amet magna. Suspendisse vel nulla non nisl euismod scelerisque vel eget velit.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed egestas rhoncus nulla. Phasellus sed justo non diam pretium sagittis sit amet sit amet lectus. Ut tempus lectus in egestas scelerisque. Cras in lobortis dui, a interdum lacus. Praesent rhoncus feugiat libero id iaculis. Maecenas eu erat at ex auctor consequat sit amet et arcu. Morbi et mauris vel ipsum molestie venenatis. Cras luctus cursus ex non porttitor. Etiam at euismod nunc, eu maximus libero. Sed et nisi et ex consequat vestibulum vitae at nisi. Quisque mollis dui nec turpis efficitur imperdiet. Suspendisse sed metus ut dolor ornare dapibus. Etiam eu nulla ut dui rhoncus viverra et sit amet magna. Suspendisse vel nulla non nisl euismod scelerisque vel eget velit.</p>
</main>
By doing this you have you header
element, which allows the sticky positioning, completely separate from a static element, which contains all of your styles. Now within the static element you can have your dropdown menu and allow it to appear behind your header.
Answered By - Jonathan Owen Chute
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.