Difference Between Position:Sticky and Position:Fixed

How does the position: sticky; property work?

Sticky positioning is a hybrid of relative and fixed positioning. The element is treated as relative positioned until it crosses a specified threshold, at which point it is treated as fixed positioned.

...

You must specify a threshold with at least one of top, right, bottom, or left for sticky positioning to behave as expected. Otherwise, it will be indistinguishable from relative positioning.
[source: MDN]

So in your example, you have to define the position where it should stick in the end by using the top property.

html, body {
height: 200%;
}

nav {
position: sticky;
position: -webkit-sticky;
top: 0; /* required */
}

.nav-selections {
text-transform: uppercase;
letter-spacing: 5px;
font: 18px "lato", sans-serif;
display: inline-block;
text-decoration: none;
color: white;
padding: 18px;
float: right;
margin-left: 50px;
transition: 1.5s;
}

.nav-selections:hover {
transition: 1.5s;
color: black;
}

ul {
background-color: #B79b58;
overflow: auto;
}

li {
list-style-type: none;
}
<nav>
<ul align="left">
<li><a href="#/contact" class="nav-selections" style="margin-right:35px;">Contact</a></li>
<li><a href="#/about" class="nav-selections">About</a></li>
<li><a href="#/products" class="nav-selections">Products</a></li>
<li><a href="#" class="nav-selections">Home</a></li>
</ul>
</nav>

Fixing navbar using fixed position or sticky position

1. position : sticky

The easiest way by far is to use sticky position but on header not on nav. Because as element I am sticky as long as my parent is visible on the screen. And since the height of header is not that big, it seems like having position:sticky on nav is not working. To know more about position sticky, you could read here.

Here is the working example:

* {
box-sizing: border-box;
}

body {
font-family: "Roboto", sans-serif;
min-height: 100vh;
background-color: #eee;
color: black;
}

.wrapper {
display: flex;
justify-content: center;
flex-direction: column;
}
/* lines I added*/
header {
position: sticky;
top: 0;
z-index: 99;
background: #eee;
}
nav {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
font-weight: 900;
font-size: 1em;
padding: 20px 10px;
flex-wrap: wrap;
border-bottom: 1px solid grey;
}

ul {
flex-grow: 1;
max-width: 30%;
display: flex;
justify-content: space-around;
text-decoration: none;
}

img {
display: flex;
width: 40vw;
}

ul li {
display: inline;
text-decoration: none;
display: flex;
}

.nav-links a {
text-decoration: none;
color: black;
}

