Custom scrollbars thumb goes out of bounds - javascript

I am trying to create a thumb scroller that scrolls together with the default scroller (with animation). I wan finally able to implement it, be the only problem is, the custom scroller doesn't scroll at the exact position. If you scroll all the way down, the thumb scroller goes past its parent element.
Also, the thumb scroller is larger than the default scroller. Here's the math:
scrollBarThumb.style.height = (innerWrapper.parentElement.offsetHeight * innerWrapper.parentElement.offsetHeight / innerWrapper.scrollHeight) + 'px';
scrollBarPosition = clamp(scrollBarPosition, 0, scrolledToBottom)
scrollBarPosition = scrollBar.offsetHeight * scrollBarPosition / innerWrapper.scrollHeight;
The formulas I used are the accepted formulas for custom scrollers.
The two problems are: (they may be one issue, because I think if the height gets fixed, then the scrolling position will automatically get fixed as well.) First, the scrollers thumb is larger than the default. Second, the scrollers thumb goes past its parent when you scroll all the way down.
What am I doing wrong, and how can I fix it?
JSFiddle
console.clear();
var innerWrapper = document.getElementById('innerWrapper');
var scrollBar = document.getElementById('scrollbar');
var scrollBarThumb = scrollBar.firstElementChild
scrollBarThumb.style.height = (innerWrapper.parentElement.offsetHeight * innerWrapper.parentElement.offsetHeight / innerWrapper.scrollHeight) + 'px';
innerWrapper.addEventListener('mousewheel', handleScroll);
innerWrapper.addEventListener('DOMMouseScroll', handleScroll);
var duration = 35,
scrollSpeed = 2,
animateAmount = 30;
var scrolledToBottom = 0,
scrollDirection = 0, // 1 = scroll down, -1 = scroll up
animationID;
function handleScroll(e) {
// Cancel previous animation
cancelAnimationFrame(animationID);
// Scroll faster
scrollSpeed += 2;
// Reason for negative `-.wheelDelta` because Firefox
// return oposite value. See http://phrogz.net/js/wheeldelta.html
// Get 1 or -1
var delta = Math.max(-1, Math.min(1, (-e.wheelDelta || e.detail)));
// Check if scroll direction changed
if (scrollDirection != delta) {
scrollSpeed = 2; // Start slowly - restart speed
scrollDirection = delta;
}
var start = innerWrapper.parentElement.scrollTop,
end = start + animateAmount * scrollSpeed * delta, // Where to end the scroll
change = end - start, // base change in one scroll
step = 0, // current step in animation
tempScrollPosition; // Cannot assign any number yet (i.e. 0), because `scrollPosition` may be 0.
// Get amount of scrolled to bottom
scrolledToBottom = innerWrapper.scrollHeight - innerWrapper.parentElement.offsetHeight;
animationID = requestAnimationFrame(smoothScrollAnim); // Start animation
function smoothScrollAnim() {
animationID = requestAnimationFrame(smoothScrollAnim); // Restart animation
// Get scroll position
var scrollBarPosition = easeOut(step++, start, change, duration);
scrollBarPosition = clamp(scrollBarPosition, 0, scrolledToBottom)
scrollBarPosition = scrollBar.offsetHeight * scrollBarPosition / innerWrapper.scrollHeight;
// Apply scroll movement
scrollBarThumb.style.top = scrollBarPosition + 'px';
// Check if scroll finished (either animation finished, or bumped to top or bottom)
if (step >= duration || tempScrollPosition === scrollBarPosition) {
// Clean up
tempScrollPosition = null;
scrollSpeed = 2;
cancelAnimationFrame(animationID);
} else {
tempScrollPosition = scrollBarPosition;
}
}
}
function easeOut(time, begin, change, duration) {
time /= duration;
return -change * time * (time - 2) + begin;
}
function clamp(val, min, max) {
if (typeof min !== 'number') min = 0;
if (typeof max !== 'number') max = 1;
return Math.min(Math.max(val, min), max);
}
html {
height: 100%;
overflow-y: hidden;
}
body {
height: 100%;
overflow-y: hidden;
display: flex;
}
#outerWrapper {
height: 400px;
overflow: auto;
background-color: black;
}
#content {
background-image: url("http://images.freeimages.com/images/premium/previews/3037/30376024-beautiful-flower-portrait.jpg");
width: 400px;
}
#scrollbar {
height: 400px;
width: 50px;
background-color: orange;
border: 2px solid green;
}
#scrollbar_thumb {
background-color: yellow;
border: 2px solid blue;
position: relative;
}
<div id="outerWrapper">
<div id="innerWrapper">
<div id="content">
Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero
sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus
Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus
enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar
justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames
ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque
Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem
lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie
vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum
vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque
Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci
Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla.
Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet
consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet
risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat
Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor
dolor
</div>
</div>
</div>
<div id="scrollbar">
<div id="scrollbar_thumb"></div>
</div>

