div position based on scroll position - javascript

I would like my logo to scroll up and down vertically based on the scroll position on the website.
In exactly the same way a default scroll bar indicates your position on the site, I would like my logo to do the same. When you are at the top of the website page, the logo sits at the top, and when you are at the bottom it will sit at the bottom of the page in a vertical bar on the left hand side of the web page.
I have no idea how to approach this, I have looked at a few plugins but none offer the positioning based on the content and I can't find any other Stack Overflow results that are what I am looking for, though I may not be phrasing the question correctly.
My setup is
.logo-scroll {
position: fixed;
border: 2px solid white;
top: 30px;
left: 30px;
height: calc(100vh - 60px);
width: 75px;
}
.scroll-text {
height: auto;
}
.logo-scroll .scroll-text img {
padding: 0 6px 0 17px;
}
and my html
<div class="logo-scroll">
<div class="scroll-text">
<a href="/home">
<img src="logo.svg"/>
</a>
</div>
</div>
Any help would be greatly appreciated
** Edit - to complicate things, I have a 30px border which is not to be included in the page height. So an offset of 30px on the top and bottom.
The size of the margin/border will need to change responsively at break points - 1 maybe 2, before I will hide it. Essentially the height of the scroll bar will always need to match the height of either the page with margins subtracted or the height of the :before element.
Alternatively if I can set offsets, I can reuse the JS and adjust based on screen size. Like media queries for JS?
You can see the web page here - which is still very under construction https://www.sheree-new.shereewalker.com/

You could give something like this a try.
window.addEventListener('scroll', e => {
const logo = document.querySelector('.scroll-text');
const logoHeight = logo.clientHeight;
const viewHeight = window.innerHeight;
const maxLogoOffset = viewHeight - logoHeight;
const scrollFraction = getElementScrollFraction(document.querySelector('body'));
logo.style.top = maxLogoOffset*scrollFraction;
});
function getElementScrollFraction(elem){
return elem.scrollTop / (elem.scrollHeight - elem.clientHeight);
}
You'll also need to add position:fixed; to the .scroll-text css.
Here is a working example: https://jsbin.com/yuholihece/edit?html,css,js,console,output

Here is my solution.
Edited:
const docHeight = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);
const logo = document.querySelector('.scroll-text');
const logoHeight = logo.offsetHeight;
// to get the pseudoelement's '#page::before' top we use getComputedStyle method
const barTopMargin = parseInt(getComputedStyle(document.querySelector('#page'), '::before').top);
let viewportHeight, barHeight, maxScrollDist, currentScrollPos, scrollFraction;
logo.style.top = barTopMargin + 'px';
window.addEventListener('load', update);
window.addEventListener('resize', setSizes);
document.addEventListener('scroll', update);
setSizes();
function update() {
currentScrollPos = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
scrollFraction = currentScrollPos / (docHeight - viewportHeight);
logo.style.top = barTopMargin + (scrollFraction * maxScrollDist) + 'px';
}
function setSizes() {
viewportHeight = window.innerHeight;
// to get the pseudoelement's '#page::before' height we use getComputedStyle method
barHeight = parseInt(getComputedStyle(document.querySelector('#page'), '::before').height);
maxScrollDist = barHeight - logoHeight;
update();
}
And if I understand correctly, you want #page::before element to have like margins on its top, left, bottom and right. If so, then I think it would be better to use this styling rules:
#page::before {
content: "";
position: fixed;
top: 30px;
bottom: 30px;
left: 30px;
right: 30px;
...
}
When you use position: fixed property (or position: absolute), you can stretch the element's width and height as you want by just setting top - bottom and left - right properties at the same time.
P. S.: And also there is no sense in using display: inline-block, because position: fixed (and position: absolute) automatically sets display to block :)
Hopefully, this helps you!

Related

Move buttons up when scrolling to footer

