On my website I have set up a "click-to-scroll" menu with the logic of:
1. when menu link is clicked, scroll to corresponding anchor and add active class to $(this)
2. onscroll, toggle active class according to the current anchor's location
This all works fine, but there is a small bug in that when you click a link, the page flickers slightly and so do the active menu links. You can see and test it live at http://jcwd98.appspot.com/ (warning that it's in its early development stages, no mobile and probably looks pretty crappy right now).
I'm not sure what causes the page to flicker, but I do know that the reason the menu links flicker is because my code is telling it to add an active class to it when it scrolls over its corresponding section. Since the document has to first scroll over a section to get to the desired section, it adds an active class to other links before it arrives.
I don't want either of these scenarios.
jsFiddle
Code:
var section_padding = 45;
$("#menu ul li a").on("click", function(event) {
event.preventDefault;
$("#menu ul li a.active").removeClass("active");
$(this).addClass("active");
var target = this.hash;
var menu = target;
var cache_target = $(target);
var buffer = (cache_target.offset().top - section_padding);
$("html, body").stop().animate({
"scrollTop": buffer
}, 400, "swing");
});
function scroll(event) {
var scroll_pos = $(document).scrollTop();
$("#menu ul li a").each(function() {
var cur_link = $(this);
var ref_el = $(cur_link.attr("href"));
if( ref_el.position().top <= scroll_pos && ref_el.position().top + ref_el.height() + (section_padding * 2) > scroll_pos ) {
$("#menu ul li a").removeClass("active");
cur_link.addClass("active");
} else {
cur_link.removeClass("active");
}
});
}
$(document).on("scroll", scroll);
* {
margin: 0;
padding: 0;
}
#menu {
display: block;
height: 50px;
width: 100%;
position: fixed;
z-index: 100;
background: rgba(255, 255, 255, .8);
}
#menu ul {
display: block;
width: 100%;
height: 100%;
list-style: none;
}
#menu ul li {
display: block;
box-sizing: border-box;
height: 100%;
width: calc(100% / 5);
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
float: left;
text-align: center;
line-height: 50px;
}
#menu ul li a {
display: block;
text-decoration: none;
font-family: arial;
}
#menu ul li a:hover,
#menu ul li a.active {
background: #f0f0f0;
}
#sections {
display: block;
position: relative;
top: 50px;
}
section {
display: block;
height: 500px;
width: 100%;
background: #67D182;
padding: 45px 50px;
box-sizing: border-box;
}
#sections section:nth-child(even) {
background: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<nav id="menu">
<ul>
<li>Top</li>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
<li>Blog</li>
</ul>
</nav>
<div id="sections">
<section id="top">
<h2>#top</h2>
</section>
<section id="about">
<h2>#about</h2>
</section>
<section id="portfolio">
<h2>#portfolio</h2>
</section>
<section id="contact">
<h2>#contact</h2>
</section>
<section id="blog">
<h2>#blog</h2>
</section>
</div>
Any help would be greatly appreciated. :)
This happen because preventDefault is a function, then you only need to change:
event.preventDefault;
To:
event.preventDefault();
And this work fine.
FIDDLE: https://jsfiddle.net/lmgonzalves/ve5qr3bL/2/
EDIT:
You need to unbind the scroll event, and then bind it again when the animation be completed.
$("#menu ul li a").on("click", function(event) {
event.preventDefault();
$(document).off("scroll"); // here unbind
// code
$("html, body").stop().animate({
"scrollTop": buffer
}, 400, "swing", function() {
$(document).on("scroll", scroll); // here bind again
});
});
FIDDLE: https://jsfiddle.net/lmgonzalves/ve5qr3bL/3/
Related
I'm looking to make a left to right scrolling navigation menu that's items are highlighted as you scroll down the page. This navigation will look similarly to the following in page navigation on Chase.com (https://www.chase.com/digital/customer-service?jp_cmp=rb/tap/off/na/prt). Please note that I want this navigation to stay scrollable on all devices.
Below is what I have so far. I'm currently having the issue with getting the nav options to scroll into focus as they are highlighted.
window.onscroll = function() {
myFunction()
};
var navbar = document.getElementById("inpagenav");
var sticky = inpagenav.offsetTop;
function myFunction() {
if (window.pageYOffset >= sticky) {
inpagenav.classList.add("sticky")
} else {
inpagenav.classList.remove("sticky");
}
}
// cache the navigation links
var $navigationLinks = $('#inpagenav > ul > li > a');
// cache (in reversed order) the sections
var $sections = $($(".pagenavsection").get().reverse());
// map each section id to their corresponding navigation link
var sectionIdTonavigationLink = {};
$sections.each(function() {
var id = $(this).attr('id');
sectionIdTonavigationLink[id] = $('#inpagenav > ul > li > a[href=\\#' + id + ']');
});
// throttle function, enforces a minimum time interval
function throttle(fn, interval) {
var lastCall, timeoutId;
return function() {
var now = new Date().getTime();
if (lastCall && now < (lastCall + interval)) {
// if we are inside the interval we wait
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
lastCall = now;
fn.call();
}, interval - (now - lastCall));
} else {
// otherwise, we directly call the function
lastCall = now;
fn.call();
}
};
}
function highlightNavigation() {
// get the current vertical position of the scroll bar
var myPadding = $('#inpagenav').height();
var scrollPosition = $(window).scrollTop();
// iterate the sections
$sections.each(function() {
var currentSection = $(this);
// get the position of the section
var sectionTop = currentSection.offset().top;
// if the user has scrolled over the top of the section
if (scrollPosition + myPadding >= sectionTop) {
// get the section id
var id = currentSection.attr('id');
// get the corresponding navigation link
var $navigationLink = sectionIdTonavigationLink[id];
// if the link is not active
if (!$navigationLink.hasClass('active')) {
// remove .active class from all the links
$navigationLinks.removeClass('active');
// add .active class to the current link
$navigationLink.addClass('active');
}
// we have found our section, so we return false to exit the each loop
return false;
}
});
}
$(window).scroll(throttle(highlightNavigation, 100));
// if you don't want to throttle the function use this instead:
// $(window).scroll( highlightNavigation );
.mainimage {
text-align: center;
height: 300px;
background: gray
}
nav {
background: white;
}
.sticky {
position: fixed;
top: 0;
width: 100%;
}
nav ul {
list-style: none;
padding: 0rem;
overflow: auto;
white-space: nowrap;
margin: 0rem;
overflow-x: scroll;
}
nav ul::-webkit-scrollbar-thumb {
background: #000;
}
nav ul li {
padding-top: 1rem;
vertical-align: center;
display: inline-block;
}
nav ul li a {
text-decoration: none;
color: dodgerblue;
display: inline-block;
margin: 0rem 2rem;
padding-bottom: 1rem;
border-bottom: 3px solid transparent;
}
nav ul li a:hover {
color: #0054a4;
border-bottom: 3px solid #0054a4;
}
nav ul li .active {
color: #308ce3;
font-weight: bold;
border-bottom: 3px solid #308ce3;
}
#section1 {
text-align: center;
height: 500px;
padding: 4rem 0rem;
background: orange;
}
#section2 {
text-align: center;
height: 200px;
padding: 4rem 0rem;
background: green;
}
#section3 {
text-align: center;
height: 300px;
padding: 4rem 0rem;
background: blue;
}
#section4 {
text-align: center;
height: 500px;
padding: 4rem 0rem;
background: red;
}
#section5 {
text-align: center;
height: 500px;
padding: 4rem 0rem;
background: pink;
}
#section6 {
text-align: center;
height: 500px;
padding: 7rem 0rem;
background: purple;
}
#section7 {
text-align: center;
height: 500px;
padding: 7rem 0rem;
background: purple;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="menu.css">
<body>
<div id="contentwrapper">
<div class="mainimage">
<h1>The whole world</h1>
</div>
<nav id="inpagenav">
<ul>
<li>Section 1</li>
<li>Section 2</li>
<li>Section 3</li>
<li>Section 4</li>
<li>Section 5</li>
<li>Section 6</li>
</ul>
</nav>
<section id="section1" class="pagenavsection">
I'm section 1
</section>
<section id="section2" class="pagenavsection">
I'm section 2
</section>
<section id="section3" class="pagenavsection">
I'm section 3
</section>
<section id="section4" class="pagenavsection">
I'm section 4
</section>
<section id="section5" class="pagenavsection">
I'm section 5
</section>
<section id="section6" class="pagenavsection">
I'm section 6
</section>
<section id="section7">lo</section>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="ScrollMenu.js"></script>
</body>
</html>
You might just need to call $navigationLink.scrollIntoView() when you toggle the active class.
Per this answer, you may need to pass special options to scrollIntoView because the items are laid out horizontally.
$navigationLink.scrollIntoView({ inline: 'end' })
// end is my guess; allowable values are: start, center, end, or nearest (the default)
I have a page that has a fixed menu and content box(div).
When click the menu, content box scroll to specific div.
So far so good.
This is the sample here.
https://jsfiddle.net/ezrinn/8cdjsmb9/11/
The problem is when I wrap this whole div and, make them as show/hide toggle button, the scroll is not working.
This is the sample that not working.
https://jsfiddle.net/ezrinn/8cdjsmb9/10/
Also here is the snippet
$('.btn').click(function() {
$(".wrap").toggleClass('on');
});
var div_parent_class_name;
var divs_class;
var id_offset_map = {};
$(document).ready(function() {
div_parent_class_name = "wrap_scroll";
divs_class = "page-section";
var scroll_divs = $("." + div_parent_class_name).children();
id_offset_map.first = 0;
scroll_divs.each(function(index) {
id_offset_map["#" + scroll_divs[index].id] = scroll_divs[index].offsetTop
});
$('a').bind('click', function(e) {
e.preventDefault();
var target = $(this).attr("href")
$('.wrap_scroll').stop().animate({
scrollTop: id_offset_map[target]
}, 600, function() {
/* location.hash = target-20; */ //attach the hash (#jumptarget) to the pageurl
});
return false;
});
});
$(".wrap_scroll").scroll(function() {
var scrollPos = $(".wrap_scroll").scrollTop();
$("." + divs_class).each(function(i) {
var divs = $("." + divs_class);
divs.each(function(idx) {
if (scrollPos >= id_offset_map["#" + this.id]) {
$('.menu>ul>li a.active').removeClass('active');
$('.menu>ul>li a').eq(idx).addClass('active');
}
});
});
}).scroll();
body,
html {
margin: 0;
padding: 0;
height: 3000px;
}
.wrap { display:none;}
.wrap.on { display:block;}
.menu {
width: 100px;
position: fixed;
top: 40px;
left: 10px;
}
.menu a.active {
background: red
}
.wrap_scroll {
position: absolute;
top: 20px;
left: 150px;
width: 500px;
height: 500px;
overflow-y: scroll
}
#home {
background-color: #286090;
height: 200px;
}
#portfolio {
background: gray;
height: 600px;
}
#about {
background-color: blue;
height: 800px;
}
#contact {
background: yellow;
height: 1000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="btn">show/hide</button>
<div class="wrap">
<div class="menu">
<ul>
<li><a class="active" href="#home">Home</a> </li>
<li>Portfolio </li>
<li>About </li>
<li>Contact </li>
</ul>a
</div>
<div class="wrap_scroll">
<div class="page-section" id="home">hh</div>
<div class="page-section" id="portfolio">pp</div>
<div class="page-section" id="about">aa</div>
<div class="page-section" id="contact">cc</div>
</div>
</div>
What Do I need to fix the code? please help.
When you calculate your offset, the div is hidden with display: none. This results in the offsets being set/calculated to zero.
Here's a quick fix I threw together: https://jsfiddle.net/hrb58zae/
Basically, moved the logic to determine offset after clicking show/hide.
var setOffset = null;
...
if (!setOffset) {
var scroll_divs = $("." + div_parent_class_name).children();
id_offset_map.first = 0;
scroll_divs.each(function(index) {
id_offset_map["#" + scroll_divs[index].id] = scroll_divs[index].offsetTop
});
setOffset = true;
}
In your CSS, instead of using display: none and display: block, try using visible instead:
.wrap { visibility:hidden;}
.wrap.on { visibility:visible;}
This will hide the element without affecting the layout.
Updated fiddle: https://jsfiddle.net/a5u683es/
The problem was you are trying to update id_offset_map when content was hidden. When you use 'display:none' prop you won't get dimensions for that element and so its not working.
I updated the logic please check the fiddle https://jsfiddle.net/qfrsmnh5/
var id_offset_map = {};
var div_parent_class_name = "wrap_scroll";
var divs_class = "page-section";
var scroll_divs = $("." + div_parent_class_name).children();
function updateOffsets(){
id_offset_map.first = 0;
scroll_divs.each(function(index) {
id_offset_map["#" + scroll_divs[index].id] = scroll_divs[index].offsetTop
});
}
$(document).ready(function() {
$('.btn').click(function() {
$(".wrap").toggleClass('on');
if($(".wrap").hasClass("on")){
updateOffsets();
}
});
$('a').on('click', function(e) {
e.preventDefault();
var target = $(this).attr("href")
$('.wrap_scroll').stop().animate({
scrollTop: id_offset_map[target]
}, 600, function() {
/* location.hash = target-20; */ //attach the hash (#jumptarget) to the pageurl
});
return false;
});
});
$(".wrap_scroll").on('scroll',function() {
var scrollPos = $(".wrap_scroll").scrollTop();
$("." + divs_class).each(function(i) {
var divs = $("." + divs_class);
divs.each(function(idx) {
if (scrollPos >= id_offset_map["#" + this.id]) {
$('.menu>ul>li a.active').removeClass('active');
$('.menu>ul>li a').eq(idx).addClass('active');
}
});
});
}).scroll();
body,
html {
margin: 0;
padding: 0;
height: 3000px;
}
.wrap { display:none;}
.wrap.on { display:block;}
.menu {
width: 100px;
position: fixed;
top: 40px;
left: 10px;
}
.menu a.active {
background: red;
}
.wrap_scroll {
position: absolute;
top: 20px;
left: 150px;
width: 500px;
height: 500px;
overflow-y: scroll;
}
#home {
background-color: #286090;
height: 200px;
}
#portfolio {
background: gray;
height: 600px;
}
#about {
background-color: blue;
height: 800px;
}
#contact {
background: yellow;
height: 1000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="btn">show/hide</button>
<div class="wrap">
<div class="menu">
<ul>
<li><a class="active" href="#home">Home</a></li>
<li>Portfolio </li>
<li>About </li>
<li>Contact </li>
</ul>
</div>
<div class="wrap_scroll">
<div class="page-section" id="home">hh</div>
<div class="page-section" id="portfolio">pp</div>
<div class="page-section" id="about">aa</div>
<div class="page-section" id="contact">cc</div>
</div>
</div>
works perfectly, it's just that when you use display: none you can not do the offsetTop calculations because in fact the element is not rendered, I'm not sure if all the values give 0 or undefined, I guess undefined, a solution is always calculate Positions using a function:
var div_parent_class_name;
var divs_class;
var id_offset_map = {};
function calcTops(){
div_parent_class_name = "wrap_scroll";
divs_class = "page-section";
var scroll_divs = $("." + div_parent_class_name).children();
id_offset_map.first = 0;
scroll_divs.each(function(index) {
id_offset_map["#" + scroll_divs[index].id] = scroll_divs[index].offsetTop
});
}
https://jsfiddle.net/561oe7rb/1/
is not the optimal way, but it is to give you an idea. Sorry for my English.
Just Checkout This Working page I have designed
jQuery(document).on('scroll', function(){
onScroll();
});
jQuery(document).ready(function($) {
div_slider();
showhide();
});
/*show hide content*/
function showhide(){
$('.toggle-wrapper button').on('click', function(){
$('.wrapper').toggle();
// div_slider();
})
}
/*scrolling page on header elements click*/
function div_slider(){
$('ul li a').on('click', function(e){
e.preventDefault();
$('ul li a').removeClass('active');
$(this).addClass('active');
var attrval = $(this.getAttribute('href'));
$('html,body').stop().animate({
scrollTop: attrval.offset().top
}, 1000)
});
}
/*adding active class on header elements on page scroll*/
function onScroll(event){
var scrollPosition = $(document).scrollTop();
$('ul li a').each(function () {
var scroll_link = $(this);
var ref_scroll_Link = $(scroll_link.attr("href"));
if (ref_scroll_Link.position().top <= scrollPosition && ref_scroll_Link.position().top + ref_scroll_Link.height() > scrollPosition) {
$('ul li a').removeClass("active");
scroll_link.addClass("active");
}
else{
scroll_link.removeClass("active");
}
});
}
body {
margin: 0;
}
.toggle-wrapper {
position: fixed;
top: 0;
left: 0;
right: 0;
background-color: #ccd2cc;
text-align: center;
}
.toggle-wrapper button {
background-color: #ED4C67;
color: #ffffff;
padding: 10px 20px;
border: 0;
cursor: pointer;
border-radius: 5px;
}
.toggle-wrapper button:active{
background-color: #B53471;
}
header {
background-color: #6C5CE7;
position: fixed;
top: 36px;
z-index: 99;
left: 0;
right: 0;
}
header ul {
list-style: none;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0;
margin: 0;
}
ul li {
flex: 1 100%;
display: flex;
justify-content: center;
}
.wrapper {
margin-top: 36px;
}
header a {
color: #ffffff;
padding: 15px;
display: block;
text-decoration: navajowhite;
text-transform: uppercase;
width: 100%;
text-align: center;
}
header a.active {
color: #000000;
background-color: #ffffff;
}
section {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
section.section1 {
background-color: #FFEAA7;
}
section.section2{
background-color:#FAB1A0;
}
section.section3{
background-color:#7F8C8D;
}
section.section4{
background-color:#4CD137;
}
section.section5{
background-color:#A3CB38;
}
section.section6{
background-color:#70A1FF;
}
section.section7{
background-color:#079992;
}
<div class="toggle-wrapper">
<button>Toggle</button>
</div>
<div class="wrapper" style="display: none;">
<header>
<ul>
<li><a class="active" href="#one">one</a></li>
<li>two</li>
<li>three</li>
<li>four</li>
<li>five</li>
<li>six</li>
<li>seven</li>
</ul>
</header>
<section class="section1" id="one">SECTION ONE</section>
<section class="section2" id="two">SECTION TWO</section>
<section class="section3" id="three">SECTION THREE</section>
<section class="section4" id="four">SECTION FOUR</section>
<section class="section5" id="five">SECTION FIVE</section>
<section class="section6" id="six">SECTION SIX</section>
<section class="section7" id="seven">SECTION SEVEN</section>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I'm trying to accomplish a simple effect of sticking the menu to top of the browser window when scrolling passes a certain point, but something went wrong and the menu wont get fixed to the top. From the libraries I'm using jQuery and animate it.
My code is as follows:
HTML:
<nav class="animatedParent">
<ul class="animated bounceInUp delay-750">
<li class="animated">O meni</li>
<li class="animated">Katalog</li>
<li class="animated">Razno</li>
</ul>
</nav>
CSS:
.fixedNav {
display: block;
position: fixed;
top: 0;
width: 100%;
background: rgba( 0, 0, 0, .8);
height: 100px;
}
nav {
width: 400px;
margin: 20px auto;
}
nav ul {
list-style: none;
}
nav ul li {
float: left;
overflow: auto;
width: 130px;
}
nav ul li a {
font-size: 35px;
font-family: 'Indie Flower', cursive;
color: #fff;
cursor: pointer;
transition: 500ms linear all;
}
nav ul li a:hover {
color: #123456;
transition: 500ms linear all;
}
JS (jQuery):
$(document).ready(function(){
$("nav ul li").mouseenter(function() {
$(this).addClass("wiggle");
});
$("nav ul li").mouseleave(function() {
$(this).removeClass("wiggle");
});
var nav = $("nav").offsetTop();
if($(window).scrollTop() > nav) {
$("nav").addClass("fixedNav");
console.log('Hello!');
} else {
$("nav").removeClass("fixedNav");
}
});
So first off, you only use the code once, which is when the document is loaded. You're going to want to check everytime you scroll the document as the code should obivously be triggered once you scroll a certain amount.
$(document).scroll(function(){
var nav = $("nav").height();
if($(window).scrollTop() > nav) {
$("nav").addClass("fixedNav");
} else {
$("nav").removeClass("fixedNav");
}
});
body {
background: black;
height:700px;
}
.fixedNav {
display: block;
position: fixed;
top: 0;
width: 100%;
background: rgba( 0, 0, 0, .8);
height: 100px;
}
nav {
display: block;
height: 100px;
width: 100%;
margin: 20px auto;
}
nav ul {
list-style: none;
}
nav ul li {
float: left;
overflow: auto;
width: 130px;
}
nav ul li a {
font-size: 35px;
font-family: 'Indie Flower', cursive;
color: #fff;
cursor: pointer;
transition: 500ms linear all;
}
nav ul li a:hover {
color: #123456;
transition: 500ms linear all;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="animatedParent nav">
<ul class="animated bounceInUp delay-750">
<li class="animated">O meni</li>
<li class="animated">Katalog</li>
<li class="animated">Razno</li>
</ul>
</nav>
You need to use the event scroll and check the offset there.
When the user is scrolling, toggleClass will add/remove the class based on the condition $window.scrollTop() > navOffset which will return true or false
var $window = $(window);
var $nav = $('nav');
var navOffset = $nav.offsetTop();
$window.on('scroll', function() {
$nav.toggleClass('fixedNav', $window.scrollTop() > navOffset);
});
add an scroll event to check your scroll position
for example:
$(document).scroll(()=>{...});
like here
This is a very plain demo, it only demonstrate wha i meant
You can use a library like scrollMonitor to accomplish your task as scroll monitoring have its own caveats.
You can let scrollMonitor to lock position of your menu when it leaves viewport, something like this:
var $menu = document.querySelector('nav'); // It is better to use CSS class name instead
var watcher = scrollMonitor.create($menu);
watcher.lock();
watcher.exitViewport(function() {
$menu.classList.add('fixedNav');
});
watcher.enterViewport(function() {
$menu.classList.remove('fixedNav');
});
Please refer this example as it closely matches your task.
You don't fire the check for the current scroll on scroll event. That's an event you're looking for.
Also you could check the scrollTop on the document (it's more error proof in jQuery), not on the window as it doesn't always work.
$(document).ready(function(){
$("nav ul li").mouseenter(function() {
$(this).addClass("wiggle");
});
$("nav ul li").mouseleave(function() {
$(this).removeClass("wiggle");
});
$(document).on('scroll', function() {
var nav = $("nav").offsetTop();
if($(document).scrollTop() > nav) {
$("nav").addClass("fixedNav");
console.log('Hello!');
} else {
$("nav").removeClass("fixedNav");
}
})
});
That is what you are looking for:
$(document).ready(function(){
$("nav ul li").mouseenter(function() {
$(this).addClass("wiggle");
}) ;
$("nav ul li").mouseleave(function() {
$(this).removeClass("wiggle");
}) ;
});
$(document).ready(fixedHeader) ;
$(window).scroll(fixedHeader) ;
function fixedHeader() {
var nav = parseInt($("nav").css("margin-top")) ;
if($(window).scrollTop() > nav) {
$("nav").addClass("fixedNav");
}
else {
$("nav").removeClass("fixedNav");
}
}
body{
height: 1000px;
}
.fixedNav {
display: block;
position: fixed;
top: 0;
width: 100%;
background: rgba( 0, 0, 0, .8);
height: 100px;
}
nav {
width: 400px;
margin: 20px auto;
}
nav ul {
list-style: none;
}
nav ul li {
float: left;
overflow: auto;
width: 130px;
}
nav ul li a {
font-size: 20px;
font-family: 'Indie Flower', cursive;
color: #fff;
cursor: pointer;
transition: 500ms linear all;
}
nav ul li a:hover {
color: #123456;
transition: 500ms linear all;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="animatedParent">
<ul class="animated bounceInUp delay-750">
<li class="animated">O meni</li>
<li class="animated">Katalog</li>
<li class="animated">Razno</li>
</ul>
</nav>
Making an active nav element for a menu isn't too difficult, here is an example. http://jsfiddle.net/6nEB6/38/
<ul>
<li>Home</li>
<li class="active">Deals</li>
<li>Support</li>
<li>Contact</li>
</ul>
CSS:
html {
filter: expression(document.execCommand("BackgroundImageCache", false, true));
}
ul {
background: url(http://shared.web2works.co.uk/tmp/tab-bg-top.png) no-repeat;
height: 51px;
font-family: arial;
font-size: 14px;
}
ul li {
float: left;
height: 51px;
}
ul li a {
display:block;
background: url(http://shared.web2works.co.uk/tmp/nav-seperator.gif) no-repeat top right;
padding: 17px 20px 17px 21px;
text-decoration: none;
color: #263e60;
}
ul li:last-child a{
/*background-image: none;*/
}
ul li:first-child a{
padding-right: 75px;
}
li.active a, li:hover a {
background: #02284c;
color: #FFF;
margin-left: -2px;
padding-left: 23px;
}
What I need is a bit different. In most active states people tend to style their menu buttons so you can use the same style for every button. I need it so the buttons activate a different image for every state.
This is an image of what I'm talking about:
Those buttons have different glow effects which are all different images. When you select a different button the glow should stay active. So if I do it this way I'm not able to use the same style for every button.
The buttons change pages and the hovers work correctly, I'm just having trouble with setting the states for each button to active when it reaches it's destination page. The only state that works is the first button, the home page.
Here is my code(important bits):
<div id="wrapper">
</div>
<div class="menu" id="menunav">
<ul class="menuul">
<li><a id="home-link">Home</a>
</li>
<li><a id="work-link">Work</a>
</li>
<li><a id="about-link">About</a>
</li>
<li><a id="contact-link">Contact</a>
</li>
<li><a id="resources-link">Resources</a>
</li>
</ul>
</div>
CSS:
.menu {
height: 50px;
margin: auto;
width: 650px;
text-align:center;
padding:10px;
}
.menu ul li {
display: inline-block;
margin: 0 10px;
}
.menu ul li a {
display: block;
text-indent: -99999px;
cursor: pointer;
color: #00000;
}
#home-link {
background: transparent url() no-repeat;
width: 90px;
}
#home-link:hover, #home-link.current-item {
background:url() no-repeat;
}
#work-link {
background: transparent url() no-repeat ;
width: 90px;
}
#work-link:hover, #about-link.current-item {
background:url() no-repeat;
}
#about-link {
background:url() no-repeat;
width: 90px;
}
#about-link:hover, #services-link.current-item {
background:url() no-repeat;
}
#contact-link {
background: transparent url() no-repeat;
width: 90px;
}
#contact-link:hover, #work-link.current-item {
background:url() no-repeat;
}
#resources-link {
background:url() no-repeat;
width: 100px;
}
#resources-link:hover, #contact-link.current-item {
background:url() no-repeat;
}
.current-item {
}
JS:
function switchscrollscroll()
{
var scrolloffset = $("#wrapper").scrollLeft();
if(scrolloffset == 0 && scrolloffset <= 1999)
{
$('#menu ul li a').removeClass('current-item');
$('#home-link').addClass("current-item");
}
else if(scrolloffset >= 2000 && scrolloffset <= 3999)
{
$('#menu ul li a').removeClass('current-item');
$('#work-link').addClass("current-item");
}
else if(scrolloffset >= 4000 && scrolloffset <= 5999)
{
$('#menu ul li a').removeClass('current-item');
$('#about-link').addClass("current-item");
}
else if(scrolloffset >= 6000 && scrolloffset <= 7999)
{
$('#menu ul li a').removeClass('current-item');
$('#contact-link').addClass("current-item");
}
else if(scrolloffset >= 8000 && scrolloffset <= 10000)// Contact
{
$('#menu ul li a').removeClass('current-item');
$('#resources-link').addClass("current-item");
}
}
switchscroll();
$("#wrapper").scroll(function(){
switchscrollcroll();
});
});
Images were taken out on purpose. If anyone has done something like this before, I'd appreciate the help.
You can do this by adding a class to the body. For example if you have class work on the body of the work page then your css can look something like
.work #work-link {
background: transparent url(different image) no-repeat ;
}
#work-link {
background: transparent url(default image) no-repeat ;
width: 90px;
}
If you don't want to go around editing every page then you can use jquery to figure out which page you are on and add the appropriate class
This code works great if i want to make toggle effect by clicking on the menu. You can see the result here.
$(document).ready(function () {
var $menu2 = $("#menu-2");
var $links = $('#menu-menu-1 .menu-item a').click(function () {
var submenu = $(this).next();
$subs.not(submenu).hide();
var isVisible = submenu.stop(true, true).is(':visible');
$menu2.stop(true, true);
if (isVisible) {
submenu.hide(500);
$menu2.slideUp(300);
} else {
$menu2.slideUp(300, function () {
$menu2.slideDown(300);
submenu.show(500);
});
}
});
var $subs = $links.next();
});
My problem is .menu-item a, with this the script executes the code for all links of the menu(also for links that don't have submenu links). But in my case i want to execute only for the links that contains submenu links.
If i try t replace .menu-item a with .menu > ul li a doesn't work.
The structure of the html(generated by php) code is like this:
<ul id="menu-menu-1">
<li class="menu">
<a>News</a> //first main menu
<ul class="sub-menu" style="display: none;"> //second grey menu
<li>
<a>Mondo</a>
<a>News Live</a>
<a>Quotidiani Cartacei</a>
</li>
</li>
</ul>
The relevant css:
.menu {
background-color: #F6F6EE;
border-radius: 1px;
height: 30px;
padding: 10px 10px 0 5px;
width: 100%;
}
.menu li a {
color: #716B6B;
display: block;
float: left;
font-size: 14px;
padding: 2px 17px;
text-decoration: none;
width: 100%;
}
#menu-2 {
background-color: #DCDCD5;
border-radius: 1px;
display: none;
height: 33px;
position: relative;
width: 100%;
z-index: -1;
}
How can i fix it?
You need to check, on the top of the function, if the current link has a submenu attached. Check the first two lines of the click callback:
$(document).ready(function () {
var $menu2 = $("#menu-2");
var $links = $('#menu-menu-1 .menu-item a').click(function () {
var submenu = $(this).next(".sub-menu");
var hasSubmenu = submenu.length >= 1;
if(hasSubmenu) {
handleLinkWithSubmenu.call(this, submenu);
} else {
handleLinkWithoutSubmenu.call(this);
}
});
var $subs = $links.next();
function handleLinkWithSubmenu(submenu) {
$subs.not(submenu).hide();
var isVisible = submenu.stop(true, true).is(':visible');
$menu2.stop(true, true);
if (isVisible) {
submenu.hide(500);
$menu2.slideUp(300);
} else {
$menu2.slideUp(300, function () {
$menu2.slideDown(300);
submenu.show(500);
});
}
}
function handleLinkWithoutSubmenu() {
$subs.hide();
}
});
If I understand your question correctly (only execute if selector has children), then replace with this:
var $links = $('#menu-menu-1 .menu-item a').click(function (e) {
if($links.children().length > 0){
e.preventDefault();
var submenu = $(this).next();
$subs.not(submenu).hide();
var isVisible = submenu.stop(true, true).is(':visible');
$menu2.stop(true, true);
if (isVisible) {
submenu.hide(500);
$menu2.slideUp(300);
} else {
$menu2.slideUp(300, function () {
$menu2.slideDown(300);
submenu.show(500);
});
}
}
});
I think something like this will work for what you need, it's a lot cleaner and more compact:
UPDATED:
http://jsfiddle.net/FZHC8/2/
<head>
<script src="jquery-1.10.2.min.js"></script>
<style>
.menu {
background-color: #F6F6EE;
border-radius: 1px;
height: 30px;
padding: 10px 10px 0 5px;
width: 100%;
}
a {
color: #716B6B;
display: block;
float: left;
font-size: 14px;
padding: 2px 17px;
width: 100%;
cursor:pointer;
}
#menu-2 {
background-color: #DCDCD5;
border-radius: 1px;
height: 33px;
position: relative;
width: 100%;
z-index: -1;
}
li{
list-style:none;
}
</style>
</head>
<body>
<ul id="menu-menu-1">
<li class="menu">
<a>News</a>
<ul class="sub-menu">
<li>
<a>Mondo</a>
<a>News Live</a>
<a>Quotidiani Cartacei</a>
</li>
</ul>
<a>News1</a>
<ul class="sub-menu">
<li>
<a>Mondo1</a>
<a>News Live1</a>
<a>Quotidiani Cartacei1</a>
</li>
</ul>
</li>
</ul>
<script>
(function () {
$("li > ul").hide();
$(".menu > a").click(function (e) {
$(this).parent().children(".sub-menu").slideUp(200);
$(this).next(".sub-menu").slideDown(200);
})
})();
</script>
</body>