What steps should I take to create a functional image scrolling effect similar to the one shown in this example?

Recently, I came across and was intrigued by the "image slide effect" featured on their homepage.

The way the background image changes as you scroll up, leading you through different introductory slides before reaching the main content of the site caught my attention.

Out of curiosity and a desire to learn more about responsive web design, I attempted to replicate this effect. However, I've hit a roadblock and am unsure if my current approach is the best solution.

You can see how far I've gotten in this JSFiddle where I tried to recreate the image slider.

$(window).bind('mousewheel DOMMouseScroll', function(event){
  if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) {
    console.log('scrolling down');
  }
  else {
    console.log('scrolling up');
    $('.s1').slideUp('slow');
  }
});
* { margin: 0; padding: 0 }

#menubar {
  width: 100%;
  background-color: orange;
  height: 60px;
}

.slide {
  position: absolute;
  width: 100%;
  top: 60px;
  bottom: 0;
}
.slide.s1 { background-color: green; }
.slide.s2 { background-color: red; }
.slide.s3 { background-color: cornflowerblue; }

.l1 { z-index: 3; }
.l2 { z-index: 2; }
.l3 { z-index: 1; }
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>

<html>
  <body>
    <header id="menubar"><p>hi im a header</p></header>
    <section class="slide s1 l1"><p>im the first</p></section>
    <section class="slide s2 l2"><p>im the second</p></section>
    <section class="slide s3 l3"><p>im the third</p></section>
  </body>
  </html>

I initially set up three .slide containers stacked on top of each other within the viewport, utilizing z-index hierarchy and jQuery's .slideUp() function to animate the topmost container's movement.

However, I'm uncertain if this method is ideal, especially when it comes to selecting the correct container to fade out.

Is there a simpler and possibly more modular approach to achieve this effect? Are there effective jQuery/CSS selectors to determine the currently visible topmost .slide layer?

Answer №1

To achieve the desired effect, you can preview it on JSFiddle: https://jsfiddle.net/d1xzc4jf/7/

Below is the jQuery code snippet relevant to this effect:

$(window).bind('mousewheel DOMMouseScroll', function(event){
if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) 
  {
    console.log('scrolling down');
    if ($('.s2').is(':visible')) { $('.s3').slideDown('slow'); }
    else if ($('.s1').is(':visible')) { $('.s2').slideDown('slow'); }
  }
  else 
  {
    console.log('scrolling up');
    if ($('.s3').is(':visible')) { $('.s3').slideUp('slow'); }
    else if ($('.s2').is(':visible')) { $('.s2').slideUp('slow'); }        
  }
});

One way to approach this issue is to have all divs initially hidden with their display property set to none, showing only the currently active one. This strategy ensures that an element is hidden after completing the slide-up animation using jQuery's slideUp function. You can then determine which div is visible and toggle its visibility while displaying the next one in your preferred method.

UPDATE:

The reason for the double-slideUp behavior during rapid scrolling, as opposed to double-slideDown, is due to how the visible property gets updated at different points: beginning of slideDown and end of slideUp.

To prevent the unintended double-slideUp when hard-scrolling, utilize a variable to indicate ongoing animations and employ callback functions to reset the variable once the animation concludes. Here's the implementation:

Add the following script at the bottom of your page:

<script> var isbusy = 0; </script>

Then replace your scroll function with this optimized version:

$(window).bind('mousewheel DOMMouseScroll', function(event){
if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) {
    console.log('scrolling up');
    if ($('.s2').is(':visible')) { 
        if (isbusy == 0) 
        {
            isbusy = 1;
            $('.s3').slideDown('slow', function() {
                isbusy = 0;
            })                
        }
    } 
    else 
    {            
        if ($('.s1').is(':visible')) 
        { 
            if (isbusy == 0)
            {
                isbusy = 1;
                $('.s2').slideDown('slow', function(){
                    isbusy = 0;
                });
            }
        }           
    }
}
else 
{
    console.log('scrolling down');
    if ($('.s3').is(':visible')) 
    {
        if (isbusy == 0) 
        {
            isbusy = 1;
            $('.s3').slideUp('slow', function(){
                isbusy = 0;
            }); 
        }
    }
    else if ($('.s2').is(':visible')) 
    {
        if (isbusy == 0)
        {
            isbusy = 1;
            $('.s2').slideUp('slow', function(){
                isbusy = 0;
            });
        }
    }
  }
});

This refined code ensures that the isbusy flag is reset to zero only after the animation completes via the callback functions, allowing the script to proceed without interruption.

Answer №2

It seems like you are interested in the slider provided below.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What could be causing the 'margin-top' property not to function as expected?

Although I understand the concept of 'margin-collapse', I am puzzled as to why there is no visible 10 px margin on the top of the first box here. The top box, which has the id 'first', should have a 10px margin above it. If this method ...

