Affix position not being recalculated on resize - javascript

I want to make my navbar become affixed when you scroll and it reaches the top even when you resize the window.
The position at which it's triggered is not updating even though I set it to recalculate the values when I $(window).resize(). What's wrong?
$(document).ready ->
$(window).resize ->
windowHeight = $(window).height()
navHeight = $('#navbar-affixable-wrapper > #navbar.affixable').outerHeight()
windowMinusNavHeight = windowHeight - navHeight
$('#navbar-affixable-wrapper > #navbar.affixable').affix
offset: { top: windowMinusNavHeight }
Or in javascript:
$(document).ready(function() {
return $(window).resize(function() {
var navHeight, windowHeight, windowMinusNavHeight;
windowHeight = $(window).height();
navHeight = $('#navbar-affixable-wrapper > #navbar.affixable').outerHeight();
windowMinusNavHeight = windowHeight - navHeight;
return $('#navbar-affixable-wrapper > #navbar.affixable').affix({
offset: {
top: windowMinusNavHeight
}
});
});
});

Can you return the offset top value as a function?
For example:
$(function(){
var $window = $( window );
var $navbar = $('#navbar-affixable-wrapper > #navbar.affixable');
$navbar.affix({
offset: {
top: function(){
// Calculate offset top value
return $window.height() - $navbar.outerHeight( true ); // I always pass true in there so margin is taken into consideration.
}
}
})
});
You can checkout the affix documentation on the Bootstrap website.

Related

Jquery transition Opacity based on var value

