I have a webpage with a fixed y scrollable sidenav and a main body. When I scroll with my mouse scrollwheel, pointer inside the side nav, sometimes the body will scroll depending on where the element is positioned. Technically the margin of the main body is still overlapping with the side nav due to bootstrap offset like offset-md-3.
How can I stop the main body from scrolling while the mouse is on the sidenav? I need the solution without using any plugins. jQuery and Bootstrap 4 only please.
My initial instinct was like this, but changing to fixed caused the main body to snap back to the top.
I disabled scrolling on hover over the .SideNav, but I needed to keep the scrollbar for continuity.
$(".SideNav").hover(function () {
$('body').css({
"position": 'fixed',
"overflow-y": 'scroll'
});
},
function () {
$('body').css({
position: 'inherit',
"overflow-y": 'scroll'
});
});
Initially using fixed was causing the body to snap back to scrolling from the top of the page. I had to compensate like so.
var offset;
$(".SideNav").hover(function () {
offset = window.pageYOffset // Get offset to set position when fixed
$("main").css("position", "fixed");
$('body').css({
"position": 'fixed',
"overflow-y": 'scroll',
"top": 0 - offset
});
},
function () {
$("main").css("position", "inherit");
$('body').css({
"position": 'inherit',
"overflow-y": 'scroll'
});
$(window).scrollTop(offset); // When scroll bar returns, set page to original position
});
I found it to be an interesting situation and reading your answer I was wondering why you needed to also change the position and top properties although it very well may be necessary to accommodate to your specific html and css structure.
Any way, I thought I could include a different approach in a simpler/minimal scenario. Let me know what you think:
var currentOverflow;
$(".SideNav").hover(()=> {
currentOverflow = $('body').css('overflow');
$('body').css({
overflow: 'hidden'
})
},
() => {
$('body').css({
overflow: currentOverflow
})
});
.SideNav{
position: fixed;
height: 100vh;
width: 20vw;
background: red;
top: 0;
left: 0
}
span{
margin-left: 30vw
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="SideNav" id="fixed"></div>
<br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span>
<br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span>
<br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span>
<br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span>
Related
My question is how can I overlap a div over a fixed div on scroll without using a background image.
I want the bottom of the div to match the bottom of the screen to fix that div and make the content (the other divs) below to scroll up (like a parallax effect). Same with if the fixed div is bigger than the screen, as in bigger height (so position sticky won't work).
Here is what I've got so far. I checked if the user scrolled to the div, that I want the scroll effect at and fixed at the bottom. When I'm at that point the content acts like the fixed div doesn't exist and skips it abruptly instead of scrolling in from below. The effect works though when I scroll back up it just skips the fixed div.
I'm trying to achieve something like this:
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_parallax_percent
But without a background image.
.background-beige {
width: 100%;
background-color: #f8f8f8;
padding-bottom: 200px !important;
}
.contact-banner-wrapper {
height: 436px;
background-color: #c22a40;
position: relative;
}
$(window).scroll(function (e) {
var el = $(".contact-banner-wrapper");
var elem = $(".background-beige");
if (
$(window).scrollTop() >=
elem.offset().top + elem.outerHeight() - window.innerHeight
) {
elem.css({ position: "fixed", bottom: "0px"});
}
if ($(this).scrollTop() < 200) {
elem.css({ position: "static"});
console.log("reset");
}
});
Do you have improvements or any other solutions?
I did a work around, to my problem and now it works as intended. position: fixed; takes the div out of the flow of the DOM so it gets ignored and skipped by the other divs. I just gave the content (the other divs that scroll from below over the fixed div a top margin of the height of the fixed div to work around the position: fixed; change.
$(window).scroll(function (e) {
var scrollOverContent = $(".contact-banner-wrapper");
var fixedDiv = $(".contact-banner-wrapper").prev();
var heightFixedDiv = fixedDiv.outerHeight();
if (
$(window).scrollTop() >=
fixedDiv.offset().top + fixedDiv.outerHeight() - window.innerHeight
) {
fixedDiv.css({ position: "fixed", bottom: "0px", zIndex: "0" });
scrollOverContent.css("margin-top", heightFixedDiv);
}
if (
$(window).scrollTop() <
scrollOverContent.offset().top - $(window).height()
) {
fixedDiv.css({ position: "static" });
scrollOverContent.css({ marginTop: "0" });
}
});
I have my menu all set, good to go, and the JS I have at the moment doesn't have the page jumping all over the place which is good. The problem I am having, is getting my "fixed" navigation to slide up/down, instead of just appearing out of nowhere.
Currently the jQuery I have is activating a class at about 300px~ down the screen, which changes the menus position from relative to fixed.
Please note: I originally managed to get this working with static positioning, but was having a hard time with the z-index and some other elements on my site, so I would like the positioning to remain relative (not static). I also do not want to duplicate the menu in any way with javascript (have seen some examples doing that).
How can I use jquery, or css to achieve both the slidedown and slideup effect when the menus position changes to fixed?
My codes below, thankyou very much.
HTML:
<div class="nt-main-navigation-sticky">
<!-- my nav, logo, etc, is in here. -->
</div>
CSS:
.nt-main-navigation-sticky {
position: relative;
}
.activeScroll .nt-main-navigation-sticky {
position: fixed;
top: 0;
left: 0;
}
JQUERY:
// get my header height
var getHeaderHeight = $('.nt-main-navigation-sticky').outerHeight();
// add/remove body class
$(window).scroll(function() {
if($(window).scrollTop() > getHeaderHeight + 200) {
$('body').addClass('activeScroll').css('padding-top', getHeaderHeight);
} else {
$('body').removeClass('activeScroll').css('padding-top', 0);
}
});
Add a transition to your css:
.nt-main-navigation-sticky {
position: relative;
}
.activeScroll .nt-main-navigation-sticky {
position: fixed;
top: -50px; // or whatever the height of the navbar
left: 0;
transition: top 600ms;
}
and js:
if($(window).scrollTop() > getHeaderHeight + 200) {
$('body').addClass('activeScroll').css('padding-top', getHeaderHeight);
$('.nt-main-navigation-sticky').css('top', '0px'); // will trigger transition
} else {
$('.nt-main-navigation-sticky').css('top', '-50px'); // will trigger transition
$('body').removeClass('activeScroll').css('padding-top', 0);
}
I want
A site banner with a navbar below
The banner to disappear when scrolling down, but the navbar to
remain fixed
I found this jsfiddle which provides the above solution:
http://jsfiddle.net/DTcHh/541/
Two main points of code:
//js
$('#topnavbar').affix({
offset: {
top: $('#banner').height()
}
});
//css
#topnavbar.affix {
position: fixed;
top: 0;
width: 100%;
}
My problem now is when you scroll down to the point where the 'affix' happens. If you look carefully at that point it kinda jumps, and now the navbar is overlapping the first 4 lines in the paragraph
Any ideas how to get rid of that overlap?
You need to displace the fixed .navbar element by adding padding-top to the body element equal to the height of the fixed element.
You can listen to the affix.bs.affix/affix-top.bs.affix events and then determine whether the padding should be equal to the element's height or removed:
Updated Example - the jump you were seeing no longer occurs.
$('#topnavbar').on('affix.bs.affix affix-top.bs.affix', function (e) {
var padding = e.type === 'affix' ? $(this).height() : '';
$('body').css('padding-top', padding);
});
Add "z-index:10;" to your topnavbar.affix class in css.
position: fixed;
top: 0;
width: 100%;
z-index:10;
Let's say that we have body width of page set to 2000px with content centered horizontally inside of body with width set to 1200px.
<body>
<div class="content"></div>
</body>
CSS:
body {
width: 2000px;
}
.content {
position: relative;
width: 1200px;
margin-left: auto;
margin-right: auto;
}
What I am trying to achieve is that I do not allow horizontal scrolling at all until your
window size is 1200px or less (on resize) with setting overflow-x to hidden.
$(function() {
$(window).resize(function() {
if(window.innerWidth > 1200) {
$("body").css({
"overflow-x": "hidden"
});
} else {
$("body").css({
"overflow-x": "visible"
});
}
});
});
which works fine. But I also want to prevent user from scrolling further than 1200px if his window width is less than 1200px (problem here is that as soon as the window width is less than 1200px, it is possible to scroll to full width - 2000px).
So how would you solve this?
If I understand your question correctly then I believe this could be fixed by adding a max width style to your body tag. This eliminated side scroll for me.
body {
max-width: 2000px;
}
In this case you can use the scrollLeft proprerty:
onScroll = function (e){
var maxScroll=1200
if(e.target.scrollLeft>maxScrollLeft){
e.target.scrollLeft=maxScrollLeft
}
}
i was working on this div animation where the original position of div from top is 70% and the div is absolute.
Now, when I click on button it slides to bottom of page with top:95%.
Now I want to check if the position is top:95% and if so, then i want to slide it back to top:70%;
Somehow the Div slides to 95% but dosent come back. what i am doing wrong here??
code
css:-
#mainMenu {
width: 100%;
height: 30px;
background-color: black;
top: 70%;
position: absolute;
}
body {
margin: 0px;
}
#clickToCheck {
font-size: 22px;
}
JQuery
<script>
$(document).ready(function () {
$('#mainMenu').click(function () {
$("#mainMenu").animate({ top: "95%" }, 1100);
});
});
$(document).ready(function () {
$('#clickToCheck').click(function () {
if ($('#mainMenu').position().top === '95%') {
$("#mainMenu").delay(1000).animate({ top: "70%" }, 1200);
} else {
alert('its not at bottom');
}
});
});
and Html
<body>
<span id="clickToCheck">Click to CHeck</span>
<div id="mainMenu"></div>
The problem is that the function
$('#mainMenu').position().top
Will return the value in pixels instead of percentage. So if you want to check if the top is 95% you will have to do the math based on the top and window height (or div height). here is the code:
$('#mainMenu').position().top/$(window).height()*100
Here you will have the the percentage of the #mainMenu in relation to the full window. If the #mainMenu is inside a div, just do based on the div's height. Also beware that you will probably get a number like 94.2343123. So when checking, I would not do and "if = 95". I would do something like "if >= 93" or something like it.
The basic problem is that .position(), .offset(), and .css() all work in pixels by default.
A reasonable workaround would be to store the the menu's original .offset() using .data() and just check to see if its offset has changed, like so:
Working Example
$(document).ready(function () {
$('#mainMenu').data('startPos', $('#mainMenu').offset().top); // when the doc is ready store the original offset top.
$('#mainMenu').click(function () {
$("#mainMenu").animate({
top: "95%"
}, 1100);
});
$('#clickToCheck').click(function () {
if ($('#mainMenu').offset().top > $('#mainMenu').data('startPos')) { // if new offset is greater than original offset
$("#mainMenu").delay(1000).animate({
top: '70%'
}, 1200);
} else {
alert('its not at bottom');
}
});
});