IntersectionObserver - run only when above a certain screen width - javascript

if ( ('IntersectionObserver' in window) && (!document.documentElement.classList.contains('dont-sticky')) ) {
var body = document.body
const sentinel = document.getElementById('sentinel')
const stickyEl = document.querySelector('.test')
const stickyClass = "sticky"
const handler = (entries) => {
if (stickyEl) {
if (!entries[0].isIntersecting) {
body.classList.add(stickyClass);
return false;
} else {
body.classList.remove(stickyClass);
return false;
}
}
}
const observer = new window.IntersectionObserver(handler)
observer.observe(sentinel)
}
body { height: 4000px; background: white; }
body.sticky { background: #FFC; }
.test { width: 100%; height :100px; top: auto; position: relative; background: #FCF; }
body.sticky .test { top: -1px; position: sticky; background: #F6F; }
<p>text text text</p>
<p>text text text</p>
<p>text text text</p>
<div id="sentinel"></div>
<div class="test"></div>
I am playing with IntersectionObserver to add a class to the body element when the .test item is position:sticky.
Ideally I would like the stickyClass to only be added to the body element when the screen width is greater than 1000px wide, including allowing for browser window resizing when viewing the page.
I know I can write css media queries to neutralize the sticky related changes when 999px width or under - but I am interested to know if it's possible and also how best to implement a 1000px minimum window width with the IntersectionObserver script. I am interested to see various ways to do it.
One option I found was window.innerWidth, which works well in the first page load but does not take into account browser width resizing.
window.innerWidth >= 1000
//used like so in the top line of the script
if ( ('IntersectionObserver' in window) && (window.innerWidth >= 1000) && (!document.documentElement.classList.contains('dont-sticky')) ) {
In searching the web I can see a new option called ResizeObserver and also something called Match. I am unsure if these are the current way to do it and also how to implement these with my IntersectionObserver script.
Greatly appreciate any help.
(confirming that I am an absolute rookie at javascript)
Many thanks.

Related

How to have an element change its color during a scroll event and then revert back to its original color?

I am trying to make the footer of a website im creating change color DURING scrolling and revert back to its original color after the scroll is done.
Is there any way to detect when a scroll event ends?
I am looking for answers in vanilla js. Or if there are any specific recoomendation available in for example jQuery im more than willing to look into it per your kind suggestion.
So you're probably looking for scroll event handeler here
And to check if you're done scrolling to the bottom, you need to check if the scroll height is left or not? This might help with that!
Using code I got from detecting when a visitor has stopped scrolling I derived this:
// Setup isScrolling variable
var isScrolling;
// Listen for scroll events
window.addEventListener('scroll', function ( event ) {
// Clear our timeout throughout the scroll
window.clearTimeout( isScrolling );
// Set a timeout to run after scrolling ends
isScrolling = setTimeout(function() {
// Run the callback
if(document.querySelector('#mydiv').style.background=='red')
document.querySelector('#mydiv').style.background='blue';
else if(document.querySelector('#mydiv').style.background=='blue')
document.querySelector('#mydiv').style.background='yellow'
else
document.querySelector('#mydiv').style.background='red'
}, 66);
}, false);
div{
width:100%;
height:400vh;
}
<body>
<h1>scroll down this(document should change colour when you stop:</h1>
<div id="mydiv"></div>
</body>
You just set a timeout to wait until the user is done scrolling. If the user continues to scroll the timeout is cleared and reset before it activates(meaning the code won't run until he stops).
You can get the window height and the height of your footer element and check the scroll pageYOffset in relation to the window height => window.innerHeight and the footers top position in relation to the viewport => footer.getBoundingClientRect().top.
Use a set of conditionals to check the scroll position. Set it anywhere you'd like for the initial color change, I used the initial window.innerHeight to start the BG color change.
For the bg-color change, I use a class and add it to the body with classList.add('bgColor'). Then we further check if the pageYOffset is greater than the window.innerHeight - footer.getBoundingClientRect().top, meaning the footer will just be breaking the bottom fold of the page and coming into view, if this happens we remove the class that adds the bg-color and return the document to its initial bg-color.
const height = 3000;
document.documentElement.style.setProperty("--height", `${height}px`)
const display = document.getElementById('display')
const footer = document.querySelector('.footer')
const rect = footer.getBoundingClientRect()
const screenHeight = window.innerHeight
function setBgOnScroll(e) {
let offset = window.pageYOffset
display.textContent = `scroll offset: ${offset} footer top position: ${rect.top - screenHeight}`
offset > screenHeight ?
document.body.classList.add('bgColor') : document.body.classList.remove('bgColor')
offset > rect.top - screenHeight ?
document.body.classList.remove('bgColor') : null
}
window.addEventListener('scroll',setBgOnScroll)
:root {
--body-bg-color: white;
}
body {
background-color: var(--body-bg-color);
transition: background-color ease-in-out 500ms;
}
.cont {
height: var(--height);
}
#display {
position: fixed;
top: 20px;
right: 220px;
}
.footer {
position: absolute;
top: calc(3000px - 100px);
left: 0;
width: 100%;
background-color: green;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.bgColor {
background-color: lightblue;
transition: background-color ease-in-out 500ms;
}
<div class="cont">
<div id="display"></div>
Page content, scroll down...
<div class="footer">Footer</div>
</div>
While you can react to the scroll event with Javascript you'll need to define some timings to decide when the user has stopped scrolling.
As you can't sense a 'not-scrolling' event this will have to be with something like a setTimeout.
<style>
div {
height: 300vh;
}
footer {
position: fixed;
bottom: 0;
width: 100vw;
height: 20vh;
background-color: magenta;
}
</style>
<body>
<div>scroll down</div>
<footer>Footer</footer>
<script>
let timeout = false;
const footer = document.querySelector('footer');
document.addEventListener('scroll', function () {
if (timeout) {clearTimeout(timeout); timeout = false;}
footer.style.backgroundColor = 'blue';
timeout = setTimeout( function () {
footer.style.backgroundColor = 'red';
}, 1000);
});
</script>
</body>

Chat box scroll down new messages

I want that when the user opens that chat or writes any message, the scroll bar to go down to see the latest messages. I have found the following answer that I want to use in order to accomplish the task.
https://stackoverflow.com/a/21067431/12051965
The problem is that it does not have any effect on the scroll bar, it is still at the top of the chatbox, and I would appreciate if someone could tell me what am I doing wrong.
let chat = document.getElementById("chat-messages-main-div-id");
window.onload = toBottom;
function toBottom() {
const isScrolledToBottom = chat.scrollHeight - chat.clientHeight <= chat.scrollTop + 1;
if (isScrolledToBottom) {
chat.scrollTop = chat.scrollHeight - chat.clientHeight;
}
}
.chat-messages-main-div {
width: 100%;
height: inherit;
overflow: overlay;
overflow-y: scroll;
display: flex;
flex-direction: column;
padding-left: 2%;
padding-right: 2%;
box-sizing: border-box;
padding-bottom: 15px;
}
<div id="chat-messages-main-div-id" class="chat-messages-main-div" onload="toBottom">
....
</div>
There is two issues with your code snippet the first one comes from the height: inherit, which make your div grow with parent element, so the scroll bar you are seeing is a parent node (the first fixed height parent if any or the window object) scrollbar and not the chat one, the div or its parent have to be limited in height for it to work, also your comparaison in the toBottom function should be a >= instead of <= (The scrollTop property is the number of pixel scrolled from the top), but i recommend you something easier (you dont need to check or calculate the position if its given that all you need to is to go to the upmost bottom of the scroll) :
function toBottom() {
chat.scroll(0, chat.scrollHeight)
}

How to make my text appearing while scrolling website

How can I make my text appear when scrolling? I've found this http://www.jqueryrain.com/?HZtLD8hN but I'd like to know how it works. There was a similar question asked but I don't understand it. Can someone explain, or provide examples, how to make this work?
Thanks
HTML
<div id = "divToShowHide" class = "BeforeScroll">Content i want to appear while scrolling</div>
CSS
.BeforeScroll {
width: 100%;
height: 200px;
background-color: yellow;
}
.AfterScroll {
width: 100%;
height: 200px;
background-color: red;
}
A basic example is this: say some of your content is in a<div id="appearble_text"> that is at 70% of the total height of the page. <div id="container">
Initially you will set document.getElementById("appearable_text").style.display = "none";
You can set up a function
function OnScroll() {
var totalHeight = this.offsetHeight; //(this, because container is the caller of the function from the code below)
if (this.scrollTop || this.scrollTop > totalHeight * 0.7) { //if scrolling reached 70% of height
document.getElementById("appearable_text").style.display = "block";
}
}
and then use it
var container = document.getElementById("container");
container.onscroll = OnScroll;
Of course, instead of just suddenly displaying the <div> you can fade it in or do all sorts of CSS/JQuery tricks you like.

how to stop header from scrolling at some point and make it fixed

I have a header, in which i put my h1 and h2 headings at top. The problem is that header scrolls along the scroll bar which is of course normal but i want to fixed it at some point when all the headings on header scroll away. At this point I want header to stop and stays fixed.
I already tried fixed position but of course it fixed heading as well which exactly I don't want.
I also tried this JavaScript but no luck.
JavaScript
$(window).scroll(function() {
var _height = 120 - (120 * $(this).scrollTop() / $('body').height());
if (_height >= 80) {
$('.header_container').height(_height);
}
});
and here qre my HTML and CSS codes respectively.
HTML
<div class="header_container" id="header_container">
<div id="header_titles">
<h1 class="homepage-heading">Browse</h1>
<h2 class="homepage-heading-subtle">GENRES & MOODS</h2>
</div>
</div>
CSS
#header_container {
background-color: black;
width: 100%;
height: 120px;
top: 0;
left: 0;
right: 0;
}
#header_titles {
position: absolute;
width: 100%;
font-size: 35px;
text-align: center;
padding-top: 10px;
}
So, let me see if I get this...you want your header to be scrolled normally with the page until a certain point where it becomes fixed?
EDIT
Ok, well, you could determine the element on the page that you want the position to be triggered at. Like, the top of a certain paragraph, and use that position in your condition.
var condition = $(element).offset().top;
if($(window).scrollTop > condition) { //add a fixedClassName } else { remove the fixedClassName }
and have header.fixedClassName have those proprieties ( with position fix, top 0 and width: 100% to your header etc). Be sure to add and remove a class on the body that gives it padding-top with the height of your displaced header.
Used some similar effect here http://goodmen.se/ after a point the logo shows up in the header, then there's a background change. You do something similar with your position.
EDIT 2
Here's an example fiddle http://jsfiddle.net/Corsico/vpskd8hd/
So you want a sticky header?
In your javascript create a code:
var $header_container = $('#header_container');
var header_height = $header_container.outerHeight(true);
if($(window).scrollTop() < header_height){
$header_container.removeClass('sticky');
} else{
$header_container.addClass('sticky');
}
$(window).on('scroll', function(){
if($(window).scrollTop()< header_height){
$header_container.removeClass('sticky');
} else{
$header_container.addClass('sticky');
}
});
This will add a sticky class to your header, and then you can set the header to be fixed:
.sticky{
position:fixed;
top:0;
left:0;
width:100%;
display:block;
}
This should do it. When you scroll pass the height of the header, you'll get the 'sticky' class, if not, you'll remove the sticky class...

How can I create a div which resizes with a window?

I would like to create a div using css that resizes with the window.
Example:
#container
{
margin: 3em;
}
#header {
height: 100px;
}
#main {
}
#footer {
height: 100px;
bottom: 0px;
}
container
header
main
footer
So when I resize the window, I want main to resize with the window while header and footer staty 100px;
Is there a way to do it using CSS or I will have to use Javascript?
html, body, #container, #main{
width:100%;
height:100%;
}
#container
{
margin: 3em;
position:relative;
}
#header {
height: 100px;
position:absolute;
z-index:1;
}
#main {
position:absolute;
top:0;
left:0;
}
#footer {
position:absolute;
height: 100px;
bottom: 0px;
z-index:1;
}
html
body
container
header
main
footer
The above code should give you what you are looking for a #main will cover the whole screen while your 100px tall header and footer sit over the top of it. I'm using this code on my website right now http://patrickarlt.com.
The footer and header site on top of a div that fills the whole screen. You might also want to listen to the resize event to resize items in #main as a user resizes their screen.
This isn't IE 6 safe however, but my site works in IE 7 and 8 last I checked.
Using JavaScript you can alter your divs on page load. See this article for the details:
dynamically resizing divs
I've done similar, but use JavaScript to do it for me as well. It's not the most elegant JS but it works. I used this when I had a div that needed to be maximum size, and it had a side bar, top and bottom bar etc. So when the browser window was resized I had to quickly adjust the container div (which was a map).
You want your markup to look like (I think you have this already):
<div id="container">
<div id="title">Title</div>
<div id="main"></div>
<div id="footer></div>
</div>
Script:
var browserWidth = 0;
var browserHeight = 0;
function getSize() {
if( typeof( window.innerWidth ) == 'number' )
{
//Non-IE
isIE = false;
browserWidth = window.innerWidth;
browserHeight = window.innerHeight;
} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
//IE 6+ in 'standards compliant mode'
browserWidth = document.documentElement.clientWidth;
browserHeight = document.documentElement.clientHeight;
} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
//They're not running IE7 / FireFox2. Older browser. Find some technology
//to destroy their computer so they're forced to upgrade.
browserWidth = document.body.clientWidth;
browserHeight = document.body.clientHeight;
}
}
function updateMapSize() {
//IE7 is 21 pixels LESS than FireFox.
//Pretty much we want to keep the map to the maximum size alloted.
getSize();
//top section
var height = browserHeight - 200;
document.getElementById("main").style.height = height;
document.getElementById("container").style.height = browserHeight ;
document.getElementById("container").style.width= browserWidth ;
setTimeout("updateMapSize()", 250);
}
You don't need Javascript, use CSS code as below:
#header {
height: 100px;
max-height:100px;
}
# main {
}
# footer {
height: 100px;
max-height:100px;
bottom: 0px;
}

Categories

Resources