For the scroll simply register the "scroll" event,
For the catching-delay effect use CSS3 transition
For the simple math involved see the example below:
const el = (sel, par) => (par || document).querySelector(sel);
const
elContent = el("#content"),
elHandler = el("#handler");
// FROM ELEMENT SCROLL TO HANDLER POSITION
const moveScrollbar = () => {
const
height = elContent.clientHeight,
scrollHeight = elContent.scrollHeight,
handlerHeight = height ** 2 / scrollHeight,
handlerTop = elContent.scrollTop / height * handlerHeight;
Object.assign(elHandler.style, {
height: `${handlerHeight}px`,
top: `${handlerTop}px`
});
}
moveScrollbar(); // At init
elContent.addEventListener("scroll", moveScrollbar); // and on scroll
* { margin: 0; box-sizing: border-box; }
#area {
display: flex;
}
#content {
height: 160px;
width: 300px;
font-size: 3rem;
background: #eee;
padding: 1rem;
}
#content {
overflow-y: scroll;
scrollbar-width: none;
-ms-overflow-style: none;
}
#content::-webkit-scrollbar {
width: 0;
height: 0;
}
#scrollbar {
flex: none;
position: relative;
background: #333;
width: 1rem;
}
#handler {
position: absolute;
top: 0;
background: orange;
width: 100%;
transition: 0.2s; /* smooth move */
}
<div id="area">
<div id="content">
Scroll and see the custom scrollbar move.<br>Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis.
</div>
<div id="scrollbar">
<div id="handler"></div>
</div>
</div>
Then, to make the handler draggable, here's the formula:
// FROM HANDLER POSITION TO ELEMENT SCROLL:
const
height = elContent.clientHeight,
scrollHeight = elContent.scrollHeight,
scrollPos = scrollHeight / height * elHandler.clientTop;

Related

Hide Header on Scroll Down After a Certain Point?