The error is popping up as I try to deploy my Next.js application on Vercel

warning " > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7d0f181c1e095009120d5011121c1914131a501f1c0f3d4f534c534d">[email protected]</a>" has an incorrect peer dependency "react@^16 || ^17" ...

How come when I applied height:100% and position: absolute to .test2, it ended up being 200px instead of the expected 204px

Upon setting the height of a container element to 200px, I encountered an issue when trying to set the height of another element within it to 100%. The height didn't render as expected, as height:100% takes the height of the parent element, which was ...

How can I match all routes in Express except for '/'?

I've been working on implementing an authentication system for my app that involves checking cookies. My approach was to use router.all('*') to handle every request, verify the cookie, and then proceed to the actual handler. However, I encou ...

CSS selector targeting an element based on the value of its table border

Is there a way to target a table on a webpage using a CSS selector? The table structure looks like this: <table border="1" width="560" cellspacing="0"> <tr> <td height="28" colspan="3" bgcolor="#FFFFF...> </tr> </table ...

Ways to verify if the user has inputted a typeahed value

My code snippet looks like this: var students = new Bloodhound({ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('fullName'), queryTokenizer: Bloodhound.tokenizers.whitespace, remote: { ...

IE9 presents a frustrating issue where the jQuery select box value is returning as

I've been battling a bug for over 2 hours now. My javascript code is supposed to generate a two-level select box for tasks and subtasks from JSON data. However, I recently discovered that this code doesn't function properly on IE9, and possibly ...

The TextBox will alter its color following an incorrect submission

I am struggling to create a bootstrap form that will change the color of the borders to red after incorrect submission. The issue I am facing is that the textbox always remains in red. Does anyone have any suggestions for setting the textbox borders to red ...

Unable to update a single object within an array using the spread operator

I am currently working on updating an object within an array and have encountered some issues. In my initial code, I successfully updated a specific property of the object inside the array like this: var equipment = this.equipments.find((e) => e.id === ...

Preventing empty submissions through contact form validation

While I'm not well-versed in php/js, I'm currently attempting to create a custom contact form within Wordpress. After following various tutorials and researching extensively, I have successfully configured the form to send its contents to my emai ...

Attempting to dynamically link my "ng-true-value" in AngularJS

Working with values retrieved from a database, my goal is to include a checkbox, load the description, and provide 2 text boxes – one editable and the other read-only. Both text boxes initially display values from the database. When the checkbox is chec ...

Slider handle for Material UI in React component reaches the range value

In my application, I am using a range slider component from material-UI. The main page displays a data table with the fields: id, name, current price, new price. The current price for each item is fixed, but the new price will be determined based on the s ...

Displaying both input fields and buttons side by side on mobile devices using Bootstrap

I am in the process of creating a navbar that includes select, input, and button elements. Below is the code I have written: <nav class="navbar sticky-top navbar-light p-0"> <div class="collapse navbar-collapse search-bar show p-4" id="navbarSupp ...

The property mentioned was attempted to be accessed during the rendering process, however it is not defined on the instance

I am currently facing four main errors that I need to resolve while working with Vue 3: https://i.sstatic.net/23ir7.png Despite everything else working correctly, my code seems to have issues specifically with user inputs. //############--contact.js-- ...

What is the correct way to include viewport width in pixels using CSS?

My div is set to a width of 50vw with padding of 25px on all sides. I am looking to add a fixed element to the right of it by increasing its width by 50vw and adding 25px. Can this be achieved using only CSS, or should I consider using Less? If so, how c ...

Combining two observable entities

Utilizing Angular 4 and rxjs, the objective is to fetch data from two distinct servers in JSON format, merge this data, and exhibit it in a list by associating the list with an observable array. **Word Search Component TypeScript File:** @Component( ...

Unable to save the ID of an element into a jQuery variable

I am currently working on a project that involves an unordered list with anchor tags within it. I am trying to access the id of the li element that is being hovered over, but for some reason, the alert is returning undefined or nothing at all. Here is the ...

What is the best way to control the number of fetch calls sent to an endpoint service ensuring that only a maximum of 10 calls are made every second?

Is there a way to prevent the browser from encountering the "Error 429 Too Many Requests" by adjusting the code below to ensure that no more than 10 calls per second are made? Please note that the rate limit of 10 calls per second is set by a 3rd-party AP ...

Always maintaining a responsive and square aspect ratio div

I am developing a CSS and JavaScript-based game that requires the game field to be square and adjust its width and height based on the height of the viewport. In case the viewport width is smaller than the height, I need the field size to adapt while maint ...

Practical Tip for jQuery - Storing DOM Element in a Variable for Consistent Usage Across Your Codebase

As I was searching for some Jquery best practices, I came across this gem. Source: // Storing the live DOM element in a variable var elem = $("#elem"); // Setting an element's title attribute using its current text elem.attr("title", elem.te ...