I am not able to scroll all the way until end. Following code stop working near the end of page.
I have used following methods to scroll programmatically,
// 1 still see scrolling left
window.scrollTo(x,y) > window.scrollTo(window.scrollWidth,0)
window.scrollBy(x,y) >
// 2
scrollingElement.scrollLeft = scrollingElement.scrollWidth - document.documentElement.clientWidth;
Info:
Some width related info for my case,
window.scrollWidth > 6180
scrollingElement.scrollWidth > 6183
document.documentElement.clientWidth > 412
Note: I have used webkitColumnGap css and turned vertical page into horizontal. That's why I have bigger scrollWidth.
If I use following (full scroll) I still see, there is some scrolling left and I can use mouse to scroll that part,
window.scrollTo(window.scrollWidth,0) // go to end
scrollingElement.scrollLeft = <full width> // go to end
// log scroll position for inpection ~ this number does not match the full width
window.scrollX ~ 4k
(window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0) ~ 4k
I have run out of ideas so would need help from you guys to find out the issue.
Browser details:
I am using flutter Webview in android device.
Edit:
After lot of trial and error adding following css fixed the issue, I don't why this fixed it?
body {
overflow: hidden !important;
}
Thanks.
You want to scroll to the bottom?
Try this:
var height = document.body.scrollHeight
window.scroll(0, height)
Hope i understood your question correctly
After lot of trial and error adding following css fixed the issue, I don't why this fixed it?
body {
overflow: hidden !important;
}
This means that some of your children elements bled out of its parent container. overflow: hidden tells the browser to cut out the parts that are not fitting inside the body container. That also means that this issue can be solved by changing the size or positioning of the body's children, and that would probably be a better approach to fixing the issue.
By default, overflow is set to visible, and therefore the browser allows you to see (and to scroll) outside of the containing box (overflow property explained)
The !important part tells the browser to artificially increase the specificity of this rule. For more details on specificity: css-tricks/sprecificity
Related
I have a project where the requirement is to move the footer ( #footer ) upward while scrolling down the page in a parallax-like effect. When you start scrolling down the page, the footer should start moving upward only until it's visible in the (bottom part of the) viewport.
The footer should have covered most of the preceding <div> half way up and in full when it has reached the top of the viewport.
The page may have a similar html structure like this :
<body>
<div id="sectionA" class="div">First section</div>
<div id="sectionB" class="div">Second section</div>
<div id="sectionC" class="div">Third section
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<div id="footer" class="div cf">Footer</div>
</body>
The parallax-like effect is achieved via javascript/jQuery adding a dynamic negative value to the top CSS property of the (relative positioned) footer. Here is the code for what it matters :
var $window = jQuery(window),
$footer = jQuery("#footer"),
$viewport = window.innerHeight,
$startEffect = $footer.offset().top - $viewport;
function footerParallax() {
var $scrollPos = $window.scrollTop() - $startEffect,
$ratio = 0.6;
$footer.css({
top: -($scrollPos * $ratio)
});
}
$window.scroll(function () {
footerParallax();
});
The (obvious) issue is that as soon as the top property starts getting a negative value, the footer starts moving away from the bottom of the page.
I have prepared a JSFIDDLE and assigned colors to each section and body to make it clearer. The body (dark-red) is visible under the footer after scrolling to the bottom.
What have I tried?
modifying the margin-top instead of the top property: this does the trick, however the preceding <div> that has to be covered by the footer (#sectionC in the example above) overlaps the contents of the footer and breaks its layout regardless that it is not visible due to its z-index property (added some floating boxes in the fiddle to make it evident.... a clearfix hack didn't help either.)
setting a static position to the footer: neither top or margin-top have effect over a static element.
Changing/reducing dynamically the height of #sectionC instead of top of footer to produce the effect of moving the second upwards : the footer stops moving as soon as height is equal to 0 (neither negative size or negative paddings are allowed)
Changed the height dynamically of the html and/or body tags to no avail.
I have also tried some parallax plugins like skrollr and skrollr-stylesheets and some others.
The problem with this solution (same with others) is that it relays in an specific (offset) position of the footer measured in px and set in a data attribute, but if the content changes dynamically, for example using the masonry plugin to arrange elements in another section of the document, the measures become inaccurate and the footer may start moving too early or too late.
By the way, other CSS sticky-footer techniques won't work because, well, they actually push the footer to the bottom of the page, and here we are doing the opposite.
I guess the question is either :
how to keep the footer stick to the bottom of the page while it is moved upwards? - or -
how to reduce the gap to 0 between the end of the document and the bottom edge of the footer?
I am starting to think that this issue has not a real solution the way it is, or maybe I am already too tired to see the obvious. I am interested in learning alternative solutions or hacks via CSS / javascript / jQuery or all of the above.
Bear in mind that I am not asking how to create the parallax effect UNLESS a totally different approach (or tweaks to the existing js code) solves the position issue.
IMPORTANT : Please consider that this is a WP site with an XHTML 1.0 Transitional DOCTYPE, and has installed many other jQuery plugins like masonry, scrollTo, jQuery UI, etc. I may have not control to change many things from the original structure (and I don't want to) so the idea is to implement this without breaking too many things and from a modular script.
EDIT #1 : Added a graphic to clarify the question.
Figure A. shows a regular web page scrolled down to the end. The red square represents the viewport and the footer (grey) is slighted moved to the right for illustration purposes. The body has a reddish background color (not visible in normal conditions) just for illustration purposes too. NOTE: the height of each section as well as the height of the footer is determined by their content (forms, images, text, etc.) so is NOT fixed.
Figure B. shows the current issue: If footer slides up in a parallax-like effect (see JSFIDDLE for reference) while scrolling down the page, it starts covering any preceding section above it (WITHOUT modifying neither its own height or the height of the preceding sections) AND it also starts separating itself from the bottom of the page, therefore the body's color background becomes visible. NOTE: the bigger the viewport is (fullscreen mode for instance) the higher the footer is moved upward (and more content is covered by it)
Figure C. is the expected result: the footer should be stuck to the bottom of the page, in other words, it should be the last visible element after the page has been totally scrolled down (and not the body background as in Figure B.) Notice that the contents and the size of each section (including the footer) should (ideally) remain untouched. Having said that, adding padding bottom to the footer or increasing its height is not the expected result since it would break its original visual layout.
Updated Version
Below is an updated version that should better matches your requirements.
This version goes back to relative positioning for the footer element and uses margin-top to position it.
margin-top is calculated off of the previous elements offset, height and current window scroll position. It then uses either
the viewport height if the footer starts offscreen
the initial top value of the footer element ($startEffect) if the footer started onscreen
to determine the actual value for margin-top.
To help keep the footer's layout from being affected by this, wrapping the content of the footer in an absolutely positioned div did the trick for the sample code provided.
Example Fiddle
CSS:
#footer > div {
position: absolute;
top: 0;
left: 0;
...
}
HTML:
<div id="footer" class="div cf"><div>Footer</div></div>
Code:
var $window = jQuery(window),
$footer = jQuery("#footer"),
$viewport = window.innerHeight,
$startEffect = $footer.offset().top;
$prev = $footer.prev(),
$useStartEffect = $startEffect < $viewport;
function footerParallax() {
var $scrollPos = $window.scrollTop() - $startEffect,
$ratio = 0.6;
var prevOffset = $prev.offset().top + $prev.height() - $window.scrollTop();
var marginTop = 0;
if(prevOffset < $viewport && prevOffset < $startEffect) {
if($useStartEffect) {
marginTop = (prevOffset - $startEffect)*$ratio;
} else {
marginTop = (prevOffset - $viewport)*$ratio;
}
}
$footer.css({
"margin-top": marginTop + 'px'
});
}
$window.scroll(function () {
footerParallax();
});
footerParallax();
How was it solved?
As I mentioned in my question, I was too tired to see the obvious but #dc5's answer put me on the right track :
To help keep the footer's layout from being affected,
wrapping the content of the footer in an absolutely
positioned div does the trick
Based on that comment, the answer became simpler than the whole code he proposed needing only :
(dynamically) wrapping the content of the footer in an absolutely positioned div using jQuery's .wrapInner() method
animating the footer by setting the margin-top property instead of the top property
So this extra CSS :
#footerInnerWrapper {
position: absolute;
top:0;
left:0;
width: 100%;
background-color: #666 /* same as footer */
}
and the tweaked original code
var $window = jQuery(window),
$footer = jQuery("#footer"),
$viewport = window.innerHeight,
$startEffect = $footer.offset().top - $viewport;
// add inner wrapper
$footer.wrapInner('<div id="footerInnerWrapper" />');
function footerParallax() {
var $scrollPos = $window.scrollTop() - $startEffect,
$ratio = 0.6;
$footer.css({
// top: -($scrollPos * $ratio)
marginTop: -($scrollPos * $ratio)
});
}
$window.scroll(function () {
footerParallax();
});
did the trick. See JSFIDDLE
This does what I think you need, the footer sticks when it has scrolled in view entirely:
jsFiddle
Code added:
function footerParallax() {
var $scrollPos = $window.scrollTop() - $startEffect,
$ratio = 0.6,
$newTop = -($scrollPos * $ratio),
$oldTop = parseInt($footer.css('top')),
$nonRelTop = $footer.offset().top - $oldTop,
$wanted = ($window.scrollTop()+$viewport-$footer.height());
if ($nonRelTop + $newTop < $wanted) {
$('#sectionC').css('display', 'none');
$wanted = ($window.scrollTop()+$viewport-$footer.height());
$nonRelTop = $footer.offset().top - $oldTop;
$newTop = $wanted - $nonRelTop;
} else {
$('#sectionC').css('display', 'block');
}
$footer.css('top', $newTop);
}
$window.scroll(footerParallax);
And in the CSS I added this so that $footer.css('top') wouldn't produce NaN:
#footer {
top:0;
/* ... */
}
EDIT: A completely new approach after more clarification of OP. I now have a fixed position footer that starts increasing in height to take over the entire screen when the user has scrolled passed half of the document. The HTML, CSS and Javascript have all been updated to achieve this:
jsFiddle
I have made a rediculasly small snippet to make a sub-header stick to the top.
But since , Like I said - I am by no means a js genious or jQuery genious - and actually far from it - I have my doubts about my own coding abilities..
the demo is here : http://jsfiddle.net/obmerk99/VvKq3/1/
The questions :
1 - there seems to be a lot of plugins (and a lot of questions also
in this very site) with much more code than my snippet - what am i
missing ?? What am I doing wrong ?
2 - will this work cross-browser ?
3 .. and this is a small problem, how to avoid the small "jump" that occurs ?
(if you go to the fiddle, and scroll slowly - you will see that the main div "jumps" when the script is evoked ..
I have tried to add another .pad class to the lower divs -
added class : .pad when script evoked.
.pad{padding-top:42px;}
but it does not seems to work right : http://jsfiddle.net/obmerk99/VvKq3/2/
5 .How can I calculate the real position of the div ? when I try
something like this :
var top = jQuery(window).scrollTop();
var div_top = jQuery('#header_stick').offset().top;
if (top > div_top) // height of float header;
it is jumpy ... http://jsfiddle.net/obmerk99/VvKq3/4/
6 any other suggestions are welcome..
The "jumping" occurs because the element was occupying space in the parent element, and when you change its position to fixed it's suddenly not anymore. I don't know the best way to handle it, but one option would be adding a small span (maybe with a single space) just before your #header_stick, with the same height of it, so when it's class is changed there will still be something there to account for the height difference. (Update: your pad solution is probably the best one, once done right; see below)
Your padding solution might also work, provided that: 1) you remember to remove that class when the user scrolls to the top (in your fiddle I see you adding it, but don't see you removing it); 2) You get the height right - I still couldn't look closely to your code, so I don't know where you got wrong. (Edit: the problem was that your .pad class was using the height of the floating header, not the stick header - fixing that and removing the class yielded what I believe to be the correct result)
About the real position of the div, have you tried subtracting the div's offset from the offset of the parent element? This way you'll have its position relative to the parent (pay attention to things like borders, though - I've recently answered another question where details like this mattered).
Update: your problem here seems to be that, when the position is changed to fixed, the offset also varies wildly. I'd suggest calculating the correct height, once, then storing it somewhere so the scroll function can use it. In other words, don't calculate it while scrolling, that makes it much more difficult to find the right theshold to do the class switch.
Other than that, I think you're code is fine, and I believe it will work cross browsers too (at least standards compliant ones; can't say anything about old versions of IE). Very insightful too, I always wondered how this "trick" worked, now I see it's simpler than I imagined...
You can try this way. I made a shorter version for easier analysis.
fiddle here
<div id="ontop">floating heading</div>
<header>sticky heading</header>
<div id="wrapper">
1<br/>2<br/>3<br/>4<br/>5<br/>6<br/>7<br/>8<br/>9<br/>10<br/>
</div>
#ontop {width:100%; height:80px; background-color:yellow;}
header {width:100%; height:20px; background-color:lightgrey; }
#wrapper {background-color:lightblue; height:5000px;}
.navfixed {position: fixed; top: 0px; z-index: 100; width:100%; display:block; margin-bottom:120px; }
.wrapperBelow{margin-top:22px;}
$(function () {
var elem = $('header'),
wrapperElem = $('#wrapper'),
elemTop = elem.offset().top;
$(window).scroll(function () {
elem.toggleClass('navfixed', $(window).scrollTop() > elemTop);
wrapperElem.toggleClass('wrapperBelow', $(window).scrollTop() > elemTop);
}).scroll();
});
I can't be the first to notice this but ever since 10.7 came out and they implemented the new style of scrollbars $(window).width() and $(window).height() no longer correctly return the size of the browser windows viewport....
Lets say you want to set a div the size of the browser window on load eh...
// load jquery //
<div id="bob">
</div>
<script>
$('#bob').width($(window).width()).height($(window).height());
</script>
and what ends up happening is something like this
To this I ask WTF?
here is an example of the issue
http://lab.aerotwist.com/webgl/a3/vertex-manipulation/
Do the elements containing #bob have margin or padding? If they do, that could be adding more space beyond the width and height of #bob, forcing scrollbars to appear.
If that's the problem, you could fix that by adding CSS like this:
html, body, #bob {
margin: 0;
padding: 0;
}
After dabbling in Chrome Extensions I've noticed that when the data inside the Page Action gets to a certain point the scroll bars automatically attach themselves to the popup, this I expect. However, instead of pushing the content to the left of the scroll bar it overlays the content causing a horizontal scrollbar to become active. I ended up just adding a check on my data and applying a css class to push the content to the left more to run parallel to the scroll bar and beside it not under it. What is the correct way to handle this besides my hackish solution?
I was wondering this myself too. Currently I just don't put anything important closer than 20px to the right side of a popup and disable horizontal scrollbars:
body {overflow-x:hidden;overflow-y:auto;}
So when a vertical scrollbar appears the content at least doesn't jump.
Perhaps you need to specify a width on the scrollbar.
::-webkit-scrollbar {
width: 42px; //Do not know actual width, but I assume you do
}
I haven't found a way to do this that isn't a hack, but here's the simplest hack I could think of:
<script type="text/javascript">
function tweakWidthForScrollbar() {
var db = document.body;
var scrollBarWidth = db.scrollHeight > db.clientHeight ?
db.clientWidth - db.offsetWidth : 0;
db.style.paddingRight = scrollBarWidth + "px";
}
</script>
...
<body onresize="tweakWidthForScrollbar()">
The idea is to detect whether the vertical scrollbar is in use, and if it is, calculate its width and allocate just enough extra padding for it.
A view in my web app has a table which may be extremely long, so I wrapped it in a div with overflow: auto; max-height: 400px; so users can scroll through it while keeping the other controls on the page visible.
I want to use a bit of JavaScript to dynamically adjust the max-height CSS property so the div stretches to the bottom of the browser window. How can I determine this value? jQuery solutions are fine.
The table doesn't start at the top of the page, so I can't just set the height to 100%.
Something like this would work I think:
var topOfDiv = $('#divID').offset().top;
var bottomOfVisibleWindow = $(window).height();
$('#divID').css('max-height', bottomOfVisibleWindow - topOfDiv - 100);
I had a very similar problem, except in my case I had a dynamic pop-up element (a jQuery UI Multiselect widget), to which I wanted to apply a max-height so that it never went below the bottom of the page. Using offset().top on the target element wasn't enough, because that returns the x coordinate relative to the document, and not the vertical scroll-position of the page.
So if the user scrolls down the page, the offset().top won't provide an accurate description of where they are relative to the bottom of the window - you'll need to determine the scroll position of the page.
var scrollPosition = $('body').scrollTop();
var elementOffset = $('#element').offset().top;
var elementDistance = (elementOffset - scrollPosition);
var windowHeight = $(window).height();
$('#element').css({'max-height': windowHeight - elementDistance});
window.innerHeight gives you the visible height of the entire window. I did something almost identical recently so I'm pretty sure that's what you need. :) Let me know, though.
EDIT: You'll still need the Y-value of the overflowed div which you can get by document.getElementById("some_div_id").offsetHeight, seeing that .style.top won't give you a result unless it has been specifically set to a point via CSS. .offsetHeight should give you the correct 'top' value.
Then it's just a matter of setting the size of the table to the window height, minus the 'top' value of the div, minus whatever arbitrary wiggle room you want for other content.
something like max-height: 100%, but not to forget the html and body height 100%.