I have this code, used from https://www.w3schools.com/howto/howto_js_navbar_hide_scroll.asp
I'm wondering if it's possible to amend this so that the header only disappears on scroll after a certain height says 120px from the top of the page. Here's the code I have currently:
var prevScrollpos = window.pageYOffset;
window.onscroll = function() {
var currentScrollPos = window.pageYOffset;
if (prevScrollpos > currentScrollPos) {
document.getElementById("navbar").style.top = "0";
} else {
document.getElementById("navbar").style.top = "-50px";
}
prevScrollpos = currentScrollPos;
}
#navbar {
background-color: #333; /* Black background color */
position: fixed; /* Make it stick/fixed */
top: 0; /* Stay on top */
width: 100%; /* Full width */
transition: top 0.3s; /* Transition effect when sliding down (and up) */
}
/* Style the navbar links */
#navbar a {
float: left;
display: block;
color: white;
text-align: center;
padding: 15px;
text-decoration: none;
}
#navbar a:hover {
background-color: #ddd;
color: black;
}
section {
background-color: grey;
margin-top: 50px;
}
<div id="navbar">
Home
News
Contact
</div>
<section>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean accumsan tincidunt massa in tristique. Vestibulum mattis erat sed porttitor cursus. Praesent dignissim, sem vel tincidunt venenatis, dolor orci sollicitudin ipsum, et vestibulum mauris ex non felis. Cras pulvinar lectus eu risus lobortis malesuada. Sed accumsan metus quis ante scelerisque molestie. Maecenas molestie arcu in massa egestas tempus. Vestibulum augue purus, tincidunt ut porta quis, pulvinar imperdiet neque. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque id convallis odio.
Sed fringilla rutrum nulla. Nam diam ex, gravida at nisl vel, feugiat vehicula ex. Duis et ligula vitae velit pretium finibus quis sit amet diam. Sed ac interdum magna, a pharetra ante. Quisque vestibulum luctus ligula, elementum aliquam sem molestie non. Maecenas auctor magna a magna hendrerit, ornare facilisis tortor finibus. Nulla eu augue leo. Donec euismod scelerisque porttitor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vehicula sit amet nisi eu porttitor. Donec dictum quis erat ut tincidunt. Curabitur pharetra iaculis purus. In hac habitasse platea dictumst. Aenean egestas laoreet lorem, ac eleifend magna.
Sed quis feugiat diam. Nunc euismod dapibus mauris quis egestas. Nam venenatis magna sit amet lorem semper, eget sagittis dolor malesuada. Sed fringilla pulvinar maximus. In venenatis ligula magna, id pulvinar magna auctor condimentum. Aliquam dictum erat sit amet elit tristique feugiat. Curabitur feugiat nunc ultricies sapien finibus condimentum. Duis gravida, ipsum sit amet luctus vulputate, odio quam ornare sapien, non aliquam enim metus eget dolor. Duis nisl lorem, tempor non cursus nec, lobortis vel nibh. Suspendisse consectetur sed nisl in vestibulum. Nunc at placerat ante. Donec ante massa, mollis vel ultricies sed, ullamcorper at risus. Morbi euismod laoreet sagittis.</section>
Currently, the header disappears as soon as you start scrolling down, but I'd like it to stay visible until after you've scrolled past the height of the header.
Hopefully, that makes sense.
You can just check when the scroll position is greater than 120 and then make it disappear, revert it back when it's less than 120
window.onscroll = function() {
var currentScrollPos = window.pageYOffset;
if (currentScrollPos > 120) {
document.getElementById("navbar").style.top = "-50px";
} else {
document.getElementById("navbar").style.top = "0px";
}
}

How can i make my fixed header scroll away when a specific div hits it, or when it is 100px from the top