.hero {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

h1 {
font-size: 2em;
font-weight: 700;
padding: 20px;
}

h2 {
font-size: 1.4em;
font-weight: 700;
}

p {
font-size: 0.8em;
letter-spacing: 0.05em;
}

input[type="email"] {
padding: 5px 10px;
margin: 10px 0px;
border: solid 1px black;
width: 350px;
}

form {
display: flex;
flex-direction: column;
align-items: center;
}

input[type="submit"] {
margin: 10px auto;
padding: 5px 15px;
background-color: #f1c40f;
font-weight: 900;
border: #eee solid 0px;
}

.bus-info {
display: flex;
flex-direction: column;
justify-content: center;
}

.features {
display: flex;
align-items: center;
justify-content: space-evenly;
}

.desc {
weight: 125px;
width: 80vw;
padding: 5px;
}

.icon {
color: #c5a00df8;
font-size: 2em;
}

.feat-title {
}

.features {
padding-top: 20px;
border: 40px 0px;
}

.video {
margin: auto;
padding: 30px 0px;
}

.tromb-types {
display: flex;
justify-content: center;
}

.type {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px 50px;
margin: 20px 10px;
border: solid black 1px;
}

.title-tromb {
font-weight: 700;
font-size: 0.8em;
}

.price {
padding: 20px 0;
}

.tromb-desc {
display: flex;
flex-direction: column;
align-items: center;
}

.text {
padding-bottom: 10px;
}

footer {
display: flex;
flex-direction: column;
align-items: flex-end;
margin-bottom: 20px;
margin-right: 20px;
}

.footer-links {
display: flex;
justify-content: flex-end;
align-items: flex-end;
max-width: 100%;
}

.footer-links .footer-link {
text-decoration: none;
padding: 0px 10px;
color: black;
}

.copyright {
max-width: 100%;
margin-top: 5px;
}

@media (max-width: 700px) {
header {
font-size: 1em;
}

nav {
display: flex;
flex-direction: column;
}

nav > ul {
display: flex;
flex-wrap: wrap;
}

.tromb-types {
flex-direction: column;
justify-content: center;
align-items: center;
}

.type {
width: 300px;
}

.price {
padding: 5px 0;
}
}
<div class="wrapper">
<header>
<nav class="Navbar">
<img src="https://cdn.freecodecamp.org/testable-projects-fcc/images/product-landing-page-logo.png" alt="original trombones logo" class="nav-img">
<ul class="nav-links">
<li><a href="#" class="link">Features</a></li>
<li><a href="#" class="link">How It Works</a></li>
<li><a href="#" class="link">Pricing</a></li>
</ul>
</nav>
</header>
<section class="hero">
<h1>Handcrafted, home-made masterpieces</h1>
<form class="email-form">
<div class="email-form">
<label for="email"></label>
<input type="email" name="email" id="email" placeholder="Enter your email address" required>
</div>
<div class="button-center">
<input class="sub-button" type="submit" value="GET STARTED">
</div>
</form>
</section>

<section class="bus-info">
<div class="features">
<div class="icon"><i class="fas fa-fire"></i></div>
<div class="desc">
<h2 class="feat-title">Premium materials</h2>
<p class="desc-words">Our trombones use the shiniest brass which is sourced locally. This will increase the longevity of your purchase.</p>
</div>
</div>
<div class="features">
<div class="icon"><i class="fas fa-truck"></i></div>
<div class="desc">
<h2 class="feat-title">Fast Shipping</h2>
<p class="desc-words">We make sure you recieve your trombone as soon as we have finished making it. We also provide free returns if you are
not satisfied.</p>
</div>
</div>
<div class="features">
<div class="icon"><i class="fa-solid fa-battery-full"></i></div>
<div class="desc">
<h2 class="feat-title">Quality Assurance</h2>
<p class="desc-words">For every purchase you make, we will ensure there are no damages or faults and we will check and test the pitch of your
instrument.</p>
</div>
</div>
</section>

<section class="video">
<iframe width="420" height="315" src="https://www.youtube.com/embed/tgbNymZ7vqY">
</iframe>
</section>

<section class="tromb-types">
<div class="type">
<h3 class="title-tromb">TENOR TROMBONE</h3>
<h2 class="price">$600</h2>
<div class="tromb-desc">
<p class="text">Lorem ipsum.</p>
<p class="text">Lorem ipsum.</p>
<p class="text">Lorem ipsum dolor.</p>
<p class="text">Lorem ipsum.</p>
</div>
<div class="select-button">
<input class="sub-button" type="submit" value="SELECT">
</div>
</div>

<div class="type">
<h3 class="title-tromb">BASS TROMBONE</h3>
<h2 class="price">$900</h2>
<div class="tromb-desc">
<p class="text">Lorem ipsum.</p>
<p class="text">Lorem ipsum.</p>
<p class="text">Lorem ipsum dolor.</p>
<p class="text">Lorem ipsum.</p>
</div>
<div class="select-button">
<input class="sub-button" type="submit" value="SELECT">
</div>
</div>

<div class="type">
<h3 class="title-tromb">VALVE TROMBONE</h3>
<h2 class="price">$1200</h2>
<div class="tromb-desc">
<p class="text">Lorem ipsum.</p>
<p class="text">Lorem ipsum.</p>
<p class="text">Lorem ipsum dolor.</p>
<p class="text">Lorem ipsum.</p>
</div>
<div class="select-button">
<input class="sub-button" type="submit" value="SELECT">
</div>
</div>
</section>

<footer>
<ul class="footer-links">
<li><a href="#" class="footer-link">Privacy</a></li>
<li><a href="#" class="footer-link">Terms</a></li>
<li><a href="#" class="footer-link">Contacts</a></li>
</ul>
<p class="copyright">Copyright 2016, Original Trombones</p>

</footer>
</div>

Fixed position but relative to container

Short answer: no. (It is now possible with CSS transform. See the edit below)

Long answer: The problem with using "fixed" positioning is that it takes the element out of flow. thus it can't be re-positioned relative to its parent because it's as if it didn't have one. If, however, the container is of a fixed, known width, you can use something like:

#fixedContainer {
position: fixed;
width: 600px;
height: 200px;
left: 50%;
top: 0%;
margin-left: -300px; /*half the width*/
}

http://jsfiddle.net/HFjU6/1/

Edit (03/2015):

This is outdated information. It is now possible to center content of an dynamic size (horizontally and vertically) with the help of the magic of CSS3 transform. The same principle applies, but instead of using margin to offset your container, you can use translateX(-50%). This doesn't work with the above margin trick because you don't know how much to offset it unless the width is fixed and you can't use relative values (like 50%) because it will be relative to the parent and not the element it's applied to. transform behaves differently. Its values are relative to the element they are applied to. Thus, 50% for transform means half the width of the element, while 50% for margin is half of the parent's width. This is an IE9+ solution

Using similar code to the above example, I recreated the same scenario using completely dynamic width and height:

.fixedContainer {
background-color:#ddd;
position: fixed;
padding: 2em;
left: 50%;
top: 0%;
transform: translateX(-50%);
}

If you want it to be centered, you can do that too:

.fixedContainer {
background-color:#ddd;
position: fixed;
padding: 2em;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}

Demos:

jsFiddle: Centered horizontally only

jsFiddle: Centered both horizontally and vertically

Original credit goes to user aaronk6 for pointing it out to me in this answer

Why is my css attribute position sticky not working?

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 class="header-container">
<h1><a class="logo-link" href="#">Tour</a></h1>
<ul class="nav-menu">
<li><a class="link" href="#">Home</a></li>
<li><a class="link" href="#">About us</a></li>
<li><a class="link" href="#">Social Media</a></li>
<li><a class="link" href="#">Comment</a></li>
<li><a class="link" href="#">Share</a></li>
</ul>
</div>
<div class="explore-btn">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%
}

How to fix: sticky position behaving like fixed?

Update the top to be 0px so that it sticks at top of the page

#sticky {
position: sticky;
background: orange;
top:0px;
z-index: 50;
width: 100%;
height:50px;
}

You can also have a look at this example



Related Topics



Leave a reply



Submit