The hidden absolute positioned div disappears once the sticky navbar becomes fixed on the page

Whenever my navbar reaches the top of the screen, the links in the dropdown menu disappear.

I followed tutorials and examples from w3schools to build my webpage. Specifically:

This code snippet exemplifies my issue:

window.onscroll = function() {
  myFunction()
};

var navbar = document.getElementById("navi");
var sticky = navbar.offsetTop;

function myFunction() {
  if (window.pageYOffset >= sticky) {
    navbar.classList.add("sticky")
  } else {
    navbar.classList.remove("sticky");
  }
}
#navi {
  overflow: hidden;
  background-color: #333;
  font-family: Arial;
}

.drop {
  float: left;
  overflow: hidden;
}

.drop .dropbutton {
  font-size: 16px;
  border: none;
  outline: none;
  color: white;
  padding: 20px 25px;
  background-color: inherit;
  font-family: inherit;
  margin: 0;
}

#navbar a:hover,
.drop:hover .dropbutton {
  background-color: #25aa25;
}

.links {
  display: none;
  position: absolute;
  background-color: #f9f9f9;
  min-width: 210px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
}

.links a {
  float: none;
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
  text-align: left;
}

.links a:hover {
  background-color: #ddd;
}

.drop:hover .links {
  display: block;
}

.sticky {
  position: fixed;
  top: 0;
  width: 100%;
}

.sticky+article {
  padding-top: 60px;
}
<body>
  <header>
    <h1>
      Example for StackOverflow
    </h1>
  </header>
  <nav id="navi">
    <div class="drop">
      <button class="dropbutton">
                Button - dropdown
            </button>
      <div class="links">
        <a href="">Random link 1</a>
        <a href="">Random link 2</a>
        <a href="">Random link 3</a>
      </div>
    </div>
  </nav>
  <article>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
  </article>
</body>

Answer №1

If you're wondering why the dropdown is still visible even when the navbar is not at the top of the screen, it's because of how CSS properties are set.

The navbar has the CSS property overflow set to hidden, which normally prevents content from being visible outside its boundaries. However, the div containing the drop-down links (.links) has position set to absolute, meaning it's taken out of the normal document flow.

According to MDN:

absolute

This means the element is removed from the normal document flow and no space is created for it in the page layout. It is positioned relative to its closest positioned ancestor, or if there isn't one, then it's placed relative to the initial containing block.

Because .links doesn't have any positioned ancestors, its position is relative to the initial containing block.

However, when the navbar reaches the top of the screen, the sticky class is applied. This class mainly sets the position CSS property to fixed (meaning it's out of the document flow and positioned relative to the initial containing block established by the viewport).

With the sticky class applied, .links is now positioned relative to the navbar itself, making it affected by overflow: hidden.

To prevent the need to hide it when sticky applies, you should set the overflow property of the navbar to visible in that situation.

In CSS, the id attribute takes priority over the class, so you have two options. You can either update the .sticky class:

.sticky {
  ...
  overflow: visible !important;
} 

But using !important can lead to a nightmare of specificity issues. A better solution would be to create a new rule with both selectors to give it higher priority:

#navi.sticky {
  overflow: visible;
}

You can achieve this effect using JavaScript as well. Here's an example:

window.onscroll = function() {
  myFunction()
};

var navbar = document.getElementById("navi");
var sticky = navbar.offsetTop;

function myFunction() {
  if (window.pageYOffset >= sticky) {
    navbar.classList.add("sticky")
  } else {
    navbar.classList.remove("sticky");
  }
}

Make sure your CSS styles match the structure of your HTML elements. For example:

#navi.sticky {
  overflow: visible;
} 

#navi {
  overflow: hidden;
  background-color: #333;
  font-family: Arial;
}

.drop {
  float: left;
  overflow: hidden;
}

/* Rest of the CSS styles go here */

Your HTML structure should look something like this:

<body>
  <header>
    <h1>
      Example for StackOverflow
    </h1>
  </header>
  <nav id="navi">
    <div class="drop">
      <button class="dropbutton">
                Button - dropdown
            </button>
      <div class="links">
        <a href="">Random link 1</a>
        <a href="">Random link 2</a>
        <a href="">Random link 3</a>
      </div>
    </div>
  </nav>
  <article>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
    <p>Just for filling in the page</p>
  </article>
</body>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular 2 404 Error persists despite successful retrieval of data from Oracle database using Backend Nodejs URL entered directly into the browser

Recently, I've been working on displaying data in my Angular frontend that is fetched from an Oracle DB connected to my Node backend. When I access the physical API link, the data appears and is displayed in the backend console.log. I'm wonderin ...

Using TypeScript, let's take a closer look at an example of Angular