I can see lots of ways to do the opposite of what i am trying to achieve but noting for what I need.
I have a fixed header that is 100px tall. I want it to scroll away with the rest of the page when a specified div hits the header or it is 100px from the top of the screen.
I had was adding a scroll class to the header which was literally just making it position absolute, causing the header to jump of screen. I then translateY'd it back into view, this didn't work the same across all screen sizes.
My next idea is maybe keeping it fixed but adding a negative transformY to the header, dependent on scroll position. This would achieve the same effect I am going for but i'm not too sure how to achieve this.
If you need any more information then i am happy to provide it.
edit:
Here are some screen shots:
from the top of the page:
Then this is where i want the header to become un-fixed and scroll with the rest of the page:
Check out my solution. Hope this helps.
const headerEl = document.querySelector('header')
const targetEl = document.querySelector('#target')
const targetTopPos = targetEl.getBoundingClientRect().top
let isHeaderFixed = true
document.onscroll = () => {
const targetTopOffset = targetEl.getBoundingClientRect().top
if (isHeaderFixed && targetTopOffset < 100) {
headerEl.style.position = 'absolute'
headerEl.style.top = `${targetTopPos - 100}px`
isHeaderFixed = !isHeaderFixed
}
if (!isHeaderFixed && targetTopOffset >= 100) {
headerEl.style.position = 'fixed'
headerEl.style.top = '0px'
isHeaderFixed = !isHeaderFixed
}
}
body {
padding: 0;
margin: 0;
position: relative;
}
header {
position: fixed;
height: 100px;
width: 100%;
background: lightblue;
}
.content {
line-height: 100px;
}
.target {
width: 100%;
background: red;
}
<header>
Custom header
</header>
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam suscipit tellus urna, ut tristique felis lobortis sed. Phasellus maximus at magna mattis vulputate. Pellentesque tempor, urna vitae congue pellentesque, est mauris faucibus nulla, vitae molestie leo purus a leo. Curabitur ut mi ac sem finibus consectetur a blandit massa. Morbi ornare tincidunt ipsum, et accumsan erat fringilla a. Cras egestas, nibh vel condimentum ultrices, nunc ipsum tempus magna, eu ullamcorper tortor magna id lacus. Morbi euismod lacus a ligula rutrum, in aliquet lectus blandit. Nam placerat sollicitudin lectus eu ornare. Etiam placerat diam eget magna blandit rutrum. Nulla et luctus massa. Sed sit amet mauris in magna tincidunt consequat. Proin mattis sit amet arcu a gravida. Nullam tempor urna nec dolor convallis consectetur sit amet a elit. Cras ut odio nec lacus efficitur porta nec sit amet justo.
</div>
<div id="target" class="target">target</div>
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam suscipit tellus urna, ut tristique felis lobortis sed. Phasellus maximus at magna mattis vulputate. Pellentesque tempor, urna vitae congue pellentesque, est mauris faucibus nulla, vitae molestie leo purus a leo. Curabitur ut mi ac sem finibus consectetur a blandit massa. Morbi ornare tincidunt ipsum, et accumsan erat fringilla a. Cras egestas, nibh vel condimentum ultrices, nunc ipsum tempus magna, eu ullamcorper tortor magna id lacus. Morbi euismod lacus a ligula rutrum, in aliquet lectus blandit. Nam placerat sollicitudin lectus eu ornare. Etiam placerat diam eget magna blandit rutrum. Nulla et luctus massa. Sed sit amet mauris in magna tincidunt consequat. Proin mattis sit amet arcu a gravida. Nullam tempor urna nec dolor convallis consectetur sit amet a elit. Cras ut odio nec lacus efficitur porta nec sit amet justo.
</div>
I should by default make .header {position: absolute} and add this class to css (not to element yet):
.header.active {
position: fixed;
top: 0;
left: 0;
width: 100%;
}
Then understand when we need to carry this event on header. JS will help:
var targetElement = document.querySelector( YOUR TARGET ELEMENT ),
header = document.querySelector('.header');
window.onscroll = function(event){
if ( targetElement.offsetTop > window.pageYOffset ) {
header.classList.add('active');
} else {
header.classList.remove('active');
}
}
Target element is element which when you want to reach it, header will be fixed.
If you need

Div goes past its parent element [duplicate]

