My problem is along the lines of these previous issues on StackOverflow but with a slight difference.
Previous issues:
Stopping fixed position scrolling at a certain point?
Sticky subnav when scrolling past, breaks on resize
I have a sub nav that starts at a certain position in the page. When the page is scrolled the sub nav needs to stop 127px from the top. Most of the solutions I have found need you to specify the 'y' position of the sub nav first. The problem with this is that my sub nav will be starting from different positions on different pages.
This is the JS code i'm currently using. This works fine for one page but not all. Plus on mobile the values would be different again.
var num = 660; //number of pixels before modifying styles
$(window).bind('scroll', function () {
if ($(window).scrollTop() > num) {
$('.menu').addClass('fixed');
} else {
$('.menu').removeClass('fixed');
}
});
I'm looking for a solution that stops the sub nav 127px from the top no matter where on the page it started from.
You can use position: sticky and set the top of the sub-nav to 127px.
See example below:
body {
margin: 0;
}
.main-nav {
width: 100%;
height: 100px;
background-color: lime;
position: sticky;
top: 0;
}
.sub-nav {
position: sticky;
width: 100%;
height: 50px;
background-color: red;
top: 100px;
}
.contents {
width: 100%;
height: 100vh;
background-color: black;
color: white;
}
.contents p {
margin: 0;
}
<nav class="main-nav">Main-nav</nav>
<div class="contents">
<p>Contents</p>
</div>
<nav class="sub-nav">Sub-nav</nav>
<div class="contents">
<p>More contents</p>
</div>
Please see browser support for sticky here
You should change your code to the below, should work fine:
$(window).bind('scroll', function () {
if ($(window).scrollTop() > $(".menu").offset().top) {
$('.menu').addClass('fixed');
} else {
$('.menu').removeClass('fixed');
}
});
Maybe you can try this:
Find navigation div (.menu)
Find the top value of the .menu (vanilla JS would be menuVar.getBoundingClientRect().top, not sure how jQuery does this).
Get top value of browserscreen.
Calculate the difference - 127px.
When the user scrolls and reaches the top value of the menu -127px -> addClass('fixed').
Related
I have a webpage where there is a full height intro image. Underneath this image is the main body of the site with a regular site header at the top, I'm trying to create an effect where once the user scrolls down to the site header, they cannot scroll back up to view the intro image.
CSS Classes:
Main Intro Image: .cq-fullscreen-intro
Site Header: .nav-down
I had a poke around on StackOverflow but I can't find anything that addresses this circumstance, can anyone point me in the right direction to achieve this using jQuery?
you can use JQuery scrollTop function like this
$(function() {
$(window).scroll(function() {
var scroll = $(window).scrollTop();
// set the height in pixels
if (scroll >= 200) {
// after the scroll is greater than height then you can remove it or hide it
$(".intro-image").hide();
}
});
});
So instead of scrolling, I personally think it would be better to have it be actionable. Forcing the user to manually do the transition (and all in between states) is a bad idea. If the user scrolls half way, and see's something actionable (menu, button, input field) is it usable? If it is, what happens if they submit... very awkward. If it isn't usable, how do they know when it is? How do they know it's because they haven't scrolled all the way. It's very poor user experience.
In the following example, I've created a pseudo-screenport for you to see what's actually going on. The .body container in your real site would be the body element.
Code Pen Example
$(document).ready(function(){
$('.splash-screen').on('click', function(){
$('.splash-screen').addClass("is-hidden");
});
})
html, body{
background: #eee;
margin: 0;
padding: 0;
}
.flex-root {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
}
.web-container {
width: 640px;
height: 480px;
background: #fff;
}
.body {
font-size: 0; // this is only to prevent spacing between img placholders
position: relative;
}
.splash-screen{
position: absolute;
transition: transform 1s ease-in-out;
}
.splash-screen .fa {
position: absolute;
z-index: 1;
font-size: 24px;
color: #fff;
left: 50%;
bottom: 15px;
}
.splash-screen.is-hidden {
transform: translateY(-110%);
transition: transform 1s ease-in-out;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="flex-root">
<div class="web-container">
<div class="body">
<div class="splash-screen">
<img src="https://via.placeholder.com/640x480?text=Splash+Screen"/>
<i class="fa fa-chevron-circle-up"></i>
</div>
<img src="https://via.placeholder.com/640x60/cbcbcb?text=Menu"/>
<img src="https://via.placeholder.com/640x420/dddddd?text=Site Body"/>
<div>
</div>
</div>
While its not direclty preventing you from scrolling up and its not jQuery, I would suggest to remove/hide the element once its out of view.
You could get the current scroll position, relative to the top of the page, and check if its greater than the elements height:
const target = document.getElementById('my-target')
const targetHeight = target.getBoundingClientRect().height
const scrollEventListener = () => {
if (
document.body.scrollTop > targetHeight ||
document.documentElement.scrollTop > targetHeight
) {
target.remove()
window.removeEventListener('scroll', scrollEventListener)
document.documentElement.scrollTop = 0
}
}
window.addEventListener('scroll', scrollEventListener)
Here is a codepen https://codepen.io/bluebrown/full/aboagov
I use this nice little JavaScript to make my navigation bar (which is normally sitting 230px down from the top) stick to the top of the page once the page is scrolled down that 230 px. It then gives the "nav" element a "fixed" position.
$(document).ready(function() {
$(window).bind('scroll', function() {
if ($(window).scrollTop() > 230) {
$('nav').addClass('fixed');
} else {
$('nav').removeClass('fixed');
}
});
});
nav {
width: 90%;
display: flex;
justify-content: center;
max-width: 1400px;
height: 85px;
background-color: rgba(249, 241, 228, 1);
margin: auto;
border-top-left-radius: 0em;
border-top-right-radius: 0em;
border-bottom-left-radius: 2em;
border-bottom-right-radius: 2em;
}
.fixed {
position: fixed;
border-top: 0;
top: 0;
margin: auto;
left: 0;
right: 0;
z-index: 4;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
</ul>
</nav>
Now, the problem: i have positioned the corresponding anchor targets
within the page and have given them some "padding-top" to account for the fixed navbar (about 90px), so that they don't disappear behind the bar when the page jumps to them after clicking.
.anchor {
padding-top: 90px;
}
<a class="anchor" id="three">
This works fine AS LONG AS the navbar is already fixed to the top.
But if you click on a link while the navbar is still in its original mid-page position (e.g. the first click the user will do), it just disregards the offset i gave the anchor target and jumps to a weird position where the anchor target is hidden behind the navbar (and not even aligned with the top of the page)!
If i THEN click on the link again (now in the fixed bar on top of the page), it corrects itself and displays the page as i want to. But that first click always misses - i can't figure out why! Please help
EDIT: WORKING DEMO here: http://www.myway.de/husow/problem/problem.html
1st Add a new class name spacebody to your first div with class="space"
<nav>
...
</nav>
<div class="space spacebody">
</div>
2nd JS use the following should fix your problem:
$(document).ready(function() {
$(window).bind('scroll', function() {
if ($(window).scrollTop() > 230) {
$('nav').addClass('fixed');
$('.spacebody').css('margin-top', '85px');
} else {
$('nav').removeClass('fixed');
$('.spacebody').css('margin-top', '0px');
}
});
});
Reason Why?
because when your nav is not fixed, it has a height of 85px, when you scroll down it has no height which is 0 height. Then everything below move up by 85px causing your to go below the target of ONE or TWO etc. It is not you are missing the first click, it is when the nav are not fixed and the click you will be scroll more down by 85px. If you scroll to top and click you will miss again.
You can easily see this if you change your CSS for nav with background-color: transparent;
With the code above should fix it when you nav become fixed to add a margin-top as 85px to the div below so they keep the same height as you clicked.
Or can someone tell me another way to do this (without using a plugin please)
I have a side nav on the left and some content to the right. Both elements are floated left.
I want the side nav to 'stick' when it gets to 125px from the top of the window, once scrolled down the page.
I feel like I'm close, but I'm definitely not there yet! With the code I have written, the side-nav 'jumps' up to the top of the window once we scroll to the correct window position and then it's going back to the position where I want it to 'stick'.
The other issue, is that once the .stick class is applied, the element is taken out of the document flow (because I'm applying a position: fixed;) and the .content moves over to the left to take it's place.
Here is a codepen: http://codepen.io/MandyMadeThis/pen/DLtsJ
** NOTE: It seems I can't recreate the side-nav 'jumping' to the top of the window on scroll, so I don't what that's all about, but I'd still like to know the correct way to do this without the content moving over to the left.**
If anyone can guide me in the right direction, that would be wonderful. Thank you.
Here is my markdown:
<body>
<nav>navigation content</nav>
<header>header content</header>
<div class="container clearfix">
<div class="side-nav">THIS IS THE THING I WANT TO STICK</div>
<div class="content">This needs to stay to the right of the .side-nav</div>
</body>
Here is the CSS:
.side-nav {
float: left;
position: relative;
top: -17px;
width: 23%;
margin-right: 2%;
}
.content {
width: 70%;
float: left;
}
.stick {
position:fixed;
top:0px;
margin-top: 125px;
}
And here is my jQuery:
var sn = $(".side-nav");
var pos = sn.position();
$(window).scroll(function() {
var windowPos = $(window).scrollTop();
if (windowPos >= pos.top - 125) {
sn.addClass("stick");
} else {
sn.removeClass("stick");
}
});
To fix this you simply need to add a margin-left to .content and remove float. This way the position of the content does not rely on the nav being there.
.content {
width: 70%;
margin-left: 25%;
}
http://codepen.io/anon/pen/jbCix
Goal
To have the page navigation positioned lower on the page when initially loaded. So that it looks like pictured below.
Background
I created a navigational element that is using Headroom.js to control its position. The point of the library is that it moves the desired navigational item out of view when a user is scrolling down so that you can see more content. Then the item shows up when you scroll back up to make it convenient to click on a link if that is what you needed to do.
Current State
I have this current demo on codepen.
That navigational item is at the top of the page but on a lower z-index. So not initially visible.
when you scroll down the element is out of view.
But when you scroll up, it is where it needs to be
Code
HTML
<nav id="page-menu" class="link-header header--fixed slide slide--reset" role="banner">
<ul>
<li>Products</li>
<li>Features</li>
<li>Testimonials</li>
<li>Cases</li>
</ul>
</nav>
CSS
#page-menu {
background-color: #BA222B;
list-style-type: none;
width: 100%;
z-index:10;
}
#page-menu ul {
list-style-type: none;
margin: 0;
position: absolute;
bottom: 5px;
right: 10px;
}
#page-menu ul li {
display: inline-block;
margin-left: 10px;
}
#page-menu ul li a {
text-decoration: none;
color: #fff;
}
.link-header {
background-color:#292f36;
height: 100px;
}
.header--fixed {
position:fixed;
z-index:10;
right:0;
left:0;
top:0px;
}
jQuery
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 150,
classes: {
initial: "slide",
pinned: "slide--reset",
unpinned: "slide--up"
}
}).init();
}());
Full demo on codepen.
Goal :
From what you are describing, you want the read navigation to appear as such on page load:
And move with the gray bar, but and down, as the user scrolls, until it cutoff point reaches the bottom of the gray bar. Then you want things to kick in, and have the red bar slide up and out of view, and then up and down depending on scroll. You want the transition to be smooth.
Method:
The thing to keep in mind for a smooth transition is that you have two states: A top state and a bottom state. You have to design both, you have to figure out the exact height to change over, and you have to make sure that they will be identical at that spot, so appear seamless.
Top State:
We don't need any sort of extra positioning here. We want it to be static in fact, as odd as that might sound.
Bottom State:
We want fixed positioning here. Since we want the changeover to occur right when the red bar touches the top of the window, your CSS in fixed-header is perfect already.
Changeover Height:
The header and the gray nav bar combined are 180px, so that number will be our change over.
Code:
1. Statechange
Lets work backwards and take the state change first. You will need to change from 150px to 180px in a lot of places. For example, your JS code:
Existing JS:
if ($(window).scrollTop() >= 150) {
...
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 150,
New JS:
if ($(window).scrollTop() >= 180) {
...
(function() {
new Headroom(document.querySelector("#page-menu"), {
tolerance: 5,
offset : 180,
And your header will need an updated height, or a removal of height entirely.
Existing CSS:
header {
height:150px;
position: relative;
z-index:30;
}
New CSS:
header {
position: relative;
z-index:30;
}
2. Top State
The big thing here messing you up is that for some reason the library you are using is applying .header--fixed and link-header on page load. I don't know how to prevent this, but we can just neutralize is by removing them from your CSS.
Remove This CSS:
.link-header {
background-color:#292f36;
height: 100px;
}
.header--fixed {
position:fixed;
z-index:10;
right:0;
left:0;
top:0px;
}
Second, we need to tweak the ul inside your red nav.
Existing CSS:
#page-menu ul {
list-style-type: none;
margin: 0;
position: absolute;
bottom: 5px;
right: 10px;
}
New CSS:
#page-menu ul {
list-style-type: none;
margin: 0 auto;
padding:0;
width:960px;
max-width:100%;
text-align:right;
}
3. Bottom State
Everything works really well here aleady, except that the fixed-header class is getting added to the gray nav as well. We need to tweak our jQuery selector bit.
Existing JS:
if ($(window).scrollTop() >= 180) {
$('nav#page-menu').addClass('fixed-header');
}
else {
$('nav#page-menu').removeClass('fixed-header');
}
NewJS:
if ($(window).scrollTop() >= 180) {
$('header nav').addClass('fixed-header');
}
else {
$('header nav').removeClass('fixed-header');
}
4. Misc Cleanup
Everything looks really good here, except that the lis inside our two navs don't line up. We need to fix some margin-right to bring them into line.
Existing CSS:
#page-menu ul li {
display: inline-block;
margin-left: 10px;
}
New CSS:
#page-menu ul li {
display: inline-block;
margin-left: 10px;
margin-right: 10px;
}
Finally, I noticed that there's a missing closing bracket in your HTML, in the gray nav. It's not hurting much, but it could:
<nav>
<ul>
<li>Dentists</li>
<li>Labs</li>
<li>Patients</li>
<ul> <--- ( Should be </ul> )
</nav>
End Result:
http://codepen.io/anon/pen/qIrhx
I am attempting to create a navigation bar that remains fixed only after it has reached the top of the page. I have the code working so that the nav is fixed, but I can't seem to get it to scroll to the top first.
Here's the HTML:
<div id= "home"> contentcontentcontent </div>
<div id="nav">
home
go green
your area
how to</div>
And the CSS:
nav {
text-align: center;
top: 600;
z-index: 100;
position: fixed;
width: 100%;
border: 0;
margin-bottom: 0;}
fixed {
top:600;
z-index: 100;
position: fixed;
width: 100%;}
home {
overflow: hidden;}
And the jQuery:
$(document).ready(function() {
$(window).scroll(function () {
//console log determines when nav is fixed
console.log($(window).scrollTop())
if ($(window).scrollTop() > 600) {
$('#nav').addClass('fixed');
}
if ($(window).scrollTop() < 601) {
$('#nav').removeClass('fixed');
}
});
These were based off of responses to similar questions on this site, but nothing has seemed to work so far. Does anyone know what's wrong with my code?
When writing a CSS selector, ids and classes need to be prefixed by a # or a . respectively. In your CSS you have
nav { // rules }
fixed { // rules }
home { // rules }
When you should have
#nav { // rules }
.fixed { // rules }
#home { // rules }
Here is a fiddle of your code working.