Hello! I've been learning jQuery for a little while now and am trying to sharpen my skills by creating a responsive website. I added a navigation bar, then a big slider, and below it is the main content of the website. Right now, jQuery (as both the menu background and the main background are black) adds a class to the navigation bar in order to turn it white as soon as you scroll past the slider (which has a height of 550px), so it will be easier to read.
Here's the thing: I want jQuery to add that class depending on the width of the window. If it's less than 600px wide, I want the class to be added automatically. Otherwise, I want jQuery to add it as soon as you scroll past the slider (since I hide it when the window is less than 600px wide). My code is below, and it works just fine if I resize the window and then refresh the page, but I want it to add the class dynamically. Do you think it is possible?
I hope I made myself clear (English is not my first language). Let me know if you need me to explain things better! Thank you in advance. :)
if ($(window).width() > 599 ) {
$(window).scroll(function() {
if ($(window).scrollTop() >= 550) { //if you scroll past the slider
$("#main nav").addClass("white-menu");
} else {
$("#main nav").removeClass("white-menu"); //so it turns black again
}
});
} else {
// add it automatically (the slider is hidden):
$("#main nav").addClass("white-menu");
};
you can use all the code inside scroll event
$(window).scroll(function() {
if ($(this).scrollTop() >= 550 && $(this).width() <= 599) { //if you scroll past the slider
$("#main nav").addClass("white-menu");
} else {
$("#main nav").removeClass("white-menu"); //so it turns black again
}
});
a similar DEMO
about resize you can use
$(window).on('resize',function() {
$("#main nav").removeClass("white-menu");
});
on window resize the code will remove the class till user scroll then the scroll event will fire after user scrolling
or instead of all of that you can just use
$(window).on('scroll resize',function() {
if ($(this).scrollTop() >= 550 && $(this).width() <= 599) { //if you scroll past the slider
$("#main nav").addClass("white-menu");
} else {
$("#main nav").removeClass("white-menu"); //so it turns black again
}
});
DEMO
.scroll allows you to listen to event, if you only listen when the window is the correct size, this listener won't get triggered if that changes, so I changed it around a bit:
$(window).scroll(function() {
if ($(window).width() > 599 ) {
if ($(window).scrollTop() >= 550) { //if you scroll past the slider
$("#main nav").addClass("white-menu");
} else {
$("#main nav").removeClass("white-menu"); //so it turns black again
}
}
});
Like Brian mentioned you should use CSS for this other case:
#media (max-width: 600px) {
#main nav {
// white-menu styles here
}
}
For reference the JS way would be:
$(window).resize(function() {
if ($(window).width() <= 599 ) {
$("#main nav").addClass("white-menu");
}
});
It also might be worth thinking about doing a throttle/debounce on these event listeners. They will get called a lot and if your JS starts to do anything more complicated you will see a performance hit. This example uses the underscore library:
var onScroll = function() {
if ($(window).width() > 599 ) {
if ($(window).scrollTop() >= 550) { //if you scroll past the slider
$("#main nav").addClass("white-menu");
} else {
$("#main nav").removeClass("white-menu"); //so it turns black again
}
}
}
// Don't run until the window has stopped being resized for at least 50ms
var debouncedOnScroll = _.debounce(onScroll, 50);
$(window).scroll(debouncedOnScroll);
See http://underscorejs.org/#debounce
Interesting. I used your code in a fiddle and it worked find. As it's state in another answer, the improve of your code will be using the scroll function to wrap all the actions:
$(window).scroll(function() {
$("#main nav").toggleClass("white-menu", ($(window).scrollTop() >= 550 && $(window).width() <= 599));
});
Related
I'm trying to fix a problem on this template:
https://codepen.io/eksch/pen/xwdOeK
The highlighting effect on the navigation menu only works on a reduced browser height, if I resize the window to full screen (https://codepen.io/eksch/full/xwdOeK) and scroll down to section 7, the link on the navigation menu will not be highlighted. (I'm viewing from a 27 in imac)
In the javascripts, I believe this funciton controls the link highlight:
$(window).scroll(function() {
var scrollDistance = $(window).scrollTop();
// Show/hide menu on scroll
//if (scrollDistance >= 850) {
// $('nav').fadeIn("fast");
//} else {
// $('nav').fadeOut("fast");
//}
// Assign active class to nav links while scolling
$('.page-section').each(function(i) {
if ($(this).position().top <= scrollDistance) {
$('.navigation a.active').removeClass('active');
$('.navigation a').eq(i).addClass('active');
}
});
}).scroll();
Is there a way that I change the code to adapt to all screen size? And how should I make the section interactive with bootstrap?
I'm stil new to front-end development, appriciate for any help!
Fix your if statement:
if ($(this).position().top - $(this).height() <= scrollDistance)
This code works well, but when I scroll up and down after 4-5 times it crashes and all the elements disappear. Why does this happen and how do I fix it?
$(window).on("load",function() {
$(window).scroll(function() {
var winheight = $(window).innerHeight();
$(".fade").each(function() {
/* Check the location of each desired element */
var objectBottom = $(this).offset().top + $(this).outerHeight();
var windowBottom = $(window).scrollTop() + $(window).innerHeight();
/* If the element is completely within bounds of the window, fade it in */
if ( windowBottom > (objectBottom - (winheight*0.65))) { //object comes into view (scrolling down)
if ($(this).css("opacity")==0) {$(this).fadeTo(500,1);}
} else { //object goes out of view (scrolling up)
if ($(this).css("opacity")==1) {$(this).fadeTo(500,0);}
}
});
}); $(window).scroll(); //invoke scroll-handler on page-load
});
Ok, I supposed that your html is something like this: https://jsfiddle.net/szdwwdac/
Sometimes, if you are scrolling fast up and down, when the element is fading out, your if doesn't work well.
if ( windowBottom >= (objectBottom - (winheight*0.65))) {
if ($(this).css("opacity")==0) {$(this).fadeTo(300,1);}
} else { //object goes out of view (scrolling up)
if ($(this).css("opacity")==1) {$(this).fadeTo(300,0);}
}
It's because of the 500ms of animation.
One of the solutions can be the eneble/disable for 500ms of the scroll page.
You can check this solution: How to disable scrolling temporarily?
EDIT
Another solution can be: add a class "fading" when you are inside your if. Then, in the if, eval if the element hasClass "fading". If not, you can go inside and make the animation.
I have a filter on my website positioned in an aside with a class 'left-bar'. My site is responsive and i want the filter to move to the div with the class 'mobile-top-bar'.
With the first 'if' i check if the window isn't already below 992px and when that's the case the filter will be moved to the 'mobile-top-bar' (this works great)
if ($(window).width() < 992) {
$('#moveableFilter').prependTo('.mobile-top-bar');
}
With the second piece of code i've made a function that should move the filter back and forth, but that doesn't happen. The filter already disappears from the 'left-bar' when i slightly change the width of the window (when it's still above 992px) and when i change it below 992px it isn't present in the mobile-top-bar.
What did i do wrong?
$(window).on('resize', function(){
var win = $(this);
if (win.width() < 992) {
$('#moveableFilter').prependTo('.left-bar');
} else if (win.width() >= 992) {
$('#moveableFilter').prependTo('.mobile-top-bar');
}
});
It looks like you switched the cases around by accident. Try this:
$(window).on('resize', function(){
var win = $(this);
if (win.width() >= 992) {
$('#moveableFilter').prependTo('.left-bar');
} else if (win.width() < 992) {
$('#moveableFilter').prependTo('.mobile-top-bar');
}
});
... However, I do agree with the comment that says that it would be better not to use two different bars, but to move it with CSS media queries.
I'm encountering a slight problem with my navigation. When I resize my browser to check the mobile menu and click the 'header' a couple times for the dropdown menu, then resize my page back to a tablet or desktop size, my navigation disappears. This problem resolves itself if I delete this segment of code:
if ( width == GetWidth() ) {
return;
}
width = GetWidth();
But I need this section of code so the navigation does not disappear when I scroll down on mobile.
var screensize = document.documentElement.clientWidth;
$(document).ready(function(){
var isMobile = window.matchMedia("only screen and (max-width: 600px)");
if (isMobile.matches) {
$('#mobile_active li a').on('click',function() {
$('.Back a').text('Back');
$('#mobile_active li ul li a').slideToggle(150);
e.preventDefault();
});
}
$(window).resize(function(){
if ( width == GetWidth() ) {
return;
}
width = GetWidth();
if( $(window).width() < 600) {
$('#mobile_active').hide();
} else {
$('#mobile_active').show();
}
});
$('header').on('click', function() {
$('#mobile_active').slideToggle(500);
e.preventDefault();
});
});
Any advice or input would be of great help. Thank you.
I agree you should use media queries and javascript for this type of thing, but I think I have found the cause of your issue.
When in mobile mode you have a click event attached to your <header> with a slideToggle. This slideToggle sets an inline style of display:block; or display:none; on the #mobile_active after it animates; depending on wether its closed or opened. When you resize to desktop size the #mobile_active still has an inline style of display:none; which is why you can not see it any more.
It looks like you may have code to correct this on your resize event:
if( $(window).width() < 600) {
$('#mobile_active').hide();
} else {
$('#mobile_active').show();
}
I think it just needs placed before this code block:
if ( width == GetWidth() ) {
return;
}
width = GetWidth();
Which may be why when you remove it, it works
I have the following script:
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$("#reas").fadeIn(2000);
$(".footer").fadeIn(2000);
$(".master_footer").css("position", "relative");
}
});
The script above changes the position of .master_footer if the user scrolls below #reas. But when i go up the position for .master_footer remains at relative. What can I do to reset it to position:absolute when the user scrolls back up?
by changing only the js code:
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$("#reas").fadeIn(2000);
$(".footer").fadeIn(2000);
$(".master_footer").css("position", "relative");
}else{
$(".master_footer").css("position", "absolute");
}
});
But i would rather use something like:
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$("#reas").fadeIn(2000);
$(".footer").fadeIn(2000);
$(".master_footer").addClass('relative');
}else{
$(".master_footer").removeClass('relative');
}
});
and then you can just custom your css
.relative{ position:relative; }
Assuming you've set the css for the .master_footer element previous to setting it with the javascript: in your javascript, when you want to reset the element back to its default style, just remove the style attribute from the element:
$(".master_footer").removeAttr("style");
for example:
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
$("#reas").fadeIn(2000);
$(".footer").fadeIn(2000);
$(".master_footer").css("position", "relative");
} else if ($(window).scrollTop() < 500){ // <-- set your reset point here
$(".master_footer").removeAttr("style");
}
});
where you would set the else if statement to whatever point you wanted to reset your element at.
First of all, I would recommend a polling solution rather than attaching an event handler to the scroll event, particularly if you intend to support older versions of IE, some of which seem to trigger the event for each pixel scrolled! E.g., you can check the scroll position as you are once per second.
Secondly, since you are using 2000ms fades, you should hold in a variable the state of the elements being faded so you don't fire a fadeOut event while the element is still being faded in (or at the very least you can stop() the existing animation).
And as far as your original question is concerned, it looks like maybe you should be able to set $('.master_footer').css('position', 'absolute') when (t < y) if you are setting position to relative when t == y. (You also might want to check t >= y in case the browser being used supports overscroll).