This question already has an answer here:
Why do child divs extend beyond their parent div?
(1 answer)
Closed 6 years ago.
I'm trying to create a custom scroller, and I'm using translate3d to scroll. The only problem is, when you scroll all the way to the bottom, the thumb (scroller) goes too far down. I'm using the accepted formula, but for some reason, it goes past its parent wrapper. Here's the formula:
scrollPosition * scrollBarThumb_height / content_height
What am I doing wrong, and how can I get the thumb to fully stay in its parents view?
JSFiddle
console.clear();
var innerWrapper = document.getElementById('innerWrapper');
var scrollBar = document.getElementById('scrollbar');
var scrollBarThumb = scrollBar.firstElementChild
scrollBarThumb.style.height = (innerWrapper.offsetHeight * innerWrapper.offsetHeight / innerWrapper.scrollHeight) + 'px';
innerWrapper.addEventListener('mousewheel', handleScroll);
innerWrapper.addEventListener('DOMMouseScroll', handleScroll);
innerWrapper.style.transform = 'translate3d(0px, 0px, 0px)';
function handleScroll(e) {
// Prevent parents from scrolling
e.preventDefault();
var direction = (e.detail < 0 || e.wheelDelta > 0) ? 1 : -1; // 1 = scroll down, -1 = scroll
var start = parseInt(innerWrapper.style.transform.split(',')[1], 10);
var scrollPosition = start + direction * 100; // Cannot use `deltaY`, because not all browsers support it.
var scrolledToBottom = innerWrapper.scrollHeight - innerWrapper.parentElement.offsetHeight;
scrollPosition = clamp(scrollPosition, -scrolledToBottom, 0);
innerWrapper.style.transform = 'translate3d(0px, ' + scrollPosition + 'px, 0px)';
scrollBarThumb.style.top = -(scrollPosition * scrollBarThumb.offsetHeight / innerWrapper.parentElement.offsetHeight) + 'px'
}
function clamp(val, min, max) {
if (typeof min !== 'number') min = 0;
if (typeof max !== 'number') max = 1;
return Math.min(Math.max(val, min), max);
}
#outerWrapper {
height: 400px;
overflow: hidden;
display: flex;
}
#content {
background-image: url("http://images.freeimages.com/images/premium/previews/3037/30376024-beautiful-flower-portrait.jpg");
width: 400px;
}
#scrollbar {
height: 100%;
width: 50px;
background-color: orange;
}
#scrollbar_thumb {
background-color: yellow;
border: 2px solid blue;
position: relative;
}
<div id="outerWrapper">
<div id="innerWrapper">
<div id="content">
Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero
sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus
Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus
enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar
justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames
ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque
Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem
lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie
vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum
vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque
Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci
Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla.
Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet
consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum
vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque
Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor
</div>
</div>
<div id="scrollbar">
<div id="scrollbar_thumb"></div>
</div>
</div>
The borders were not calculated properly into the total element's height, thus creating the problem.
Simply add box-sizing: border-box; to solve the issue:
#scrollbar_thumb {
...
box-sizing: border-box;
}
working JSFiddle fork: https://jsfiddle.net/azizn/9nfns6kk/

How to create reusable function with alternating if statements