I'm trying to push up two buttons vertically displayed in order to put them above the footer content when I'm scrolling to it.
My two buttons are like this:
And I want them to be like that:
Any ways to make it with Javascript?
Thanks a lot !
Since you provided no code at all, here's my solution based on the assumption your buttons are in a parent div and that div has position: fixed and a right / bottom -property set to a certain amount of pixel.
window.onscroll = function (ev) {
if ((window.innerHeight + window.pageYOffset) >= document.body.offsetHeight - 2) {
document.getElementById("buttons").style.bottom = "100px";
} else {
document.getElementById("buttons").style.bottom = "20px";
}
}
/*
window.onscroll = function (ev) {
let footerHeight = document.getElementsByTagName("footer")[0].offsetHeight;
if ((window.innerHeight + window.pageYOffset) >= (document.body.offsetHeight - footerHeight)) {
document.getElementById("buttons").style.bottom = "100px";
} else {
document.getElementById("buttons").style.bottom = "20px";
}
}
*/
main {
height: 1000px;
}
#buttons {
position: fixed;
bottom: 20px;
right: 20px;
}
button {
background-color: grey;
border-radius: 50%;
display: block;
border: none;
padding: 15px;
margin-top: 10px;
}
<main></main>
<div id="buttons">
<button></button>
<button></button>
</div>
window.onscroll fires of at every scroll-event. It then checks, if the height of the window (window.innerHeight) and the distance scrolled so far (window.pageYOffset) are greater or equal to the total height of the body (document.body.offsetHeight)(- 2) is added because of an annoying mac-'feature'. For more look at this post). If thats the case, it moves the buttons up 100px instead of the 20px normally. If you dont add the else-statement, your buttons will stay at the position even if you scroll up again.
You can now get a bit creative. If you dont want to hit rock bottom of the page to make the buttons move, change the - 2. So you check for the height of your footer, and substract it from the total body height. Your buttons then start to move once the footer is it. Example of that in the javascript snippet, the part that is commented out.

Is there any way to change a div size on scroll using intersectionObserver?

I'm trying to change the size (or scale) of a div while scrolling.
This div has a .8 scale attached to it css. I'd like to reach a scale of 1 progressively while scrolling.
IntersectionObserver seems to be a good choice to work with instead of scroll event but i don't know if i can change the state of an element using it.
You can change the scale of a div using.
document.getElementById("scaledDiv").style.transform = "scale(1)";
The scroll event should do what you want it to do. You can continue to add more if statements and check how many pixels they are scrolling to change it gradually to 1 or even back to 0.8 when they scroll back up. The 50 below represents 50 pixels from the top of the page.
window.onscroll = function() {
if (document.body.scrollTop > 50 || document.documentElement.scrollTop > 50) {
// They are scrolling past a certain position
document.getElementById("scaledDiv").style.transform = "scale(1)";
} else {
// They are scrolling back
}
};
I hope this will help you:
const container = document.querySelector('.container');
const containerHeight = container.scrollHeight;
const iWillExpand = document.querySelector('.iWillExpand');
container.onscroll = function(e) {
iWillExpand.style.transform = `scale(${0.8 + 0.2 * container.scrollTop / (containerHeight - 300)})`;
};
.container {
height: 300px;
width: 100%;
overflow-y: scroll;
}
.scrollMe {
height: 1500px;
width: 100%;
}
.iWillExpand {
position: fixed;
width: 200px;
height: 200px;
top: 10px;
left: 10px;
background-color: aqua;
transform: scale(0.8);
}
<div class='container'>
<div class='scrollMe' />
<div class='iWillExpand' />
</div>

How to get the height and width of window in bootstrap

