Detect how much the user has scrolled within an element - javascript

I'm building a web app for which I disable the bounce back effect of OS X and iOS, but still need the user to be able to scroll.
So I ended up using this CSS trick to achieve that:
html {
height: 100%;
width: 100%;
overflow: hidden;
}
body {
height: 100%;
width: 100%;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
It works just fine (although not quite as smoothly as without the trick — any suggestions?). Given that I disable the scroll on the html, I know that I've got to bind the .scroll() to the body:
$('body').scroll(function() {
doSomething();
});
But the thing is, I need to detect how much the user has scrolled within the body element, and I can't seem to figure out how to do just that.
var doSomething = function(){
var scrollTop = $('body').offset().top; // returns 0.
var scrollTop = $('body').scrollTop(); // returns 0 as well.
};
Can anyone help me out? Thanks!

Easiest solution:
The easiest thing to do is just to check the position of the top element inside the body:
Here's the codepen
$(function(){
$('body').scroll(function(){
// Substitute your first element for 'header.main'
console.log( $('header.main').position().top );
});
});
Another method:
Or you can add a wrapper element like below:
I was able to get a correct offset by adding another element wrapper inside the body and checking the position of that.
Here's the codepen
<body>
<div id="offset">
<!-- all of your content in the "offset" wrapper -->
</div>
</body>
JS:
$(function(){
$('body').scroll(function(){
console.log( $('#offset').position().top );
});
});
Update: I tested this in OSX, and it looks like this does indeed suppress the bounce effect AND give the correct scroll offset number.

Related

How to move HTML elements when a page is scrolled?

How to make an HTML element that is initially 'fixed' then when we scroll the web page down or more specifically through the element, the element will move to the side or wherever we specify. And of course when we scroll the web page back up and pass the element, it will return to normal.
Please help if there is, I ask for an article or explanation of what to use and an example of the source code.
You can use sticky for that: https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_sticky_element
div.sticky {
position: -webkit-sticky; /* Safari */
position: sticky;
top: 0;
}
I'm using jQuery for something similar on my app. The following code will add the class of 'scroll-active' to the 'nav' when scrolled 10px, and removes it when there is nothing scrolled.
$(function () {
$(window).on('scroll', function () {
if ( $(window).scrollTop() > 10 ) {
$('nav').addClass('scroll-active');
} else {
$('nav').removeClass('scroll-active',);
}
});
});
I think you can use this and add the necessary css to it on your added class to have it on the right side.
You'll probably need javascript for that, this might work for you if you don't want to use jQuery.
<div id="container">
some content
</div>
and some javascript to define add a class:
window.addEventListener('scroll', function(e) {
container = document.getElementById('container');
// The 0 could be a larger threshold if you want to move it after scrolling a bit
container.classList.toggle('scrolling', window.scrollY > 0);
});
and then define your CSS:
#container {
/* style when not scrolling */
}
#container.scrolling {
/* style when scrolling */
position: fixed;
}
here is a working jsfiddle: https://jsfiddle.net/96xvotpc/2/

TinyMCE color picker dropdown appears off-screen