I am creating a smooth scrolling and a bounce (at top and bottom) effect. (After a full day of trial and error,) I was able to successfully implement it. I'm now having trouble finding a method to have reusable clean code. (I think that's called an algorithm?)
The specific problem I'm having, is alternating between <= and >=. The code overall can use some clean up, which I did to the best of my ability, but I think it needs some more (let me know if it doesn't).
So in reusable function, like this:
function reusableFunction() {
...
if (num1 >= num2) // One case I have to compare like this
if (num1 <= num2) // Another case, I have to compare like this
...
}
I got stuck at line #86 in the function bounceBack. If you have a better way of making the smooth scrolling, and bouncing effect, please post as an answer. I don't want to use any librarys, or other frameworks (like JQuery).
JSFiddle
console.clear();
var innerWrapper = document.getElementById('innerWrapper');
innerWrapper.addEventListener('mousewheel', handleScroll);
innerWrapper.style.transform = 'translate3d(0px, 0px, 0px)';
var interval, // scroll is being eased
mult = 0, // how fast do we scroll
dir = 0, // 1 = scroll down, -1 = scroll up
steps = 50, // how many steps in animation
length = 30; // how long to animate
var bouncePadding = 30;
function handleScroll(e) {
e.preventDefault();
clearInterval(interval); // cancel previous animation
++mult; // we are going to scroll faster
var delta = -Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
if (dir != delta) { // scroll direction changed
mult = 1; // start slowly
dir = delta;
}
var start = parseInt(innerWrapper.style.transform.split(',')[1], 10); // Get x from translate3d
var end = start + length * mult * delta; // where to end the scroll
var change = end - start; // base change in one step
var step = 0; // current step
var scrolledToBottom = innerWrapper.scrollHeight - innerWrapper.parentElement.offsetHeight;
var tempVar;
interval = setInterval(function() {
var scrollPosition = easeOut(step++, start, -change, steps);
scrollPosition = clamp(scrollPosition, -scrolledToBottom - bouncePadding, 0 + bouncePadding);
innerWrapper.style.transform = 'translate3d(0px, ' + scrollPosition + 'px, 0px)';
if (tempVar === scrollPosition) {
step = steps;
} else {
tempVar = scrollPosition
}
if (step >= steps) { // scroll finished without speed up - stop by easing out
endScrollCallback();
if (scrollPosition > 0 && dir === -1) {
step = 0;
var myInterval = setInterval(function() {
var scrollPos = easeOut(step++, scrollPosition, -scrollPosition, 15);
innerWrapper.style.transform = 'translate3d(0px, ' + (scrollPos) + 'px, 0px)';
if (scrollPos <= 0) {
clearInterval(myInterval);
innerWrapper.style.transform = 'translate3d(0px, ' + (0) + 'px, 0px)';
}
}, 10);
} else if (scrollPosition < -scrolledToBottom && dir === 1) {
step = 0;
var myInterval = setInterval(function() {
var change = -scrolledToBottom - scrollPosition;
var scrollPos = easeOut(step++, scrollPosition, change, 15);
innerWrapper.style.transform = 'translate3d(0px, ' + (scrollPos) + 'px, 0px)';
if (scrollPos >= -scrolledToBottom) {
clearInterval(myInterval);
innerWrapper.style.transform = 'translate3d(0px, ' + (-scrolledToBottom) + 'px, 0px)';
}
}, 10);
}
}
}, 10);
}
function easeOut(t, b, c, d) {
t /= d;
return -c * t * (t - 2) + b;
}
function endScrollCallback() {
mult = 0;
clearInterval(interval);
}
function bounceBack(from, to, difference) {
var step = 0;
var interval = setInterval(function() {
var scrollPos = outQuartic(step++, from, difference, 15);
innerWrapper.style.transform = 'translate3d(0px, ' + (scrollPos) + 'px, 0px)';
if (scrollPos <= 0) { /* Got stuck here */
clearInterval(interval);
innerWrapper.style.transform = 'translate3d(0px, ' + to + 'px, 0px)';
}
}, 10);
}
function clamp(val, min, max) {
if (typeof min !== 'number') min = 0;
if (typeof max !== 'number') max = 1;
return Math.min(Math.max(val, min), max);
}
body {} #outerWrapper {
width: 500px;
height: 400px;
overflow: hidden;
background-color: black;
}
#content {
background-image: url("http://images.freeimages.com/images/premium/previews/3037/30376024-beautiful-flower-portrait.jpg");
}
<div id="outerWrapper">
<div id="innerWrapper">
<div id="content">
Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero
sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus
Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus
enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar
justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames
ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque
Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem
lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie
vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum
vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque
Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci
Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla.
Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet
consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet
risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat
Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor
dolor
</div>
</div>
</div>
Generally, to customize a function, which is what <= is, one can use a function. If you'd like customize a statement like:
if (a <someFunction> b){
// ...
}
where someFunction in your case can be either <= or >, one way to do it could be:
function f(a,b,conditionsMet){
return conditionsMet ? a <= b : a > b;
}
and then call it:
if ( f(a,b,are conditions met?) ){
// ...
}
(Not sure if that's what you mean, feel free to comment..)

dynamically change value on resize and window scroll

I have a fixed header function like below. I would like to change dynamically "100" value while window resizing.
I was trying to wrap everything in sth like "if (screen.width >= 1200)" or "jQuery(window).on('resize', function ()" but this kind of stuff is working only with page refresh.
jQuery(document).ready(function($) {
var $window = $(window),
$stickyEl = $('.tabsmenu > ul'),
elTop = $stickyEl.offset().top - 100;
$window.scroll(function() {
if ($window.scrollTop() < 900) {
$stickyEl.toggleClass('sticky', $window.scrollTop() > elTop);
} else {
$stickyEl.removeClass('sticky');
}
});
});
Any tips?
This may not be perfect but it's what I think what you want to do and the way I would do it. This just gets the scroll value and then does some math to calculate how much it needs to change. I have added a bunch of content to let it scroll.
window.onload = function() {
$("#everything").scroll(function() {
var startAt = 40; //How many pixles scrolled to start effect, 0 would match link
if ($("#everything").scrollTop() >= startAt) {
var scroll = $("#everything").scrollTop(),
total = 0, // go to this value
distance = 40, //distance to shrink
value = (scroll < distance) ? total : total + (distance - (scroll - startAt));
$("#head").css("height", value); //change #head to what ever you want to shrink
} else {
$("#head").css("background-color", value);
}
});
}
html,
body {
overflow: hidden;
/* Disables regular scrolling */
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#everything {
overflow: scroll;
/* enables content to scroll */
position: relative;
width: 100%;
height: 100%;
padding-top: 40px;
}
#head {
width: 100%;
height: 40px;
background-color: red;
position: fixed;
top: 0px;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<div id="everything">
<div id="head">header</div>
<span>
Text Following text is so the page can scroll: <br/>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer porta velit eu turpis imperdiet congue. Morbi nec mi ipsum. Nam eu nunc in lorem sagittis feugiat a quis nisl. Donec suscipit leo quis magna egestas, id convallis leo gravida. Curabitur finibus lectus ut metus feugiat, eu tincidunt eros tempor. Fusce facilisis nunc vulputate, posuere velit nec, ultrices diam. Vestibulum aliquam velit in lectus imperdiet, vitae condimentum lectus finibus. Aliquam ac arcu eget velit molestie rhoncus. Etiam rhoncus, tellus nec lacinia porta, diam lorem ultrices sem, et dignissim ipsum augue non augue. Suspendisse tincidunt felis sit amet orci accumsan, at ornare tellus viverra. Nam viverra nulla in urna elementum ornare.Sed interdum nisi libero, id porta turpis consectetur vitae. Curabitur nunc ex, interdum eget hendrerit maximus, faucibus non est. Etiam scelerisque condimentum eleifend. Integer ac ligula eget magna porta tristique at eu neque. Sed venenatis ipsum non metus sodales finibus. Suspendisse nec nunc lobortis ligula venenatis tristique. Suspendisse aliquam leo elit, et pretium ipsum tempor sed. Maecenas tincidunt dictum leo sit amet accumsan. Nullam eu viverra nulla. Aenean vehicula tellus a mauris malesuada interdum. Sed libero lacus, consectetur at condimentum vel, egestas vitae nisl.Mauris facilisis tincidunt magna, at gravida elit. Cras molestie eros sed tincidunt ultricies. Pellentesque eleifend egestas orci, sit amet condimentum nisl semper eleifend. Sed ipsum elit, aliquet nec lacinia a, maximus eu dolor. Quisque finibus efficitur odio gravida convallis. Vivamus nec velit in est ornare luctus at a risus. In hac habitasse platea dictumst. Proin condimentum eget est non posuere. Vivamus ante quam, bibendum in tincidunt ut, egestas sed mauris. Nunc non interdum nibh, nec ornare tellus. In interdum elit nisi, a interdum est tempor id. Cras a elit ut purus ornare mollis sit amet ut est. Cras ut ex sed neque lacinia accumsan quis aliquet turpis. Quisque nisl nunc, pretium sed lectus pretium, lacinia ornare magna. Curabitur sit amet felis turpis. Morbi nisi mi, mattis quis tempor ut, accumsan nec ex.
</span>
</div>
</body>
</html>

Categories

Resources