I have a single HTML page with a fixed position top level navigation menu with links that lead to different sections. Is there a way to change the color of my links when a user reaches the corresponding section (either by clicking the link itself or scrolling down to the section)?
This is what my HTML looks like, basically:
<div id="topNav">
<ul>
<li>Contact</li>
<li>Web Design</li>
<li>Home</li>
</ul>
</div>
<div id="home">
<img src="images/dog.jpg" class="bg" />
</div>
<div id="web_design">
<img class="titleImage" src="images/web_design.jpg" />
</div>
<div id="contact">
<img class="titleImage" src="images/contact.jpg" />
</div>
And this is the CSS:
#topNav {
width: 100%;
height: 60px;
position: fixed;
top: 20px;
}
I'd like to use a class "selected" for my list items and probably apply it to whichever link corresponds to the user's current section, and do something like:
#topNav li.selected a {
color: #cbcacc;
}
Any help is greatly appreciated!
I think you need an item called scrollspy. There are some free stuffs all the web:
This jsFiddle is an lightweight example
Some jQuery scrollspy plugin in jQuery plugin registry
Bootstrap scrollspy javascript plugin
You can also google with the keyword scrollspy for more stuffs.
This is the code from the above fillde:
JS
// Cache selectors
var lastId,
topMenu = $("#top-menu"),
topMenuHeight = topMenu.outerHeight()+15,
// All list items
menuItems = topMenu.find("a"),
// Anchors corresponding to menu items
scrollItems = menuItems.map(function(){
var item = $($(this).attr("href"));
if (item.length) { return item; }
});
// Bind click handler to menu items
// so we can get a fancy scroll animation
menuItems.click(function(e){
var href = $(this).attr("href"),
offsetTop = href === "#" ? 0 : $(href).offset().top-topMenuHeight+1;
$('html, body').stop().animate({
scrollTop: offsetTop
}, 300);
e.preventDefault();
});
// Bind to scroll
$(window).scroll(function(){
// Get container scroll position
var fromTop = $(this).scrollTop()+topMenuHeight;
// Get id of current scroll item
var cur = scrollItems.map(function(){
if ($(this).offset().top < fromTop)
return this;
});
// Get the id of the current element
cur = cur[cur.length-1];
var id = cur && cur.length ? cur[0].id : "";
if (lastId !== id) {
lastId = id;
// Set/remove active class
menuItems
.parent().removeClass("active")
.end().filter("[href=#"+id+"]").parent().addClass("active");
}
});
HTML
<div id="topNav">
<ul>
<li>Contact</li>
<li>Web Design</li>
<li>Home</li>
</ul>
</div>
<div class="spacer"></div>
<div id="home">
<img src="images/dog.jpg" class="bg" />
</div>
<div id="web_design">
<img class="titleImage" src="images/web_design.jpg" />
</div>
<div id="contact">
<img class="titleImage" src="images/contact.jpg" />
</div>
CSS
#topNav {
width: 100%;
height: 60px;
position: fixed;
top: 20px;
}
div.spacer {
height: 80px;
}
#topNav li.selected a {
color: #cbcacc;
}
CSS3 has an interesting selector :target, you can style your links based on the targets , you can do something like this
:target{color:#ff0000;}
Try google for css3 target selector
Related
I am working on a simple portfolio for my friend. He wants it so that when I go to his portfolio section, the navbar simply should be hidden and it should only show up when I hover over it.
I saw a lot of tutorials on w3schools on how they do it but quite wasn't able to do it. Here is my HTML code for my navigation.
Once again, I want it so that the Navigation page should be hidden when I click "portfolio" and that it should only show when I hover over it.
Here is an example of what I mean.
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_navbar_hide_scroll
HTML CODE:
<header id="header" class="header-tops">
<div class="container">
<h1>Parth Prajapati</h1>
<!-- <img src="assets/img/logo.png" alt="" class="img-fluid"> -->
<h2>I'm a 4th year <span>Architectural Student</span> based in Toronto</h2>
<nav class="nav-menu d-none d-lg-block">
<ul>
<li class="active">Home</li>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>
</nav><!-- .nav-menu -->
<div class="social-links">
<!-- <i class="icofont-instagram"></i> -->
<i class="icofont-linkedin"></i>
</div>
</div>
</header><!-- End Header -->
JS Code:
var prevScrollpos = window.pageYOffset;
window.onscroll = function () {
var currentScrollPos = window.pageYOffset;
if (prevScrollpos > currentScrollPos) {
document.getElementsByClassName('container').style.top = "0";
} else {
document.getElementsByClassName('container').style.top = "-50px";
}
prevScrollpos = currentScrollPos;
}
what css properties did you add?
There are few things you can do to improve your code.
1)see if your navbar position needs fixed or sticky property
and 2)use id to your navbar, classes have lower specificity than id.
the example you provided has this css.
#navbar {
background-color: #333;
position: fixed;
top: 0;
width: 100%;
display: block;
transition: top 0.3s;
}
your js code just applying the style to the whole container class, is that what you really want?
I am new to jQuery and Waypoint and have been googling everywhere to find an answer to this problem unsuccessfully and I am stumped.
While scrolling down, the sticky menu appears at a certain point overlapping the first section of the web page and starts flickering until it reaches the second section.
The Chrome Developer Tools shows that my jQuery script toggles back and forth between adding "sticky" and removing "sticky" from the .
This only happens on Chrome. I do not have this issue on Safari or Firefox.
I am using jQuery v3.4.1 and Waypoint v.4.0.1.
You will find below code snippets.
Here is the link to the Website to see the behaviour.
How can I fix this issue?
Any help would be greatly appreciated!
I tried adding CSS styling to my sticky classes to no avail:
-webkit-transition: all 0.5s ease-in 0s;
transition: all 0.5s ease-in 0s;
-webkit-transform: translateZ(0);
transform: translateZ(0);
z-index: 9999;
I tried increasing and decreasing the offset.
I tried moving around the class ".js--section-product" and id=id="product" inside the section-product section but it made things worse.
Here is my Waypoint and jQuery:
$(document).ready(function () {
/* For the sticky navigation */
$('.js--section-product').waypoint(function(direction) {
if (direction == "down") {
$('header').addClass('sticky');
} else {
$('header').removeClass('sticky');
}
}, {
offset: '20%'
});
/* Navigation scroll */
$(function() {
// Select all links with hashes
$('a[href*="#"]')
// Remove links that don't actually link to anything
.not('[href="#"]')
.not('[href="#0"]')
.click(function(event) {
let nav = $('.js--navigation__nav');
let icon = $('.js--nav-icon ion-icon');
if (icon.attr("name") === "close") { //if on mobile view, menu is open and must be closed
nav.slideToggle(200); //when a link is clicked on mobile close menu
icon.attr("name", "menu") //then replace with "close" icon
}
// On-page links
if (
location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '')
&&
location.hostname == this.hostname
) {
// Figure out element to scroll to
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
if (target.length) {
// Only prevent default if animation is actually gonna happen
event.preventDefault();
console.log('Link scroll down=', target.offset().top)
$('html, body').animate({
scrollTop: target.offset().top //{scrollTop: targetOffset - 100} ?
}, 1000, function() {
// Callback after animation
// Must change focus!
var $target = $(target); //refers to the jQuery representation of the dom object
$target.focus();
if ($target.is(":focus")) { // Checking if the target was focused
return false;
} else {
$target.attr('tabindex','-1'); // Adding tabindex for elements not focusable
$target.focus(); // Set focus again
};
});
}
}
});
});
});
Here is part of my index.html file:
<body>
<header class="header">
<img src="img/logo_MlleLaSalxpe_NoirEtBlanc.svg" alt="logo" class="header__logo">
<div class="navigation">
<a class="mobile-nav-icon js--nav-icon"><ion-icon name="menu"></ion-icon></a>
<nav class="navigation__nav js--navigation__nav">
<ul class="navigation__list">
<li class="navigation__item">Product</li>
<li class="navigation__item">Our vision</li>
<li class="navigation__item">The Shades</li>
<li class="navigation__item">La Première Dame</li>
<!-- <li class="navigation__item">Find a store</li> -->
<li class="navigation__item">Contact Us</li>
</ul>
</nav>
</div>
</header>
<main>
<section class="section-banner">
<div class="section-banner__box">
<h1 class="heading-primary u-center-text">
Stand in the Sun
</h1>
</div>
</section>
<section class="section-product js--section-product" id="product">
<div class="heading__text-box u-center-text u-margin-top-big">
<h2 class="heading-secondary u-margin-bottom-big ">
<span class="heading-secondary--main">Product</span>
<span class="heading-secondary--sub">Psaume 4</span>
<span class="heading-secondary--sub2 ">The All-In-One Skincare Foundation</span>
</h2>
</div>
</section>
I fixed the problem by completely redesigning my navigation and header. Also replaced the gradient banner with a background picture as cover.
1)
`
<nav>
<div class="row">
<img src="img/logoMlleLaSalxpe_name-white.png" alt="logo" class="header__logo-white">
<img src="img/logo_MlleLaSalxpe_name-black.png" alt="logo" class="header__logo-black">
<ul class="navigation js--navigation">
<li>Product</li>
<li>Our vision</li>
<li>The Shades</li>
<li>La Première Dame</li>
<li >Contact Us</li>
</ul>
<a class="mobile-nav-icon js--nav-icon"><ion-icon name="menu"></ion-icon></a>
</div>
</nav>
<div class="slogan-text__box">
<h1 class="heading-primary u-center-text">Stand in the Sun</h1>
<div class="u-center-content">
<a class= "button-full" href="#signup">Sign Up</a>
</div>
</div>
</header>`
2)
.header {
height: 100vh;
background-image: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)), url(../img/AdobeStock_sunrise2.jpg);
background-size: cover;
background-position: center;
background-attachment: fixed;
}
I have an html menu. The markdown must remain as shown. Need to expand content on ""-link hover
<div class="container">
<div class="first-div-in row-menu" data-menu-block="first-div-in">Title</div>
..some other buttons..
</div>
<div id="first-div-in" class="menu-in">
<div class="container" style="display:none;">
<div class="col-xs-10">
... here is content ...
</div>
</div>
</div>
The problem is in realization. The idea is that when the user hovers on "div"-link, it expands the container with content. When the user changes the mouse position to this container, the container must be still visible.
The JS:
var hover_menu = function() {
var parent = $(this);
var menu_block = $( parent ).data('menu-block');
$('#' + menu_block).slideToggle('slow');
}
$('.row-menu').on( 'hover', hover_menu );
My JS code must expand container on "div"-link hover. The container must be visible on changing the cursor position to expanded container. How can I realize this kind of behavior?
Try something like this. On mouseover, if the current item is already visible then do nothing. Otherwise, hide any other open sections and show the new one.
var hover_menu = function(){
var $parent = $(this);
var $menu_block = $('#' + $parent.data('menu-block'));
if ($menu_block.not(':visible')) {
$('.menu-in:visible').not($menu_block).slideOut('slow');
$menu_block.slideIn('slow');
}
}
$('.row-menu').on( 'mouseover', hover_menu );
Actually, you could do this menu with simple css, using max-height and overflow(hidden).
<div class="menu-container">
<div class="visible-content">
My menu
</div>
<div class="invisible-content">
<div class="content-of-invisible-div">
<ul>
<li>My first item</li>
<li>My second item</li>
<li>My third item</li>
</ul>
</div>
</div>
.menu-container:hover .invisible-content {
max-height: 100px
}
.invisible-content{
max-height: 0px;
overflow: hidden;
}
.visible-content{
background-color: red;
padding: 10px;
}
.content-of-invisible-div {
background-color: blue;
}
Here's the fiddle
ttps://jsfiddle.net/7w1rts24/
I have an issue I was hoping someone could kindly help me with. I'm currently building a webiste, and tried to use a jquery plugin for the first time to create a sticky navigation bar (http://stanhub.com/scroll-to-top-then-fixed-navigation-effect-with-jquery-and-css-free-download/).
When I assign an #ID to the nav tag, and change the CSS rule accordingly to apply just on this specific nav, the plugin stops working. The problem is that I would like to have a few navs on my page and I don't see another option.
Any suggestions?
Thanks!
And here is a link to the full code:
http://codepen.io/anon/pen/gbQBOo
HTML:
<section id="screen1">
<p>Scroll down</p>
<nav id="main-nav">
<ul>
<li>Home</li>
<li>About</li>
<li>Services</li>
<li>Team</li>
<li>Contact</li>
</ul>
</nav>
</section>
<section id="screen2"></section>
<section id="screen3"></section>
CSS:
/* Navigation Settings */
#main-nav {
position: absolute;
bottom: 0;
width: 100%;
height: 70px;
background: #fff;
}
JS:
$(document).ready(function(){
$(window).bind('scroll', function() {
var navHeight = $( window ).height() - 70;
if ($(window).scrollTop() > navHeight) {
$('#main-nav').addClass('fixed');
}
else {
$('#main-nav').removeClass('fixed');
}
});
});
In CSS, #main-nav is more precise than .fixed, so it takes precedence.
You could:
1) change .fixed into #main-nav.fixed
2) set the position from .fixed to fixed!important
3) not use an id but a specific class for your nav, and make sure .fixed is defined after that new class
Working on creating a small jquery plugin for a client's website that is a simple breadcrumb system using anchor tags, that changes the last element in the breadcrumb list based on which anchor tag is currently visible. Further, I'm using HTML5 data- elements to store each page name, so that I can add that as the second element in the breadcrumb list as well.
For visibility, I'm using this plugin: https://github.com/zeusdeux/isInViewport
This is the fiddle I'm working with: http://jsfiddle.net/7F59C/4/
Here is the HTML:
<div class="header">head element
<div id="breadcrumbs" data-page="About">
<ul>
<li>Home</li>
<li class="currentpage"></li>
<li class="active"></li>
</ul>
</div>
</div>
<div class="spacer"></div>
<div class="gridContainer">
<div class="space">
take up some space<br />
<a class="crumb" id="About" href="#">About Us</a>
</div>
<div class="space">
take up more space<br />
<a class="crumb" id="Other_heading" href="#">Other heading</a>
</div>
</div>
The JS:
$(document).ready(function() {
$jbread();
});
$.fn.jbread = function () {
//set bc as breadcrumbs list
var bc = $("#breadcrumbs");
//BUILD CURRENT PAGE BREADCRUMB ITEM
//set currentpage to current page's data-page value
var currentpage = bc.data("page");
//set currentpage_link to current page's url
var currentpage_link = window.location.pathname;
//add currentpage as next li in breadcrumbs list
$(".currentpage").html('' + currentpage + '');
//UPDATE ACTIVE ITEM IN BREADCRUMB LIST
$.fn.updateCrumbs = function () {
var currentactive = $(e.target);
$(".active").html(currentactive);
}
//WORK WITH ISINVIEWPORT PLUGIN
$('div.gridContainer > a.crumb').updateCrumbs();
$('div.gridContainer > a.crumb:in-viewport(10)').updateCrumbs();
$(window).scroll(function() {
$('div.gridContainer > a.crumb').updateCrumbs();
$('div.gridContainer > a.crumb:in-viewport(250)').updateCrumbs();
});
//STYLE BREADCRUMB LIST
};
And, for good measure, CSS:
#breadcrumbs ul {
list-style: none;
float: left;
padding: 2px;
}
#breadcrumbs ul li a {
text-decoration: none;
color: black;
}
.space {
height: 500px;
background-color: red;
}
.header {
position: fixed;
height: 100px;
background-color: #FFF;
width: 100%;
margin-top: 0;
}
.spacer {
min-height: 100px;
}
INTENDED FUNCTIONALITY:
As the user is scrolling down the page, when one of the anchor tags with the class "crumb" comes intoViewport (which I have set as 250-350 pixels down the page), I would like the list item with the class of "active" to be updated with the anchor tag that just triggered the function. I'm not sure if I'm using $(e.target) correctly, or if it will even reference the correct thing.
I'm hoping to get this function working, and then I need to create an actual demo page to flesh out styling the list after it is populated. That's for another question.
Any thoughts, comments, or criticisms are welcome as I am very new to jQuery and am questioning my logic on this one.
Looks like you want something like
$.fn.updateCrumbs = function () {
var currentactive = this.text();
$(".active").text(currentactive);
}