I want to draw a line on screen from the top of the page to the bottom when the user scrolls the page and have an arrow at the bottom of it. I don't want to use fixed position so that its always in the same spot, I want it to indicate where they are on the page by determining the page length etc.
I have the following code that works to a point. The problem with this is the arrow disappears off the bottom of the page when I scroll just after half way down.
I have tried different variations of this code but none work. Can anyone help?
//Draw dotted line on scroll - works to certain extent but scrolls off page
$( window ).scroll(function() {
if ( $.windowScrollTop() > 10 ) {
var pos = $.windowScrollTop();
var scrollHeight = $(window).innerHeight();
var element = $('#dashes');
$( '#line' ).css( 'height', pos - scrollHeight / 4 );
$( '#arrow' ).css( 'top', pos - scrollHeight / 4 );
} else {
$( '#line' ).css( 'height', '6px' );
$( '#arrow' ).css( 'top', '-150px' );
}
});
//also tried the below
$(window).on("scroll", function() {
var scrollHeight = $(document).height();
var scrollPosition = $(window).height() + $(window).scrollTop();
if ((scrollHeight - scrollPosition) / scrollHeight === 0) {
// when scroll to bottom of the page
alert('bottom');
} else {
$( '#line' ).css( 'height', $(window).scrollTop() );
$( '#arrow' ).css( 'top', $(window).scrollTop() );
}
});
I want to draw a line on screen from the top of the page to the bottom when the user scrolls the page and have an arrow at the bottom of it. I don't want to use fixed position so that its always in the same spot, I want it to indicate where they are on the page by determining the page length etc.
I have the following code that works to a point. The problem with this is the arrow disappears off the bottom of the page when I scroll just after half way down.
I have tried different variations of this code but none work. Can anyone help?
//Draw dotted line on scroll - works to certain extent but scrolls off page
$( window ).scroll(function() {
if ( $.windowScrollTop() > 10 ) {
var pos = $.windowScrollTop();
var scrollHeight = $(window).innerHeight();
var element = $('#dashes');
$( '#line' ).css( 'height', pos - scrollHeight / 4 );
$( '#arrow' ).css( 'top', pos - scrollHeight / 4 );
} else {
$( '#line' ).css( 'height', '6px' );
$( '#arrow' ).css( 'top', '-150px' );
}
});
//also tried the below
$(window).on("scroll", function() {
var scrollHeight = $(document).height();
var scrollPosition = $(window).height() + $(window).scrollTop();
if ((scrollHeight - scrollPosition) / scrollHeight === 0) {
// when scroll to bottom of the page
alert('bottom');
} else {
$( '#line' ).css( 'height', $(window).scrollTop() );
$( '#arrow' ).css( 'top', $(window).scrollTop() );
}
});
Share
Improve this question
edited Mar 1, 2018 at 16:34
TylerH
21.1k77 gold badges79 silver badges112 bronze badges
asked Feb 27, 2018 at 12:54
LeeTeeLeeTee
6,60118 gold badges85 silver badges142 bronze badges
3
- 1 Check this. stackoverflow./questions/35111425/… – sagar43 Commented Feb 27, 2018 at 12:56
- Ok so this uses $(this).offset(); but not sure how to apply that to my code – LeeTee Commented Feb 27, 2018 at 13:24
- 1 Can you post your markup/css or create a simplified example so we can play around with it – Huangism Commented Mar 1, 2018 at 16:37
3 Answers
Reset to default 7 +50What we are trying to do here is reflect the document height into an element of window height. So the actual scrollable document height will be
var actualScrollHeight = $(document).height() - $(window).height();
/* This is the distance we actually scroll */
And our #line
will have a maximum possible height of
var lineMaxHeight = $(window).height() - topMargin - bottomMargin - arrowHeight;
/* #arrow is inside #line but we positioned it outside it's height */
No to reflect the scroll progress in #line
elements height what we need to do is
var lineHeight = $(document).scrollTop() / actualScrollHeight * lineMaxHeight;
/* Super Easy, isn't it? */
The Final Result:
You don't need to position both the #line
and #arrow
. Fix the #arrow
at the bottom of #line
and then just changing the height of #line
works just fine. I added the topMargin
and bottomMargin
feature making screen adjustment more customizing.
$(function(){
var topMargin = 15, bottomMargin = 5;
var arrowHeight = $('#arrow').height();
var $lineElement = $('#line');
$lineElement.height(topMargin);
$(window).scroll(function() {
var winHeight = $(window).height();
var actualScrollHeight = $(document).height() - winHeight;
var lineMaxHeight = winHeight - topMargin - bottomMargin - arrowHeight;
var scrollTop = $(document).scrollTop();
var lineHeight = scrollTop / actualScrollHeight * lineMaxHeight;
$lineElement.height(topMargin + lineHeight);
});
});
#logo {
width: 80px;
background-color: #53befd;
padding: 20px;
}
#line {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAMCAYAAABBV8wuAAAAFklEQVR42mNgoB74OEXzPzY8sBLUAwB6PmBV1D+CIAAAAABJRU5ErkJggg==);
position: fixed;
top: 0px;
right: 19px;
z-index: 20;
width: 3px;
}
#arrow {
background-color: #f28323;
height: 40px;
width: 40px;
position: absolute;
bottom: -40px;
left: -18px;
border-radius: 20px;
color: white;
text-align: center;
font-size: 32px;
line-height: 35px;
padding-top: 3px;
cursor: pointer;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="logo">LOGO </div>
<p> Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p> Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p> Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p> Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p> Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p> Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p> Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p> Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p> Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p> Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p>
<div id="line"><div id="arrow">V</div></div>
Your approaches look like you're overthinking it. I'm seeing an HTML progress
element turned 180 degrees for the visual. Then, set it's value
attribute dynamically with JS as the user scrolls and the line will essentially look like it's animating down.
// PROGRESS INDICATOR
// Calculate height of main object and the window, set max attr of progress accordingly
var winHeight = $(window).height(),
sectionHeight = $('#line').height(),
progressBar = $('progress'),
max,
value;
// Set the maximum scrollable area
max = sectionHeight - winHeight;
progressBar.attr('max', sectionHeight);
// Set value attr of progress, changes as user scrolls
$(document).on('scroll', function(){
value = $(window).scrollTop();
progressBar.attr('value', value);
});
CSS for the progress element would look something like this, where you place the bar as a fixed element on the page and animate it to cover progressively more of the page with the JS above.
CSS example:
progress {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
background-color: transparent;
border: none; //firefox fix
color: green;
height: 2.5rem;
margin-top: 20vw;
position: fixed;
top: 8rem;
width: 100vh;
@media (min-width: 768px) and (max-width: 1200px) {
display: block;
transform: rotate(90deg) translateY(1800%);
}
@media (min-width: 1200px) {
display: block;
transform: rotate(90deg) translateY(1200%); // matches content shift to smaller column
}
}
I built this on one of my client sites if you want to see if working in the wild (only works at about 1000px and higher so make sure your window is wide enough).
Here is an easier solution with less code:
$(function() {
$(window).scroll(function() {
var p = ($('body').height() - $(window).height()) / ($(window).height() - 43);
var scrollTop = $(document).scrollTop() / p;
$(':root').css('--scroll-top', scrollTop + 43 + "px");
});
});
:root {
--scroll-top: 43px;
}
#logo {
width: 80px;
background-color: #53befd;
padding: 20px;
}
.content {
height: 210vh;
background: red;
margin-right: 50px;
}
#line:before {
content: "V";
background-color: #f28323;
height: 40px;
width: 40px;
display: inline-block;
position: absolute;
right: 0;
bottom: 0;
border-radius: 20px;
color: white;
text-align: center;
font-size: 32px;
line-height: 35px;
padding-top: 3px;
cursor: pointer;
}
#line {
position: fixed;
top: 0;
right: 0;
height: var(--scroll-top);
width: 40px;
background: linear-gradient(to bottom, #f28323 50%, transparent 50%) 50% 0/3px 12px repeat-y;
}
<script src="https://code.jquery./jquery-3.3.1.min.js"></script>
<div id="logo">LOGO </div>
<div class="content"></div>
<div id="line"></div>