I am trying to replicate the chips example found at this link (https://material.angularjs.org/latest/#/demo/material.components.chips) using TypeScript. I have just started learning TypeScript this week and I am having some difficulties translating this co ...

Is it possible to incorporate cmd.exe into an HTML file?

Currently in the process of creating an online batch tutorial and aiming to integrate the Windows command prompt as a dynamic element on my webpage. Initially attempted using the html5 embed tag, however encountered an error stating unsupported plugin. S ...

Retrieval of components from JSON array of objects

I have a JSON array containing objects stored on the server. How can I access the first object to print its contents? The data is in the following format: [ { "eventId": "8577", "datasetId": "34", "nodeId": "8076", "typeId": "4", "type": ...

The presence of an Angular Element within an Angular application can lead to a problematic cycle of constant reloading,

, I am encountering issues with integrating Angular Elements as plugins into my Angular application. The problem arises when building the element with "--prod" - it functions properly with "ng serve" in my development setup but causes infinite reloading wh ...

Is it possible to utilize the function(e) multiple times within a single file?

Can the same function be used multiple times in a single file? document.getElementById('one').onlick = function test(e) { var key = e.which; if(key === 13) { document.getElementById('two').c ...

Utilize Wordpress TinyMCE to apply the underline decoration using the "U" tag instead of the style

Is there a way to modify the function of the button in the WordPress content textarea of TinyMCE? Specifically, I am referring to the "u" button for underline formatting. <span style="text-decoration-line: underline;">text underlined</span> I ...

Angular library is being excluded from the R.js optimizer process

I'm encountering difficulties when trying to optimize an Angular project with the r.js optimizer. Everything works smoothly when I use grunt-requirejs for optimization, but as soon as I attempt to exclude Angular from the build, I encounter an error ...

When using Mongoose populate, it may either return an empty array or a list of Object

Currently, I am honing my skills in express.js by constructing a relational API but facing difficulty in populating keys within a schema. The structure involves having a list of properties, each with associated units. The units are linked through a proper ...

Does ExpressJS always terminate with JSON by default?

I am currently utilizing expressjs to serve JSON data. Upon attempting to use res.end() with an object, I encounter the following error: TypeError: first argument must be a string, Array, or Buffer Is there a specific setting or middleware available tha ...

Is it possible to modify the host header within an Angular app?

I'm experiencing a vulnerability issue and to resolve it, I need to utilize SERVER_NAME instead of the Host header. Is it possible to accomplish this using Angular? ...

What are the steps for utilizing JSON data retrieved from an ajax response?

After successfully making an ajax request and receiving JSON data, I am struggling with how to use it effectively. The response I am getting looks like this: [{ "id": "5", "reviewID": "2389", "serviceID": "50707", "title": "well d ...

Transitioning the width in CSS without using the "auto"

Currently, I am experiencing a problem with my CSS animation that is leaping directly from the start to finish. It appears to be connected to a similar issue addressed in this thread. My inquiry is: Is there a way to create a smooth transition in width f ...

Utilizing Vuetify 2 skeleton-loader to customize loading states through Vuex store manipulation

Utilizing the Vuetify v-skeleton-loader component to wrap a v-data-table component. The server-side pagination and sorting in the data-table component are set up. To enable server-side pagination, the documentation recommends monitoring the options objec ...

Tips for extracting information from a Javascript Prompt Box and transferring it to a PHP variable for storage in an SQL database

My current issue involves a specific function I want my script to perform: before a user rejects an entry on the server side, the system needs to prompt a text box asking for the reason behind the rejection. The inputted reason should then be saved to a My ...

Navigate through collections of objects containing sub-collections of more objects

The backend is sending an object that contains an array of objects, which in turn contain more arrays of objects, creating a tree structure. I need a way to navigate between these objects by following the array and then back again. What would be the most ...

I am encountering an issue where the useState hook is returning an undefined value on separate components, even after

When setting up a login context, I wrap all my routes with the context provider and pass the initial value using useState: <userContext.Provider value={{loggedUser, setLoggedUser}}> In LogInMenu.jsx, which is responsible for setting the loggedUser ( ...

Issue with current time malfunctioning

For my latest project, I've been tasked with creating a karaoke application using javascript. The challenge is to synchronize the lyrics with the song as it plays. Here's a snippet of my HTML code: <div id="lyric"></div> <audio i ...

ReferenceError: 'exports' is undefined in the context of Typescript Jest

I'm currently delving into unit testing with jest and encountered an error that looks like this: > npm run unit > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="771f181012374659475947">[email protected]</ ...

An error occurred while trying to serialize the `.res` response received from the `getServerSideProps` function in

I encountered the following issue while utilizing the getServerSideProps function to fetch data from Binance API. import binance from "../config/binance-config"; export async function getServerSideProps() { const res = await binance.balance(( ...