Reveal nav when scrolling down - javascript

What I'm trying to achieve is when a page is scrolled down the navigation is hidden - as in it disappears off the top of the screen like it traditionally would. When a user scrolls back up the page, the navigation slides into view again. Likewise, if you scroll down again, it's hidden.
I've tried a few different plugins for this and they nearly work. The one I'm currently looking at is "jquery-unveiled-navigation"
Link: https://github.com/weaintplastic/jquery-unveiled-navigation
Example: http://codepen.io/weaintplastic/full/RNpXOO/
This very nearly does what I want it to. It could do with some classes once the script is 'active'. As I only want to add a background-color when the script is 'active'. So it would be transparent until the navigation had left the screen and wasn't at the top.
Also, I know with this navigation if you scroll back up so half the navigation is in view, it will quickly adjust so you can see the bar in it's entirety. But I quite like the idea of it only showing as much as you've scrolled up by. So if the nav is 100px tall, and you scroll 30px, you only see the bottom 30px of the bar. Scrolling back down would hide the bar again, pixel by pixel - does that make sense?
So the steps would be (if this makes it clearer):
Header at the top of the page, transparent background.
When scrolling down, pixel by pixel the navigation leaves the screen.
When the user scrolls back up, the header starts to reveal it's self again - this time is has a background-color.
Once header hits the top of the browser again, the background is removed.
My markup is pretty simple. The bar only holds a logo and navigation toggle as the nav is hidden until the toggle is clicked, which displays the nav full screen.
<header class="page-head">
<span>Menu</span>
<nav class="site-nav">
<ul class="site-nav__list">
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
</ul>
</nav>
</header>
I've removed the SVG I have within page-head__home-link otherwise it would be a wall of code!
Hope someone can help :)

You can do this pretty easily without jquery or a library. You just need to watch the scroll event and when the direction changes place the header just above the field of vision and then as you continue to scroll make sure it never moves off of the top of the parent container.
var body, direction, margin, pageHead, pageHeadHeight, scrolled;
body = document.getElementById('tall');
scrolled = 0;
direction = null;
pageHead = document.getElementsByClassName('page-head')[0];
pageHeadHeight = pageHead.offsetHeight - 1;
margin = 0;
body.addEventListener("scroll", function(event) {
if (scrolled < body.scrollTop) {
direction = 'down';
} else {
if (direction === 'down') {
direction = 'up';
margin = Math.max(0, body.scrollTop - pageHeadHeight);
}
if (margin > body.scrollTop) {
margin = body.scrollTop;
}
pageHead.style['margin-top'] = margin + 'px';
}
return scrolled = body.scrollTop;
});
.tall {
background-color: blue;
min-height: 3000px;
min-width: 100%;
}
#tall {
max-height: 180px;
border: 3px solid pink;
overflow: auto;
}
.page-head{
color: white;
display: inline-block;
}
a {
color: white;
}
<div id="tall">
<div class='tall'>
<header class="page-head">
<span>Menu</span>
<nav class="site-nav">
<ul class="site-nav__list">
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
<li class="site-nav__item">Link</li>
</ul>
</nav>
</header>
</div>
</div>

Related

Adjust height dynamically