This is an issue on Firefox and IE so far that I've tested; the problem does not exist on Chrome.
I'm including two TinyMCE editors on a page with one partially off-screen to start. When I select the color picker dropdown option from the toolbar on the first TinyMCE instance, the dropdown appears where it should. But if I scroll down and select the color picker dropdown in the second instance, that dropdown appears way below the editor and typically off the page.
You can see this in action here: http://jsfiddle.net/nm6wtca3/
Without removing the html, body CSS, what can I do to have the color picker always appear in the correct position?
I've traced the problem down to setting CSS on the html, body elements.
html, body {
width: 100%;
height: 100%;
overflow-x: hidden;
}
The dropdown div has CSS applied to it that is auto-calculated by TinyMCE. It looks something like this:
z-index: 65535;
left: 641.467px;
top: 633px;
width: 162px;
height: 105px;
How it appears in FF (sometimes way worse):
How it appears in Chrome (how it should look):
You did say you don't want to remove any CSS from the html,body, but you didn't say anything about adding to it! This solution is based on the assumption that you can add to the html,body
Solution
html, body {
width: 100%;
height: 100%;
overflow-x: hidden;
position: relative; /* Line added */
}
JSFiddle Example
I hope this helps. In all reality, you really only need to apply position: relative; to the body like so body { position: relative; }
I'm not super familiar with tinymce's colorpicker, but I can see the issue, and I can replicate it reliably: your problem occurs when you have a picker open, and then you scroll. I can replicate this in chrome too. Here's a video.
When I look at the DOM, I see that tinyMCE has created two absolute-positioned divs at the end of document.body, one for each picker. When you open one, their position is updated to reflect the location of the toolbar-button at the time you clicked it, but it never gets updated when you scroll!
So, how to solve this? Well, there are a few possibilities:
Option 1: it looks like tinyMCE provides a method to bind a control to an event (here). With this, you could bind a callback to 'scroll' that repositions the box...
Huh, now that I think of it, you could simply close any open colorpickers whenever a user scrolls ... kinda feels like a cop-out but there's no denying it has the best R.O.I. ;) We'll call that Option 2!
Option 3: depending on the implementation of the colorpicker, you may be able to override where in the DOM those divs get rendered. The API method I saw that looked the most promising is here. Once you have the div inside a relative-positioned parent, you'd also have to make the colorpicker's positioning algorithm smart enough to look in the right place for x and y offset ...when I tried this by just moving the element and mashing in some css by hand in chrome-console, the algorithm still computed x and y offsets based on doc.body, so depending on where you were scrolled at click-time, everything would be out of position
It looks like this issue might be troubling other people as well... maybe they've found a solution but haven't posted anything about it?
I hope this is enough info to get you past the problem... Let me know if you have any questions!
It looks like the problem is caused by overflow-x: hidden;
It may not be the answer you want but removing that or moving it to a page wrapper will solve your problem.
Working Example
html, body {
width: 100%;
height: 100%;
padding:0;
margin:0;
}
#pagewrapper{
overflow-x: hidden;
}
Another option would be to force repositioning on scroll, but honestly this is overkill... I strongly recommend fixing the css instead.
Another working example
$('body').scroll(posfix); // when the body scrolls
$('#mceu_10').click(posfix); // when you click the top font color button
$('#mceu_35').click(posfix); // when you click the bottom font color button
function posfix() {
setTimeout(function () { // hack way to ensure it fires after the menu is shown
$('#mceu_51').css({
top: $('#mceu_10').offset().top + $('#mceu_10').height(), // set top/left based on button's position
left: $('#mceu_10').offset().left + $('#mceu_10').width() / 2
});
$('#mceu_52').css({
top: $('#mceu_35').offset().top + $('#mceu_35').height(),
left: $('#mceu_35').offset().left + $('#mceu_35').width() / 2
});
}, 1);
}
it works on firefox, and Internet Explorer fine
just remove this css code
html, body {
width: 100%;
height: 100%;
overflow-x: hidden;
}
Please take a look at this:
html,
body {
width: auto;
height: auto;
overflow-x: hidden;
}
You can simply set body width and height to auto, then there won't be any need to use position and you don't have to remove anything. I think you do not need to use height: 100% since it will be auto-calculated by TinyMCE. i hope it helped.
Update
Look at the screen shot from chrome and its same in firefox. And i didn't remove any css but just changed..and by putting 100% in css the output will be like :-
Please check this one with auto but not 100%..thank you

Navbar Not Switching To Fixed When I Scroll By It

For reference here is the url http://buildme.co/
I am currently having a issue with my main navbar not switching to fixed as you scroll by it. This is the navbar under the skewed images.
The Following JavaScript code is supposed to be making it do this
// Change To Fixed Header
$(document).ready(function(){
$(window).bind('scroll', function() {
var navHeight = $( window ).height() - 100;
if ($(window).scrollTop() > navHeight) {
$('.main-navbar').addClass('navbar-fixed-top');
}
else {
$('.main-navbar').removeClass('navbar-fixed-top');
}
});
});
However this is not the case and nothing happens.
Here is a example of what I am trying to achieve. http://stanislav.it/tutorials/sticky-navigation/
It looks like you may need to bind the scroll event to the 'body' in your case (the window scroll event wasn't firing when I checked it on your site but the body was)
Edit: Oh wait I think I see...It's the overflow styling you've added to html, body:
html, body {
overflow-x: hidden;
height: 100%;
}
if I get rid of the overflow-x: hidden your code works for me. I know I've had trouble before with the fact that it's not allowed to have one axis allow overflow and the other not (so if you set overflow-x: hidden it may do funny things with the y scrolling)

Using scrollTop inside of a fixed element with overflow-y:scroll

I can't seem to get scrolltop to work when my content is inside of a fixed position container that has overflow-y: scroll specified.
Here is my relevant code:
/* some container with many large content blocks inside */
#container {
position: fixed;
width: 300px;
height: 300px;
overflow-y: scroll;
}
/* button that has a data-path attribute that specifies where the container should scroll to*/
$(".button").on("click", function(){
var path = $(this).attr("data-path");
var anchor = $("#" + path);
var position = anchor.position().top;
$("#container").animate({scrollTop: position});
});
I believe this fiddle illustrates my dilemma quite well: http://jsfiddle.net/Qndu5/
If you scroll from the top down to an element, it works great. After that, all bets are off. It is completely incapable of scrolling from any position other than the top. It either horribly misses the mark, or scrolls all the way back to the top, even though the position values being fed to it are seemingly correct.
Surely I'm missing something here, but I'm not sure what I am not understanding. Thanks for any help provided!
What you are missing is the scrollTop when calculating the position, so if the view is already scrolled, that need to be added to the calculation var position = anchor.position().top + $("#container").scrollTop();
http://jsfiddle.net/x36Rm/