In bootstrap I have a fixed top nav bar and fixed bottom nav bar. I want to show a large image in the background between the space of those two nav bars and I also want to cover the width of the window. How can I dynamically get the height between the navbars and the width of the window? The window size may change depending on device.So I need it dynamic
Requires jquery:
var viewport = {
width : $(window).width(),
height : $(window).height()
};
//can access dimensions like this:
//viewport.height
Though you won't always get perfect results, different devices behave differently and this gives the viewport dimensions, not the screen dimensions.
Alternatively you could check the width of a data-role="page" element to find the device-width (since it's set to 100% of the device-width):
var deviceWidth = 0;
$(window).bind('resize', function () {
deviceWidth = $('[data-role="page"]').first().width();
}).trigger('resize');​​​
$(window).resize(function() {
var top_nav_height = $("#id_of_top_nav").height();
var bottom_nav_height = $("#id_of_bottom_nav").height();
var window_height = $(window).height();
var height_of_open_space = window_height - (top_nav_height+bottom_nav_height);
$("#id_of_img").css({
height:height_of_open_space+'px';
});
});
this will be fine with if 0px padding and margin, if not also get that values and subtract from height_of_open_space before applying to img height
It is a bit hard to tell without seeing any of your markup, but it should be feasable with pure css. I set up a very basic example to demonstrate:
http://codepen.io/anon/pen/XbGJJO
HTML:
<div class='top'>
top navbar
</div>
<div class='content'>
<p> some content </p>
</div>
<div class='bottom'>
bottom navbar
</div>
CSS:
.top, .bottom {
height: 40px;
background: red;
position: fixed;
width: 100%;
}
.top {
top: 0;
}
.bottom {
bottom: 0;
}
.content {
margin: 40px 0;
min-height: calc(100vh - 80px);
background: green; /* background goes here */
}
The trick lies in the following line:
min-height: calc(100vh - 80px);
This tells your content to at least take up 100% of the vertical height, minus the height of the top and bottom bar. Let me know if you want me to explain further.

CSS to keep background video centred

I've got a background video playing on a web page, and this CSS;
#video_background {
position: fixed;
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
top: 0px;
left: 0px;
z-index: -1000;
overflow: hidden;
}
..is keeping it centered, like I want it to, but it's keeping all of the edges within the browser window, rather than always being full-bleed. I'm trying to replicate what this site is doing;
http://marisapassos.com/#home
This site appears to have two sets of rules, one on a div that contains the video, and one on the video itself. Could someone explain to me why that works and what I'm doing doesn't? Is there also js working to keep the video on the linked site centered?
Yes, look at the video_background.js in the source of the website you linked to, specifically at the $(window).resize function:
$(window).resize(function() {
var windowWidth = $(window).width();
var windowHeight = $(window).height();
var width;
var height;
//size
width = windowWidth;
height = width*formH/formW;
if(height<windowHeight){
height = windowHeight;
width = formW*height/formH;
}
$div_holder.css("width", width);
$div_holder.css("height", height);
$div_holder.css("left", windowWidth/2-width/2);
$div_holder.css("top", windowHeight/2-height/2);
});
Left and top are defined in terms of both the windowWidth and (video) width which keeps the video centered.

How to keep a floating div centered on window resize (jQuery/CSS)

Is there a way (without binding to the window.resize event) to force a floating DIV to re-center itself when the browser window is resized?
To help explain, I imagine the pseudocode would look something like:
div.left = 50% - (div.width / 2)
div.top = 50% - (div.height / 2)
UPDATE
My query having been answered below, I wanted to post the final outcome of my quest - a jQuery extension method allowing you to center any block element - hope it helps someone else too.
jQuery.fn.center = function() {
var container = $(window);
var top = -this.height() / 2;
var left = -this.width() / 2;
return this.css('position', 'absolute').css({ 'margin-left': left + 'px', 'margin-top': top + 'px', 'left': '50%', 'top': '50%' });
}
Usage:
$('#mydiv').center();
This is easy to do with CSS if you have a fixed-size div:
.keepcentered {
position: absolute;
left: 50%; /* Start with top left in the center */
top: 50%;
width: 200px; /* The fixed width... */
height: 100px; /* ...and height */
margin-left: -100px; /* Shift over half the width */
margin-top: -50px; /* Shift up half the height */
border: 1px solid black; /* Just for demo */
}
The problem, of course, is that fixed-size elements aren't ideal.
The simplest way would be with the following CSS code:
#floating-div {
width: 50%;
border: 1px solid gray;
margin: 0 auto;
}
The key line of CSS code above is the "margin: 0 auto;" which tells the browser to automatically set the left/right margins to keep the div centered on the page, even when you resize the browser window.
Try this little article about Horizontal and Vertical centering. It is a little old and has a few hacks but you should be able to work out some test code from it.

Categories