I have the following snippets in my code that help me achieve a fixed-top-navigation-on-scroll.
HTML:
<nav>
<button class="navbar-toggler navbar-static-top hidden-sm-up" type="button" data-toggle="collapse" data-target="#navbar-header" aria-controls="navbar-header">
☰
</button>
<div class="collapse navbar-toggleable-xs" id="navbar-header">
<img class="navbar-brand" src="pics/logonavigation.png"/>
<ul class="nav navbar-nav">
<li class="nav-item">
<a class="nav-link smoothScroll" href="#navigation">HOME</a>
</li>
<li class="nav-item">
<a class="nav-link smoothScroll" href="#about">ABOUT</a>
</li>
<li class="nav-item">
<a class="nav-link smoothScroll" href="#services">OUR SERVICES</a>
</li>
<li class="nav-item">
<a class="nav-link smoothScroll" href="#contact">CONTACT US</a>
</li>
</ul>
</div>
</nav>
JAVASCRIPT:
<script>
$(document).ready(function(){
$(window).bind('scroll', function() {
var navHeight = $( window ).height() - $('nav').height();
if ($(window).scrollTop() > navHeight) {
$('nav').addClass('fixed');
}
else {
$('nav').removeClass('fixed');
}
});
$('.navbar-toggler').click(function() {
var newHeight = $('nav').height();
$(".fixed").height(newHeight);
});
});
</script>
CSS:
.fixed {
position: fixed;
background-color: rgba(0, 0, 0, 0.8);
top: 0;
z-index: 1;
height: 50px;
}
The entire file pastebin can be found HERE
I am using bootstrap v4
Viewing the site in mobile view the following is observed:
The collapsible portion of the navigation is left "bare" without the black background. What I would like is to get the effect below:
I cannot use the class "navbar" at because somehow it interferes with the fixed-top-navigation-on-scroll. How can I get the background of the collpasible portion of the navigation in mobile view to appear black? I tried adjusting the height of .fixed dynamically using jquery but it doesn't work.
It's better to put your code into something more universally used like JSfiddle or CodePen.
Since I don't have a Pastebin account and can't easily run the code, I'll take a guess. Based on what I can see here, because your nav is gaining the .fixed class with a fixed height: 50px;, you're not going to get the black background behind the menu because it's only 50px tall.
Try changing it to height: auto;, assuming height is 50px before it gains .fixed. I'd also add a transition: height Xs; on it because when height is set to auto, it will "grow" to cover the menu.
EDIT
One big issue here is that you've declared a top AND bottom value on .nav. This was causing the full height for the .fixed nav. So remove that.
Then change the second half of your jQuery to this:
$(function() {
$('.navbar-toggler').click(function() {
$('nav').css('height', 'auto');
});
})
So when .navbar-toggler is clicked, we add height: auto; to the nav.
This worked for me upon testing, as far as getting the navbar to expand to include the menu items without going full browser height.
I recognize that pulling bottom: 0 out from nav will cause placement issues relative to #screen1, but I don't understand why you put the nav inside that section anyway. I would put it between #section1 and #section2.
You could change the height for #section1 to be calc(100vh - 50px) so that the navbar fits perfectly at the bottom of the screen.

navbar opacity/rgba change on scroll