I am trying to animate an opacity value from 0 to 1, based on the scroll position within the viewport height. The code below sets variables for windowHeight and scrollTop, which can be combined to calculate percentageScrolled (0–100) of the viewport height. Based on this I am able to switch CSS values at set points, but instead I want to gradually change the opacity from 0–100 of percentageScrolled.
How can I adjust the code below to transition/animate the opacity?
Thanks.
$(window).on('scroll', function(){
// Vars
var windowHeight = $(window).height();
var scrollTop = $(this).scrollTop();
var percentageScrolled = (scrollTop*100)/windowHeight;
if( percentageScrolled < 100 ) {
$('.colour-overlay').css('opacity', '1');
} else {
$('.colour-overlay').css('opacity', '0');
}
});
You can remove the if and set the opacity to the percentage divided by 100
$(window).on('scroll', function() {
// Vars
var windowHeight = $(window).height();
var scrollTop = $(this).scrollTop();
$('.colour-overlay').css('opacity', scrollTop / windowHeight);
});
.colour-overlay {
display: block;
width: 20px;
height: 1200px;
background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="colour-overlay"></div>
$(‘.colour-overlay’).css(opacity, percentageScrolled / 100);
Instead of if else statement.
Also as a general advice try to avoid using var, use const or let instead and if your project doesnt depend on jquery try to avoid it too.
const overlays = document.querySelectorAll(‘.colour-overlay’);
window.addEventListener('scroll', () => {
const windowHeight = window.offsetHeight;
const scrollTop = window.scrollTop;
const percentageScrolled = (scrollTop * 100) / windowHeight;
for (const overlay of overlays) {
overlay.style.opacity = percentageScrolled / 100;
}
});
This would be the pure js solution.
Dont know if i understood you right, but a wrote an example have a look.
$(document).on('scroll', function(){
// Vars
// use body instead of window, body will return the right height where window will return the view size
var windowHeight = $("body").height();
var scrollTop = $(this).scrollTop();
var percentageScrolled = Math.abs((((scrollTop / windowHeight) * 100) / 100 ));
$('.colour-overlay').css('opacity', percentageScrolled);
});
.colour-overlay{
background:red;
height:1000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="colour-overlay"></div>

debug lag of calculate margin top for Position fixed sidebar scrolling to bottom

I want to fix left sidebar on the responsive view.
I use Margin top (dependency with scroll position) for wrapper of sidebar!
that's work! but on the some browser it's slow motion (example: macbook pro retina 15" 2014 chrome Version 42)
jsfiddle
jQuery(function($){
var target = $('#fixed_sidebar .fixed');
var sidebarPosition = $(target).offset().top;
function calculatesidebar(){
var heightWindow = $(window).height();
var scrollPosition = $(document).scrollTop();
var sidebarHeight = target.outerHeight();
var positionOftarget = (sidebarPosition + sidebarHeight) - heightWindow;
var targetMargin = parseInt(target.css('marginTop'));
if (scrollPosition >= positionOftarget){
var margin = scrollPosition - positionOftarget;
target.css('marginTop', margin+'px');
}else{
target.css('marginTop', '0');
}
}
$( window ).scroll(function(){
calculatesidebar();
});
$( window ).resize(function() {
calculatesidebar();
});
});
i'm resolved in other way
jsfiddle
jQuery(function ($) {
function fixed_sidebar_bottom(wrapper, target) {
var left = $(wrapper).offset().left,
right = $(wrapper).offset().right,
top = $(wrapper).offset().top,
width = $(wrapper).width(),
target = $(target),
targetHeight = target.outerHeight(),
scrollPosition = $(document).scrollTop(),
windowHeight = $(window).height(),
windowWidth = $(window).width(),
hotSpot = (top + targetHeight) - windowHeight;
if (scrollPosition >= hotSpot) {
if (!target.attr('style')) {
target.css({'left': left, 'right': right, 'position': 'fixed', 'bottom': '0', 'width': width});
} else {
target.css({'left': left, 'right': right, 'width': width});
}
} else {
target.removeAttr("style");
}
}
$(window).scroll(function () {
fixed_sidebar_bottom('#fixed_sidebarLeft','#fixed_sidebarLeft_target');
});
$(window).resize(function () {
fixed_sidebar_bottom('#fixed_sidebarLeft','#fixed_sidebarLeft_target');
});
});

Sticky sidebar doesn't stop scrolling

I have a sticky sidebar on my page using the following script:
$(function() {
var offset = $("#sidebar").offset();
var topPadding = 15;
$(window).scroll(function() {
if ($(window).scrollTop() > offset.top) {
$("#sidebar").stop().animate({
marginTop: $(window).scrollTop() - offset.top + topPadding
});
} else {
$("#sidebar").stop().animate({
marginTop: 0
});
};
});
});
The problem is that it should stop scrolling when it reaches the Middle Block Div. At the moment it doesn't stop scrolling and it pushes all the rest of the content down. Is there a way to fix this?
- DEMO -
Thank you.
You need to get the position of .middle-block and stop the sidebar from scrolling at that point (minus the height of the sidebar).
Change your jQuery function to:
$(function() {
var offset = $("#sidebar").offset();
var mbOffset = $(".middle-block").offset();
var mbPos = mbOffset.top - $("#sidebar").outerHeight() - 30; /*30px extra space*/
var topPadding = 15;
$(window).scroll(function() {
if ($(window).scrollTop() > offset.top ) {
if( $(window).scrollTop() < mbPos ) {
$("#sidebar").stop().animate({
marginTop: $(window).scrollTop() - offset.top + topPadding
});
}
} else {
$("#sidebar").stop().animate({
marginTop: 0
});
};
});
});
Updated Pen
you have check if Sidebar has been moved to Middle Box, if so just stop the sidebar to animate.
like this :
$(function() {
var offset = $("#sidebar").offset();
var boxOffset = $(".middle-block").offset().top;
var sidebarHeight = parseInt($("#sidebar").outerHeight());
var topPadding = 15;
$(window).scroll(function() {
if ($(window).scrollTop() > offset.top) {
if(($(window).scrollTop()+sidebarHeight)<boxOffset){
$("#sidebar").stop().animate({
marginTop: $(window).scrollTop() - offset.top + topPadding
});
}
} else {
$("#sidebar").stop().animate({
marginTop: 0
});
};
});
});
check it live here: jsfiddle

Get the visible height of a div with jQuery

I need to retrieve the visible height of a div within a scrollable area. I consider myself pretty decent with jQuery, but this is completely throwing me off.
Let's say I've got a red div within a black wrapper:
In the graphic above, the jQuery function would return 248, the visible portion of the div.
Once the user scrolls past the top of the div, as in the above graphic, it would report 296.
Now, once the user has scrolled past the div, it would again report 248.
Obviously my numbers aren't going to be as consistent and clear as they are in this demo, or I'd just hard code for those numbers.
I have a bit of a theory:
Get the height of the window
Get the height of the div
Get the initial offset of the div from the top of the window
Get the offset as the user scrolls.
If the offset is positive, it means the top of the div is still visible.
if it's negative, the top of the div has been eclipsed by the window. At this point, the div could either be taking up the whole height of the window, or the bottom of the div could be showing
If the bottom of the div is showing, figure out the gap between it and the bottom of the window.
It seems pretty simple, but I just can't wrap my head around it. I'll take another crack tomorrow morning; I just figured some of you geniuses might be able to help.
Thanks!
UPDATE: I figured this out on my own, but looks like one of the answers below is more elegant, so I'll be using that instead. For the curious, here's what I came up with:
$(document).ready(function() {
var windowHeight = $(window).height();
var overviewHeight = $("#overview").height();
var overviewStaticTop = $("#overview").offset().top;
var overviewScrollTop = overviewStaticTop - $(window).scrollTop();
var overviewStaticBottom = overviewStaticTop + $("#overview").height();
var overviewScrollBottom = windowHeight - (overviewStaticBottom - $(window).scrollTop());
var visibleArea;
if ((overviewHeight + overviewScrollTop) < windowHeight) {
// alert("bottom is showing!");
visibleArea = windowHeight - overviewScrollBottom;
// alert(visibleArea);
} else {
if (overviewScrollTop < 0) {
// alert("is full height");
visibleArea = windowHeight;
// alert(visibleArea);
} else {
// alert("top is showing");
visibleArea = windowHeight - overviewScrollTop;
// alert(visibleArea);
}
}
});
Calculate the amount of px an element (height) is in viewport
Fiddle demo
This tiny function will return the amount of px an element is visible in the (vertical) Viewport:
function inViewport($el) {
var elH = $el.outerHeight(),
H = $(window).height(),
r = $el[0].getBoundingClientRect(), t=r.top, b=r.bottom;
return Math.max(0, t>0? Math.min(elH, H-t) : Math.min(b, H));
}
Use like:
$(window).on("scroll resize", function(){
console.log( inViewport($('#elementID')) ); // n px in viewport
});
that's it.
jQuery .inViewport() Plugin
jsFiddle demo
from the above you can extract the logic and create a plugin like this one:
/**
* inViewport jQuery plugin by Roko C.B.
* http://stackoverflow.com/a/26831113/383904
* Returns a callback function with an argument holding
* the current amount of px an element is visible in viewport
* (The min returned value is 0 (element outside of viewport)
*/
;(function($, win) {
$.fn.inViewport = function(cb) {
return this.each(function(i,el) {
function visPx(){
var elH = $(el).outerHeight(),
H = $(win).height(),
r = el.getBoundingClientRect(), t=r.top, b=r.bottom;
return cb.call(el, Math.max(0, t>0? Math.min(elH, H-t) : Math.min(b, H)));
}
visPx();
$(win).on("resize scroll", visPx);
});
};
}(jQuery, window));
Use like:
$("selector").inViewport(function(px) {
console.log( px ); // `px` represents the amount of visible height
if(px > 0) {
// do this if element enters the viewport // px > 0
}else{
// do that if element exits the viewport // px = 0
}
}); // Here you can chain other jQuery methods to your selector
your selectors will dynamically listen to window scroll and resize but also return the initial value on DOM ready trough the first callback function argument px.
Here is a quick and dirty concept. It basically compares the offset().top of the element to the top of the window, and the offset().top + height() to the bottom of the window:
function getVisible() {
var $el = $('#foo'),
scrollTop = $(this).scrollTop(),
scrollBot = scrollTop + $(this).height(),
elTop = $el.offset().top,
elBottom = elTop + $el.outerHeight(),
visibleTop = elTop < scrollTop ? scrollTop : elTop,
visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
$('#notification').text(`Visible height of div: ${visibleBottom - visibleTop}px`);
}
$(window).on('scroll resize', getVisible).trigger('scroll');
html,
body {
margin: 100px 0;
}
#foo {
height: 1000px;
background-color: #C00;
width: 200px;
margin: 0 auto;
}
#notification {
position: fixed;
top: 0;
left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div id="foo"></div>
<div id="notification"></div>
The logic can be made more succinct if necessary, I've just declared separate variables for this example to make the calculation as clear as I can.
Here is a version of Rory's approach above, except written to function as a jQuery plugin. It may have more general applicability in that format. Great answer, Rory - thanks!
$.fn.visibleHeight = function() {
var elBottom, elTop, scrollBot, scrollTop, visibleBottom, visibleTop;
scrollTop = $(window).scrollTop();
scrollBot = scrollTop + $(window).height();
elTop = this.offset().top;
elBottom = elTop + this.outerHeight();
visibleTop = elTop < scrollTop ? scrollTop : elTop;
visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
return visibleBottom - visibleTop
}
Can be called with the following:
$("#myDiv").visibleHeight();
jsFiddle
Here is the improved code for jquery function visibleHeight: $("#myDiv").visibleHeight();
$.fn.visibleHeight = function() {
var elBottom, elTop, scrollBot, scrollTop, visibleBottom, visibleTop, height;
scrollTop = $(window).scrollTop();
scrollBot = scrollTop + $(window).height();
elTop = this.offset().top;
elBottom = elTop + this.outerHeight();
visibleTop = elTop < scrollTop ? scrollTop : elTop;
visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
height = visibleBottom - visibleTop;
return height > 0 ? height : 0;
}

jquery: $(window).scrollTop() but no $(window).scrollBottom()

I want to place an element to the bottom of the page whenever the user scrolls the page. It's like "fixed position" but I can't use "position: fixed" css as many of my clients' browser can't support that.
I noticed jquery can get current viewport's top position, but how can I get the bottom of the scroll viewport?
So I am asking how to know: $(window).scrollBottom()
var scrollBottom = $(window).scrollTop() + $(window).height();
I would say that a scrollBottom as a direct opposite of scrollTop should be:
var scrollBottom = $(document).height() - $(window).height() - $(window).scrollTop();
Here is a small ugly test that works for me:
// SCROLLTESTER START //
var showerEl = $('<h1 id="st" style="position: fixed; right: 25px; bottom: 25px;"></h1>')
showerEl.insertAfter('body');
$(window).scroll(function () {
var scrollTop = $(window).scrollTop();
var scrollBottom = $(document).height() - $(window).height() - scrollTop;
showerEl.html('scrollTop: ' + scrollTop + '<br>scrollBottom: ' + scrollBottom);
});
// SCROLLTESTER END //
For the future, I've made scrollBottom into a jquery plugin, usable in the same way that scrollTop is (i.e. you can set a number and it will scroll that amount from the bottom of the page and return the number of pixels from the bottom of the page, or, return the number of pixels from the bottom of the page if no number is provided)
$.fn.scrollBottom = function(scroll){
if(typeof scroll === 'number'){
window.scrollTo(0,$(document).height() - $(window).height() - scroll);
return $(document).height() - $(window).height() - scroll;
} else {
return $(document).height() - $(window).height() - $(window).scrollTop();
}
}
//Basic Usage
$(window).scrollBottom(500);
var scrollBottom =
$(document).height() - $(window).height() - $(window).scrollTop();
I think it is better to get bottom scroll.
This will scroll to the very top:
$(window).animate({scrollTop: 0});
This will scroll to the very bottom:
$(window).animate({scrollTop: $(document).height() + $(window).height()});
.. change window to your desired container id or class if necessary (in quotes).
try:
$(window).scrollTop( $('body').height() );
Here is the best option scroll to bottom for table grid, it will be scroll to the last row of the table grid :
$('.add-row-btn').click(function () {
var tempheight = $('#PtsGrid > table').height();
$('#PtsGrid').animate({
scrollTop: tempheight
//scrollTop: $(".scroll-bottom").offset().top
}, 'slow');
});
// Back to bottom button
$(window).scroll(function () {
var scrollBottom = $(this).scrollTop() + $(this).height();
var scrollTop = $(this).scrollTop();
var pageHeight = $('html, body').height();//Fixed
if ($(this).scrollTop() > pageHeight - 700) {
$('.back-to-bottom').fadeOut('slow');
} else {
if ($(this).scrollTop() < 100) {
$('.back-to-bottom').fadeOut('slow');
}
else {
$('.back-to-bottom').fadeIn('slow');
}
}
});
$('.back-to-bottom').click(function () {
var pageHeight = $('html, body').height();//Fixed
$('html, body').animate({ scrollTop: pageHeight }, 1500, 'easeInOutExpo');
return false;
});
var scrolltobottom = document.documentElement.scrollHeight - $(this).outerHeight() - $(this).scrollTop();
For an item in my page :
document.getElementById(elementId).scroll(0,
document.getElementById(elementId).scrollHeight);
function scrollBottum(elementId){
document.getElementById(elementId).scroll(0, document.getElementById(elementId).scrollHeight);
}
<html><div><button onclick="scrollBottum('myCart')">Click me to scroll</button></div>
<div id="myCart" style="height: 50px; overflow-y: scroll;">
<div>1: A First ...</div>
<div>2: B</div>
<div>3: C</div>
<div>4: D</div>
<div>5: E</div>
<div>6: F</div>
<div>7: LAST !!</div>
</div>
</html>
i try that and it work very well
scrollrev(){
let x:any= document.getElementById('chat')
x.scrollTop = -9000;
}
i try that code and it work
// scroll top
scroll(){
let x:any= document.getElementById('chat')
x.scrollTop = 9000;
}
// scroll buttom
scrollrev(){
let x:any= document.getElementById('chat')
x.scrollTop = -9000;
}
This is a quick hack: just assign the scroll value to a very large number. This will ensure that the page is scrolled to the bottom.
Using plain javascript:
document.body.scrollTop = 100000;

Categories