0

When my navbar touches the top of the screen, the links of the dropdown menu are disappearing.

I've used w3schools tutorials and examples to create my page. Especially:

This is the example of my problem:

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>
David
  • 6,695
  • 3
  • 29
  • 46

1 Answers1

1

The correct question would be "Why we can see the dropdown when the navbar is not at the top of the screen?".

The navbar has the CSS property overflow set to hidden, preventing content out of its boundaries to get visible. But the div containing the drop-down links (.links) has position set to absolute, so it is out of the document flow.

From MDN:

absolute

The element is removed from the normal document flow, and no space is created for the element in the page layout. It is positioned relative to its closest positioned ancestor, if any; otherwise, it is placed relative to the initial containing block.

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

But when the navbar touches the top of the screen, the .sticky class gets applied. Its mainly function is to set the position CSS property to fixed (out of the document flow and positioned relative to the initial containing block established by the viewport).

When .sticky is applied, .links is positioned relative to navbar, so it gets affected for overflow: hidden.

Because you don't need to hide it when .sticky applies, set the overflow property of the navbar to visible when that happens.

In CSS, the id attribute has priority over the class so you have two options. Update the .sticky class:

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

That will lead sooner or later to an !important nightmare. Or much better, create a new rule containing both selectors to give it a higher priority:

#navi.sticky {
  overflow: visible;
}

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.sticky {
  overflow: visible;
} 

#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>
Community
  • 1
  • 1
David
  • 6,695
  • 3
  • 29
  • 46