I've been trying to create a nav that would be transparent at the top and would gain white color as the user scrolls down the page. My header height is 800px and I want my nav to lose 100% of transparency after those 800px. Here`s my code:
<header id="header">
<nav class="navbar">
<ul class="navigation">
<li>Home</li>
<li>About us</li>
<li>Our qualities</li>
<li>Contact us</li>
<li>contact us</li>
</ul>
</nav>
nav {
width: 1600px;
position: fixed;
top: 0;
ul {
margin: 0 auto;
li {
display: inline-block;
padding: 5px 20px;
a {
font-family: $f1;
font-size: 16pt;
color: $c3;
}
}
}
}
}
First I tried with opacity, but it didn't work, and on top of that child elements (ul and li) had opacity of 0 as well.
Here`s the JS for that:
jQuery(document).ready( function() {
var navOffset = jQuery("nav").offset().top;
jQuery(window).scroll(function() {
var scrollPos = jQuery(window).scrollTop();
var navOpacity = scrollPos /800;
jQuery('.navbar').css(opacity, 'navOpacity');
if (jQuery('nav').css('opacity') < 1) {
jQuery('.navigation').css('opacity', '1')
};
Then I tried to change RGBA value on scroll, that didn't work either
Instead of
jQuery('.navbar').css( opacity, 'navOpacity' );
I used
jQuery('.navbar').css(backgroundcolor, 'rgba (255, 255, 255, + "navOpacity")');
That failed as well, so, I have to ask you too help me
You have made opacity not a string, but the variable navOpacity has become a string. That was wrong. Everything else is working fine in general. :)
// change
$('.navbar').css(opacity, "navOpacity");
// to
$('.navbar').css("opacity", navOpacity);
Working example.
The issue in your code is that you're providing navOpacity as a string to css(), instead of the variable itself. Try this:
$('.navbar').css('opacity', navOpacity);
Also note that your current logic is backwards to what you describe as your goal (the header starts transparent and becomes opaque at 800px) and the logic can also be simplified a lot. Try this:
$(window).scroll(function() {
var pc = $(this).scrollTop() / 800;
$('.navbar').css('opacity', 1 - pc);
});
Working example
Alternatively you could use jquery method .fadeTo() instead of css('opacity'). This method animates the opacity of the elements smoothly. It is easier to use and the animation is pretty good looking compared to instant opacity change.
jQuery('.navbar').fadeTo( "slow" , navOpacity);
if (jQuery('nav').css('opacity') < 1) {
jQuery('.navigation').fadeTo( "slow" , 1);
};

Twitter's Bootstrap fixed-to-top navbar on scroll with in-page anchor links bouncing

I have a web page with a top horizontal navigation bar – it is Twitter's Bootstrap Fixed Top Navbar to be more precise – with a bottom-fixed position (actually it's not really fixed by CSS; see JavaScript below) so the navigation bar will first be visible at the bottom of the page and later displayed at the top of the page when scrolling (position: fixed; top: 0).
I have the navigation links set up with anchor tags to take the viewer to various places in the body of the page. Unfortunately, sometimes it takes the user a bit too far down (especially if the user is at the top of the page and the navigation bar has not yet became fixed).
Take a look at my HTML structure:
<div id="landing"></div>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li>Home</li>
<li>Section 1</li>
<li>Section 2</li>
<li>Section 3</li>
</ul>
</div>
</div>
</nav>
<div id="section1"></div>
<div id="section2"></div>
<div id="section3"></div>
I'm using the following JavaScript to ensure that the navbar sticks to the top of the page after scrolling down:
function init() {
nh = 50; // navbar height
sh = $(window).height();
ih = sh-nh;
$("#landing").css('height', ih+'px');
}
function navbarState() {
if ($(window).scrollTop() > ih) {
$('.navbar').addClass('navbar-fixed-top');
} else {
$('.navbar').removeClass('navbar-fixed-top');
}
}
init();
navbarState();
$(window).on('load scroll resize orientationchange', function () {
init();
navbarState();
});
One can observe that repeatedly pressing the first anchor link causes a bouncing effect. How can I prevent that?
My goal is to have the navigation scroll to the proper anchors, no matter whether the user is at the landing page or not.
Why not using navbar-fixed-bottom as well?
See here: https://jsfiddle.net/y7soL4ej/
I added the mentioned class as default to nav. And modified minor things:
CSS
html, body, div#landing {
height: 100%
}
section, [id*=section] {
padding-top: 52px;
}
JS
function init() {
nh = 50 + 2; // navbar height + 2x border width (top + bottom)
sh = $(window).height();
ih = sh-nh;
//$("#landing").css('height', ih+'px');
}
function navbarState() {
if ($(window).scrollTop() > ih) {
$('.navbar').removeClass('navbar-fixed-bottom').addClass('navbar-fixed-top');
} else {
$('.navbar').removeClass('navbar-fixed-top').addClass('navbar-fixed-bottom');
}
}
init();
navbarState();
$(window).on('load scroll resize orientationchange', function () {
init();
navbarState();
});
The jumpy behaviour: When the navbar is at the bottom in your example it is part of the dom flow - it seperates the landing div and the section1 div by its height. As soon as it is clicked the browser jumps to the location, the navbar is then set as fixed at the top - and is no longer part of the flow (the both divs are no longer seperated by it). The section divs are therefore moved accordingly up to the landing div closing the gap. So clicking the same section anchor again will result in an additional jump, because the section was repositioned due to the landing div went from position:static to position:fixed.
That's an additional reason why I recommend to use navbar-fixed-bottom.
Update
new fiddle: https://jsfiddle.net/y7soL4ej/2/
I removed .navbar-fixed-bottom from HTML and JS as the navbar should not jump from bottom to top.
To make it smooth and avoid the earlier mentioned jumpy behaviour, I had to set it to absolute position.
some CSS needed to be added:
div#landing {
padding-bottom: 72px;
margin-bottom: -72px;
}
nav.navbar {
position: absolute;
left: 0; right: 0;
}
nav.navbar.navbar-fixed-top {
position: fixed;
}

overflow div area with many unordered list items

I have a div that contains a ul with a lot of li's. The div's height is smaller than the height the li's cover so I have overflow auto on the css for div.
sample html
<div class="points-area">
<ul class="points-list">
<li class="point selected" id="startPoint">Start</li>
<li class="point" id="endPoint">End</li>
<li class="point" id="N">Nasion</li>
<li class="point" id="S">Stella center</li>
<li class="point" id="P">Porion</li>
<li class="point" id="ar">Artikulare</li>
<li class="point" id="T1">T1</li>
<li class="point" id="Me">Me</li>
<li class="point" id="Gn">Gnathion</li>
<li class="point" id="T2/MT1">T2/MT1</li>
</ul>
</div>
css
.points-list{
list-style: none;
padding: 0;
margin-top: 0;
}
li.point{
border-bottom: 1px solid black;
padding: 0.1em;
}
.points-area{
overflow: auto;
height: 20em;
border: 1px solid black;
}
li.point.selected,
li.point:hover{
background-color: blue;
}
I have some javascript that when something user adds a circle on a kineticjs stage the next li gets selected (toggled selected class).
if (! $("li.point.selected").is(":last-child")){
prevLi = $("li.point.selected");
prevLi.next().toggleClass('selected');
prevLi.toggleClass('selected');
toBeAdded = prevLi.next();
}
so in my javascript code after a circle is added it toggles the 'selected' class name on the next li.
My problem is that because points are more than div's hieght can handle, the scrollbar doesnt move when I move down the li's. So e.g
scroll area reaches as far as li with text value porion. All li's bellow that are not shown cause of scrollbar. I need when changing from Porion Artikulare (toggling selected class) the overflow to scroll down a bit so that the li can appear on the div area. How can this be achieved?
It is very simple. all you need to know is 'you div height', 'li height', scrolltop and scrollto functions in JS / JQ.
calculate the scrollTop using number of li's u need to scroll, and use scrollTo inorder to scroll to particular position on scroll bar!!
if you have your codes in plnkr / JSFiddle etc.. please share it, i can help you with it
I think I got it! This is the updated fiddle
I added this piece of code
var divHeight, liHeight, lisPerScrollPage;
divHeight = $(".points-area").height(); //caluclate divs height
liHeight = $("li.point").outerHeight(true);// calculate li's height with padding margin etc
lisPerScrollPage = parseInt(divHeight / liHeight); //calculate how many li's fits a scroll page
Then I just checked to see if the li i am selecting is inside the scroll area and if its not move the scroll area as much ase needed. If the scroll area is allready lower and it can be shown don't do nothing (in case user manually used the scrollbar)
index = $("li.point").index(toBeAdded) + 1;
if ($(".points-area").scrollTop() < liHeight *(index - lisPerScrollPage))
{
$(".points-area").scrollTop(liHeight *(index - lisPerScrollPage));
}
I think it works as I want to.

How can I display an image as a menu item once the user has scrolled down the page 150px?

I have a horizontal menu that is fixed to the top of the page and built by the following list:
<div id="menu">
<ul id="nav">
<li>Home</li>
<li>blog</li>
<li>more info</li>
<li>contact</li>
</ul>
</div>
Currently there is an empty space to the far left of the home menu link. How could I go about having an image of their logo show up in this location after the user scrolls down the page 150px?
I imagine this is a combo of javascript and CSS which is fine, I just need a roadmap of how to achieve the result. Thanks.
Place an element for the logo in the area you want it to be and provide it styling. Set it to display none at first.
Attach a scroll listener to the window. Check for if the page has scrolled 150px from the top. If it has change the display to block on the element with the logo. It if hasn't change the element to display none if it is visible.
You can do it with jQuery, if you'd like. The idea will be to go ahead and add the image, and then use JavaScript to add a class of hidden to the image (the image will be displayed whenever JavaScript is turned off, then), and then with jQuery, add or remove the class hidden depending on the scroll position.
<div id="menu">
<img src="path/to/logo.png" id="logo">
<ul id="nav">
<li>Home</li>
<li>blog</li>
<li>more info</li>
<li>contact</li>
</ul>
</div>
/* CSS */
.hidden {
display: none;
}
// jQuery
$(function() {
var logo = $('#logo');
logo.addClass('hidden');
$(window).scroll(function() {
if( +$(this).scrollTop > 149 ) {
logo.removeClass('hidden');
} else {
logo.addClass('hidden');
}
});
});
Just as a note, if you would like the image to always be hidden if JavaScript is off, then hard-code class="hidden" into the HTML. When JavaScript is turned on, the code will still work the same. It's just a preference of how you want your page to behave with vs without JavaScript being on.
here is a little example how you can show/hide an element on page scroll with jQuery. hope this helps: http://jsfiddle.net/KWyS2/
<script type="text/javascript">
$(document).ready(function(){
$(window).scroll(function(){
var scrollTop = $(window).scrollTop();
$('.addDistance').html(scrollTop);
if(scrollTop >= 150 ) {
$('.show-hide-me').fadeIn();
} else {
$('.show-hide-me').fadeOut();
}
})
})
</script>
<div class="show-hide-me"></div>
<div class="content"></div>
<p class="addDistance"></p>
<style text="type/css">
.show-hide-me {
display:none;
width:100px;height:100px;
background-color:orange;
position:fixed;
top:0px;
left:0px;
}
.content {
height:10000px;
background-color:fuchsia;
width:10px;
}
p {
position:fixed;
top:0px;right:0px;
border:solid 1px red;
}
</style>

Categories