There is the following code:
<div id="main">
<div id="first">
First item
</div>
<div id="second">
Second item
</div>
<div id="third">
Third item
</div>
</div>
CSS styles:
#first {
background-color: yellow;
}
#second {
background-color: blue;
}
#third {
background-color: green;
}
html, body, #main, #first, #second, #third {
height: 100%;
}
There are 3 div in main div and user scrolls in order to go to the bottom of the screen. I want to do the following thing: when user scrolls with mousewheel the first time he goes to "second" div, the second time - "third" div. This feature has been realized on the following site: some site. Please, tell me some advice. Thanks.
Living demo: http://jsfiddle.net/xz2DN/1/
Update for IE: http://jsfiddle.net/xz2DN/6/
(html element is scrolled, as the body contains the css property overflow:hidden which makes it impossible to scroll for IE)
You need to:
Disable the scrolling bar on the site
Detect the mousewheel event (not working in old browsers)
Have knowledge of which section are you in before scrolling up or down
Update that status once you move from one to another section
You could try to look for each of this points by separate and you will get it working :)
Disabling scrolling bar and default scrolling
body,html{
overflow:hidden;
}
Detecting mouse wheel:
http://www.sitepoint.com/html5-javascript-mouse-wheel/
Having knowledge of which section are we in
I would recommend you to create an array with a pair of values id, status. The id would be the id tag of the current section and the status would indicate you if is the current "slide"/section or not.
You could do something like this:
var sections = {};
var numberSections = 0;
$('.section').each(function(index, element){
//current slide is active
if(!index){
sections[$(this).attr('id')] = 1;
}
else{
sections[$(this).attr('id')] = 0;
}
numberSections++;
});
And then you should define two functions, one to move update the status of the array when the user scrolls up, and the other for the case in which they scroll down.
Related
I would like to know how do I execute a javascript function when reaching the end of the div via the overflow scroll. My case is as follows, I want that when the user sees all the posts arranged in such a div, reaching the end of everything, load more content through ajax, and this is the function that I want to run when scrolling down.
Try this, which shows an alert box once you scroll to the bottom (and disappears once you scroll back up):
$('.watch-scroll').on('scroll', function(e){
var t = $(this);
if(t[0].scrollHeight - t.scrollTop() - t.outerHeight() < 1){
$('.alert').show();
}else{
$('.alert').hide();
}
})
.watch-scroll {
height: 100px;
width:500px;
overflow: auto;
border:1px solid black;
}
.placeholder{
height:300px;
}
.alert{
width:300px;
padding:1em;
color:white;
background-color:#ff5c5c;
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="watch-scroll">
<div class="placeholder"></div>
</div>
<div class="alert">You have scrolled to the bottom</div>
Adding a scroll event like the previous answer will work, but if you want the best performance possible, you should use IntersectionObserver.
<div class="container">
<div class="scrollable">
... All Visible Content Here ...
<div class="scroll-bottom"></div>
</div>
</div>
In this example, make the .scroll-bottom of non-zero height and at the very bottom, and use Javascript to attach an IntersectionObserver on it. Then wait till it intersects with container and you'll know it's scrolled into view which means you've scrolled to the bottom.
You can use something similar for page scrolling, but you can simply detect intersection with the viewport.
You can read up about IntersectionObserver further since it's not entirely trivial to implement.
Of course, if performance is not important, you can just use a scroll listener as suggested by the other answer.
I'm working on a site that has all of its pages basically "slide" around on the main landing page. So you basically start on a div with an ID of "main" that also has a class of "currentpage." If you click a nav menu item, the content slides away, and the next page's content slides into place. This new content's primary div would have a new id (let's say #about), and now the "currentpage" class is added to this div as well.
The thing is, the body tag has a background-image attached to it (it used to have a full screen video, but I set that to hide, and then there's this bg image behind it). I'd like to change the background image depending on which "page" you are on. At first, I set it up so that #about had a background-image set up, and so forth for the rest of the page IDs. The thing about this is that the content of the primary div is padded a whole bunch, so you would see the specified #about background image, but then you'd actually also still see that original image from the body tag behind it.
Thus, I'd like to change the actual body tag's background image property depending on which ID you're on.
I figured some means of checking if you're on a specified ID, as well as if the class for that div is set to "currentpage" would be step 1, with step 2 then changing the background image if that condition is true.
Here is what I have tried so far, to no avail:
Attempt 1:
if ($this.is('#about')) {
$('.bgimage').css({"background":"url(imageurlhere)"});
}
This didn't do anything.
Next, I found this old SO thread and tried to modify it just to see it in action to know if I was on the right path. Here's what I used:
Attempt 2:
if ($("#about").hasClass("currentpage")) {
$('#about').css({"background-color":"red"});
}
Unfortunately, this also didn't cause anything differently) when I went to About.
And yes, I had cleared cache out each time, and manually even went to the JS file to ensure it had the new code blocks each time.
Edit
Here is the basic page format:
<body class="video">
<div class="preload">Whole lot of stuff in here for a preload overlay</div>
<nav>Nav is here</nav>
<main>
<div id="pt-main" class="pt-perspective ">
<div class="page-1 currentpage" id="main"></div>
<div class="page-2" id="about"></div>
<div class="page-3" id="services"></div>
<div class="page-4" id="portfolio"></div>
<div class="page-5" id="contact"></div>
</div>
</main>
The "currentpage" class will go to a different div if the corresponding link in the nav is clicked. So, click About in the nav, currentpage class drops from #main and ends up in same div as #about
And then the CSS for the body tag is as follows:
.video {
background: url(../img/video_bg.jpg);
background-size: cover;
}
I basically want to make it so that background (image) of .video changes when you end up on #about, #services, #portfolio, etc.
TL;DR
Can anyone help me with this code block? How do I check if an div with a specific ID also has a class, and then modify the .bgimage CSS to change its background?
Edit 2:
I came up with a workaround for this. Here's what I did:
1) I set the overall background color to #000, removed the original bg-image altogether, and actually restored a full-screen video I'd previously hid
2) I edited each nav menu item to have a hidevid class, except for the Home link, which I made showvid
3) I created CSS for each "page" ID (ie #about {background-image: url(image);}
4) I created a new CSS class: .hidethis {display: none;}
5) I then implemented the following jquery:
$(document).ready(function(){
$(".hidevid").click(function(){
$("video").addClass("hidethis");
});
$(".showvid").click(function(){
$("video").removeClass("hidethis");
});
});
What this does is set the background to black, but that's not seen on the landing ("home") page, just the video. However, clicking a nav menu item will "slide" the next "page" into view, displaying its background image and changing the video to have a display: none property, basically hiding it and the extra content (the nav) just has a black background behind it.
Using vanilla JavaScript (pure JavaScript), you can check if a div has a particular class name and based on the results, change the css by doing this:
var x = document.getElementById('about');
var y = document.querySelector('.bgimage');
if (x.classList.contains('currentpage')){ // if #about has "currentpage" class, run the following
x.style.background = 'red'; //change background-color of #about to red
y.style.background = 'url(imageurlhere)'; // change background-image of .bgimage
}
jsFiddle: http://jsfiddle.net/AndrewL64/nqjypevh/10/
your codes is wrong. true usage is this.
css('background-color','red')
I came up with a workaround for this. Here's what I did:
1) I set the overall background color to #000, removed the original bg-image altogether, and actually restored a full-screen video I'd previously hid
2) I edited each nav menu item to have a hidevid class, except for the Home link, which I made showvid
3) I created CSS for each "page" ID (ie #about {background-image: url(image);}
4) I created a new CSS class: .hidethis {display: none;}
5) I then implemented the following jquery:
$(document).ready(function(){
$(".hidevid").click(function(){
$("video").addClass("hidethis");
});
$(".showvid").click(function(){
$("video").removeClass("hidethis");
});
});
What this does is set the background to black, but that's not seen on the landing ("home") page, just the video. However, clicking a nav menu item will "slide" the next "page" into view, displaying its background image and changing the video to have a display: none property, basically hiding it and the extra content (the nav) just has a black background behind it.
I’m making a whole lot of assumptions and guesses. You only showed one css class. From the description it sounds like the problem is actually using CSS to cover the background, and that if it weren’t for that, there would be no need to change the class on the body. The basic solution, move the initial background from the body to the #main div, move the padding to the .page-1, .page-2 etc. divs. Also, if the background images are transparent also give a background-color.
I’m assuming the nav does not have a background image and stays put. I’m also assuming you already have the sliding of the sections in place, I didn’t show that but instead just a simple display none/block just to keep it simple. I also didn’t show the js (but you shouldn’t need to change the body class.) I also left the html alone.
body {
margin: 0;
height: 100%;
}
nav {
height: 50px;
background-color: #ccc;
}
main {
background-image: url(https://picsum.photos/200/300?image=0);
background-size: cover;
}
.pt-perspective > div {
height: calc(100vh - 50px);
padding: 50px;
background-repeat: no-repeat;
background-color: aqua;
background-size: cover;
background-image: url(https://picsum.photos/200/300?image=0);
display: none; /* or positioned off screen, wherever you already have it */
}
.pt-perspective .currentpage {
display: block;
}
.pt-perspective .page-1 {
background-image: url(https://picsum.photos/800?image=1);
}
.pt-perspective .page-2 {
background-image: url(https://picsum.photos/800?image=2);
}
.pt-perspective .page-3 {
background-image: url(https://picsum.photos/800?image3);
}
.pt-perspective .page-4 {
background-image: url(https://picsum.photos/800?image=4);
}
.pt-perspective .page-5 {
background-image: url(https://picsum.photos/600?image=5);
}
<body class="video">
<!-- <div class="preload">Whole lot of stuff in here for a preload overlay</div> -->
<nav>Nav is here</nav>
<main>
<div id="pt-main" class="pt-perspective ">
<div class="page-1 currentpage" id="main"></div>
<div class="page-2" id="about"></div>
<div class="page-3" id="services"></div>
<div class="page-4" id="portfolio"></div>
<div class="page-5" id="contact"></div>
</div>
</main>
Modern browsers seem to have a feature where the viewport sticks to bottom when page height increases. What actually happens is that browser scrolls the viewport at the same rate as height being increased when initial position is at (or very close to) the bottom of the page. This results in appearance as if page is expanding upwards instead of downwards.
How can this feature be disabled for a certain page using CSS or JS, so that the page would always visually expand downwards?
This of course, also happens when added element's height is expanded animated. For this reason, if possible, I would want to avoid resetting scroll position afterwards to prevent visible jump. The demo of this "feature" (that seems to happen only within rare conditions) interacting with the viewport and drop animation can be observed in the gif below.
I know there must be a way, otherwise every site with infinite scroll would suffer from an infinite loop. Counter argument: Chrome appears not to do this for containers that surpass certain height limit. So maybe infinite-scroll sites don't even bother addressing this in their sites.
Check this fiddle. You can observe that in Chrome, the first container snaps to the bottom, while the other divs has a scroll relative to the top. In Firefox or IE 11, you cannot observe this behavior.
This happens when the top bound of the last element on a scroll container is above the top bound of the container. The browser decides that the last element is what the user is interested in and decides to stay in that position.
The last div doesn't snap to the bottom because the scroll happens relative to the top bound of the last element and the last element is growing.
If you want a different behavior, I would not suggest handling it with Javascript, but I would suggest changing your layout considering these rules. For example the last div should be the growing one, instead of the previous siblings of it.
Obligatory code:
var div = document.querySelectorAll('.growing');
var height = 500;
setInterval(function(){
height += 100;
div[0].style.height = height + 'px';
div[1].style.height = height + 'px';
div[2].style.height = height + 'px';
},1000);
.start, .end{
height: 110px;
}
.start{
background: red;
}
.end{
background: green;
}
.growing{
background: yellow;
}
.cnt1,.cnt2,.cnt3{
overflow: auto;
border: 5px solid black;
margin: 5px 0;
scroll-snap-type: mandatory;
}
.cnt1{
height: 100px;
}
.cnt2{
height: 120px;
}
.cnt3{
height: 100px;
}
<div class="cnt1">
<div class="start"></div>
<div class="growing"></div>
<div class="end"></div>
</div>
<div class="cnt2">
<div class="start"></div>
<div class="growing"></div>
<div class="end"></div>
</div>
<div class="cnt3">
<div class="start"></div>
<div class="end"></div>
<div class="growing">
Content
</div>
</div>
Edit:
If the bounds of the growing div is in the visible area, the scroll is relative to the top of the growing div. So you can hack CSS to show the growing div, but actually not show it.
In this fiddle I have used two different CSS hacks. First one is adding a negative margin bottom and a positive padding bottom at same amount. The second hack is adding an :after element to the growing div but hide its visibility.
for click events, use blur, avoid scrollTo
It seems like this issue is focus-related. I came across a similar bug and when the element that triggered a height change was switched to an unfocusable element, like a div, the screen jumping disappeared. This clearly isn't a great solution because we should be able to use buttons! It also implicates focus in this strange behavior. Further experimentation led to blurring the trigger element before the height change, which solves the problem without moving the viewport. I've only tried this with click events so I'm not sure if it works for drag n drop.
codepen that showcases viewport jumping with accordions and a blur fix
function handleClick(e) {
e.currentTarget.blur();
// code to change height
}
Do you mean that when you scroll to the bottom, and a piece of content gets added, you stay at the bottom? Because the solution for that is real simple:
Option 1
Store the current scrolloffset to the top (eg how many px you've scrolled down)
Add new content
Set scrolloffset to the top to the stored value
Those last two steps can be done so fast that the user wont notice.
Option 2
Not 100% sure this works, but i'm guessing it does:
When the visitor scroll to the bottom, always scroll them back 3px. This way, they're not at the bottom at the point where new content gets added, so the browser stays where it is.
As per my understanding regarding your requirement, I have given a working jsfiddle sample.
Hope it would help to you.
If you expect something more, feel free to add comment.
Cool!
$(function(){
var height = 200;
var pos = 0;
setInterval(function(){
if($(document).height() >= $(window).height()){
var height = $('.container1').height();
$('.container1').height(height + 20);
pos = pos + 20;
$(window).scrollTop(pos);
}
}, 1000);
});
.container1 {
border: 1px solid #ccc;
min-height: 200px;
background: #ccc;
height: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container1">
<p>11</p>
<p>12</p>
<p>13</p>
</div>
All of your draggable elements are in a container with no auto overflow, when you drag and drop your elements the whole page scrolls due to dragging.
Instead of that do as:
<div class="container">
<!-- Place all your draggable elements here -->
</div>
set a max-height and overflow of the container class as:
.container {
max-height: 400px;
overflow: auto;
}
Now when you drag and drop your elements, instead of the whole page, the only container will scroll.
After implementing this solution, it will look like this.
Before dragging.
While dragging.
Hope this helps you.
Take the following example:
https://jsfiddle.net/atg5m6ym/5079/
Here, you have to scroll down a bit to see the message "Hello!". I also animated a div to move down beyond the screen:
$("div").animate({top: '3000px'}, 6000);
You can see how the scrollbar changes and we now have a much larger page to scroll through.
Now, I want users to be able to scroll down to the "Hello!" text, if the text is beyond the user's screen. However, I don't want the div to extend the vertical scrollbar once it reaches the bottom of the screen. Rather, I want the div to continue moving down beyond the screen, with the scroll bar remaining unchanged. This way, the scrollbar could not follow it.
Doing "overflow-y: hidden" would prevent users from scrolling downwards on their own choice and reading the "Hello!" Is there anything I can do to accomplish both of these using JS (preferably jQuery) or CSS?
EDIT: I still want the div to exist, so I don't want to fade it out. If I had a div that returns afterward or travels in an elliptical orbit, I would like it to still reappear when it reenters the screen, but not to affect the scrollbar.
This will make div travel to whatever the Y position of the paragraph is, and after that gets faded out:
$(document).ready(function() {
var p_pos = $("p").offset().top;
$("div").animate({top: p_pos}, 6000).fadeOut();
});
Alright, try the following:
<div id="everything">
<div id="orb"></div>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br>
<p>
Hello!
</p>
</div>
And in your css:
#everything {
display: inline-block;
position: relative;
width: 100%;
height: 800px;
max-height: 800px;
overflow-y: hidden;
background-color: #ccc;
}
Make sure to animate $("#orb") instead of just $("div") (and rename it in your css.
There you go. Just add to the body and set the div position to
body {
overflow: hidden
}
div {
bottom: 0;
}
https://jsfiddle.net/atg5m6ym/5082/
I have a simple blog page - a list of posts that each consist of a title and contents. When the page loads I want all posts' contents hidden until their titles are clicked. The following code accomplishes this but with an unwanted side effect - the on-page-load hide() function that hides each post's content also hides the background of the containing (id="content") div:
Relevant JavaScripts:
$(document).ready(function() {
$(".blog_post p").hide();
//BLOG CONTENT ANIMATION
$('.blog_post').click(function() {
$(this).find('p').slideToggle(130);
});
});
Summary of blog page:
<section class="grid_7">
<div id="content">
<div class="blog_post">
<div class="blog_head">
<h2>Title</h2>
</div>
<p>Contents</p>
</div>
</div>
</section>
Relevant CSS:
section {
border: 1px solid white;
}
#content {
margin: 20px;
background-image:url('../images/content_background.jpg');
}
When the page loads the list of titles displays without the #content parent div's background. However when I click on a post's title the #content div's background shows up behind all posts up to and including that one.
Any idea what's going on?
It sound like you have some CSS that applies to the blog_head elements, that makes them float, for example:
.blog_post { float: left; }
In that case, the reason that the background doesn't show up is that the height of the content div is zero. A floating element doesn't affect the size of its parent, and when the content div only contains the headers, the height becomes zero. The background is still there, but there is no area where it's visible.
Add an overflow to the content div, that will make it contain its children:
#content { overflow: hidden; }
Note that this will not hide anything as long as you don't specify a size for the content element, it will just change how it's rendered so that it will become a container for its children.
A bit of a stab in the dark: Your #content div will, of course, be a lot shorter as the blog posts aren't there, basically consisting just of the divs with the titles. Perhaps that's the problem.
Does the image have a blank (or subtle) bit at the top or something, so that it's only apparent that it's there when there's more content in the #content div (e.g., when it's taller)? Or is there some other reason you can see that when #content is really short, you wouldn't see the background on the part of it that's there? (You can use the debugging tools in most modern browsers to see what the dimensions of the #content div are when the paragraphs are hidden; or slap a border on it temporarily, but tools these days are pretty good.)
Basically, since the jQuery doesn't, of course, actually hide the background, it must be a side-effect of the paragraphs being hidden — because of the effect that has on the dimensions of the #content div.
This is working fine for me:
HTML:
<div class="blog_post">
<div class="blog_head">
<h2>Title</h2>
</div>
<p>Contents</p>
</div>
</div>
CSS:
section {
border: 1px solid white;
}
#content {
margin: 20px;
background-image:url('http://bluebackground.com/__oneclick_uploads/2008/04/blue_background_03.jpg');
}
JS
$(document).ready(function() {
$(".blog_post p").hide();
//BLOG CONTENT ANIMATION
$('.blog_post').click(function() {
$(this).find('p').slideToggle(130);
});
});
Check it live here: Jsfiddle example