Home > front end >  Why is my css attribute position sticky not working?
Why is my css attribute position sticky not working?

Time:02-17

I tried to make a navigation bar that sticks to the top, but it's not working. I also tried to make the div position:fixed to top, but the div overlaps with the others after scroll, so I gave up on the position:fixed. How do I get position:sticky to work?

Here is my code:

var navbar = $('header:first');

$(window).scroll(function() {

  if (window.pageYOffset >= 120) {


    $('#nav-hidden').css({
      'display': 'none'
    });

    $('header:first').css({
      'background': 'none',
      'height': '20vh'
    });

    navbar.addClass('sticky')

  } else {
    $('#nav-hidden').css({
      'display': 'inherit'
    });

    $('header:first').css({
      'background': "linear-gradient(to bottom,rgba(255, 255, 255, 1.0) 40%,rgba(255, 255, 255, 0.5)), url('background.jpg') center no-repeat",
      'height': '100vh',
      'position': 'inherit'
    });
    navbar.removeClass("sticky");
  }
});
* {
  padding: 0;
  margin: 0;
}

html body {
  min-height: 100%;
  height: 100%;
  scroll-behavior: smooth;
}

header {
  height: 100vh;
  width: 100%;
  position: inherit;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 1.0) 40%, rgba(255, 255, 255, 0.5)), url('background.jpg') center no-repeat;
  background-size: cover;
}

nav {
  padding: 3rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 1.6rem;
  font-family: 'Roboto', sans-serif;
}

nav ul {
  display: flex;
  margin-top: auto;
}

nav ul li {
  list-style: none;
}

nav ul li a {
  padding: 2rem;
  font-weight: bold;
  color: rgba(1, 1, 1, .9);
}

.logo a {
  color: rgba(1, 1, 1, 1);
  font-weight: bolder;
  font-size: 4rem;
}

a:link {
  text-decoration: none;
}

a:visited {
  text-decoration: none;
}

a:hover {
  text-decoration: none;
  color: rgba(1, 1, 1, .8);
}

a:focus {
  text-decoration: none;
  color: rgba(1, 1, 1, .5);
}

#nav-hidden {
  position: absolute;
  text-align: left;
  bottom: 60vh;
  left: 8vw;
}

.container {
  height: 100vh;
  width: 100%;
  padding-top: 20vh;
}

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

.content {
  background: rgba(1, 1, 1, .2);
}
<!DOCTYPE html>
<html>

<head>

  <title> Main</title>
  <link rel="stylesheet" href="style.css">

</head>

<body>
  <header>
    <nav>
      <h1 ><a href="Main.html">Tour</a></h1>
      <ul >
        <li><a href="">Home</a></li>
        <li><a href="">About us</a></li>
        <li><a href="">Social Media</a></li>
        <li><a href="">Comment</a></li>
        <li><a href="">Share</a></li>
      </ul>

    </nav>
    <div id="nav-hidden">Explore.</div>
  </header>

  <div  >hi</div>

  <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
  <script language="JavaScript" type="text/javascript" src="script.js"></script>
</body>

</html>

CodePudding user response:

So, your code is difficult to debug, because it has been written in a complex way. I provided some guidance on how you can refactor the code, which will make it easier to fix.

First, update your HTML to use classes (where appropriate), so that your CSS rules can reference classes instead of DOM elements. For example, you can update your header to be something like:

...

<div >
  <h1><a  href="#">Tour</a></h1>
  <ul >
    <li><a  href="#">Home</a></li>
    <li><a  href="#">About us</a></li>
    <li><a  href="#">Social Media</a></li>
    <li><a  href="#">Comment</a></li>
    <li><a  href="#">Share</a></li>
  </ul>
</div>
<div >Explore</div>

...

Then your CSS becomes something like:

...

.header-container {
  padding: 3rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 1.6rem;
  font-family: 'Roboto', sans-serif;
}

.nav-menu {
  display: flex;
  margin-top: auto;
}

.link {
  padding: 2rem;
  font-weight: bold;
  color: rgba(1, 1, 1, .9);
}

.link:link {
  text-decoration: none;
}

.link:visited {
  text-decoration: none;
}

.link:hover {
  text-decoration: none;
  color: rgba(1, 1, 1, .8);
}

.link:focus {
  text-decoration: none;
  color: rgba(1, 1, 1, .5);
}

.logo-link {
  color: rgba(1, 1, 1, 1);
  font-weight: bolder;
  font-size: 4rem;
}

.explore-btn { 
  display: block;
  position: absolute;
  text-align: left;
  bottom: 60vh;
  left: 8vw;
}

.explore-btn .hidden {
  display: none;
}

...

The following styles should be part of a base set of styles that you define alongside a standard stylesheet reset file:

* {
  padding: 0;
  margin: 0;
}

html body {
  min-height: 100%;
  height: 100%;
  scroll-behavior: smooth;
}

...

The CSS in that JS file should be converted into utility classes which get toggled on/off using something like:

...

$(window).scroll(function() {
  if (window.pageYOffset >= 120) {
    $('.explore-btn').addClass('hidden');
  } else {
    $('.explore-btn').removeClass('hidden');
  }
});

Notice that I don't use id selectors. Avoid them if you can, because they make your selectors brittle by being too specific. Also, avoid using HTML elements as selectors (except in your base rules), because you want to avoid your CSS from "bleeding" into other places in unintended ways. Defining specific classes on elements (that you intend to style) is a good way of managing scope.

If I see a style defined in your HTML, I know that it exists somewhere in your CSS. It should be a flat selector (if possible). Keep it simple. The only nested selector I use is the one where explore-btn toggles between hidden and visible. This is a good system.

If you find yourself repeating the same styles across multiple classes, then that's a sign that you should refactor it. Similarly, if you find yourself nesting selectors too deeply (e.g. nav ul li a), you probably want to define a special class for that element (e.g. .link). There's always exceptions, but you should aim for the simplest approach first.

Once you're done refactoring the code then save your code here: https://jsfiddle.net/ and ping me with a link. I can take another look.

UPDATE:

So, you can find an example of a sticky header here: https://jsfiddle.net/yj49tn6r/

Using your refactored code, all I needed to do was define a JQuery method that toggled the sticky class on the header-container:

 $(window).scroll(function () {
   if (window.pageYOffset >= 120) {
    $(".header-container").addClass("sticky");
  } else {
    $(".header-container").removeClass("sticky");
  }
});

Then define the utility class itself:

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

CodePudding user response:

You can also add a margin to the top of the page, when you use the fixed div:

body::before {
    content: "";
    display: block;
    margin-top: 6rem;
}

Or much better, please read about "scroll-padding-top": https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-padding-top it is fully supported.

  • Related