Hide iframe scrollbar but allow scrolling [duplicate]

I want to hide any scrollbars from my div elements and my whole body, but still let the user scroll with the mouse wheel or arrow keys. How can this be achieved with raw JavaScript or jQuery? Any ideas?
Like the previous answers, you would use overflow:hidden to disable the scrollbars on the body/div.
Then you'd bind the mousewheel event to a function that would change the scrollTop of the div to emulate scrolling.
For arrow keys, you would bind the keydown event to recognize an arrow key, and then change scrollTop and scrollLeft of the div as appropriate to emulate scrolling.
(Note: you use keydown instead of keypress since IE doesn't recognize keypress for arrow keys.)
Edit: I couldn't get FF/Chrome to recognize keydown on a div, but it works in IE8. Depending on what you needed this for, you can set a keydown listener on the document to scroll the div. (Check out the keyCode reference as an example.)
For example, scrolling with the mouse wheel (using jQuery and a mousewheel plugin):
<div id="example" style="width:300px;height:200px;overflow:hidden">
insert enough text to overflow div here
</div>
<script>
$("#example").bind("mousewheel",function(ev, delta) {
var scrollTop = $(this).scrollTop();
$(this).scrollTop(scrollTop-Math.round(delta));
});
</script>
(This is a quick mockup, you'd have to adjust the numbers since for me, this scrolls a bit slowly.)
keyCode reference
mousewheel plugin
keydown, keypress # quirksmode
Update 12/19/2012:
The updated location of the mousewheel plugin is at: https://github.com/brandonaaron/jquery-mousewheel
What about a purely CSS solution?
Solution 1 (cross browser but more hacky)
#div {
position: fixed;
right: -20px;
left: 20px;
background-color: black;
color: white;
height: 5em;
overflow-y: scroll;
overflow-x: hidden;
}
<html>
<body>
<div id="div">
Scrolling div with hidden scrollbars!<br/>
On overflow, this div will scroll with the mousewheel but scrollbars won't be visible.<br/>
Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>
</div>
</body>
</html>
Solution 2 (uses experimental features, may not support some browsers)
Just add the nobars class to any element you want to hide the scrollbars on.
.nobars {
/* Firefox: https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-width */
scrollbar-width: none;
/* IE: https://msdn.microsoft.com/en-us/library/hh771902(v=vs.85).aspx */
-ms-overflow-style: none;
}
.nobars::-webkit-scrollbar {
/* Chrome/Edge/Opera/Safari: https://css-tricks.com/custom-scrollbars-in-webkit/ */
display: none;
}
Solution 3 (cross browser javascript)
Perfect Scrollbar doesn't require jQuery (although it can utilise jQuery if installed) and has a demo available here. The components can be styled with css such as in the following example:
.ps__rail-y {
display: none !important;
}
Here is a complete example including the implementation of Perfect Scrollbar:
<link rel="stylesheet" href="css/perfect-scrollbar.css">
<style>
#container {
position: relative; /* can be absolute or fixed if required */
height: 200px; /* any value will do */
overflow: auto;
}
.ps__rail-y {
display: none !important;
}
</style>
<script src='dist/perfect-scrollbar.min.js'></script>
<div id="container">
Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>Scrollable<br>
</div>
<script>
// on dom ready...
var container = document.getElementById("container");
var ps = new PerfectScrollbar(container);
//ps.update(container);
//ps.destroy(container);
</script>
You dont have to use jquery or js to make this. Its more performant with simple webkit.
Just add the code below to your css file.
::-webkit-scrollbar {
display: none;
}
Caution !
This will disable all the scrollbar so be sure to put it in a specific class or id if you just want one to be hidden.
I much prefer SamGoody's answer provided to a duplicate of this question. It leaves native scrolling effects intact, instead of trying to manually re-implement for a few particular input devices:
A better solution is to set the target div to overflow:scroll, and wrap it inside a second element that is 8px narrower, who's overflow:hidden.
See the original comment for a fleshed-out example. You may want to use JavaScript to determine the actual size of scrollbars rather than assuming they are always 8px wide as his example does.
To get this working for me, I used this CSS:
html { overflow-y: hidden; }
But I had problems using $(this).scrollTop(), so I bound to my #id, but adjusted the scrollTop of window. Also, my smooth scrolling mouse would fire lots of 1 or -1 deltas, so I multiplied that by 20.
$("#example").bind("mousewheel", function (ev, delta) {
var scrollTop = $(window).scrollTop();
$(window).scrollTop(scrollTop - Math.round(delta * 20));
});
As Baldráni said above
::-webkit-scrollbar { display: none; }
Or you can do
::-webkit-scrollbar{ width: 0px; }
(posted for other people that stumble on this from google search!)
Well, perhaps not the most intuitive in my opinion, but I can imagine you being able to make it a decent experience, give this a try.
overflow:hidden;
make sure the parent object has a height and width, and displays as block

Categories

Resources