Tips for Keeping a Responsive Image at the Forefront of a Text-Image Layout as You Scroll

I'm currently in the process of creating a website where text appears on the left side with an accompanying image on the right. The challenge I'm encountering is ensuring that as users scroll, the image adjusts dynamically based on the associated text. Although everything works smoothly on desktop, there are difficulties in keeping the image sticky and always on top during responsive mode. When the screen size shrinks, the image ends up shifting below the text. Here's the code snippet I have been working on:

document.addEventListener("DOMContentLoaded", function() {
    const artwork = document.getElementById('artwork');
    const sections = document.querySelectorAll('.content-section');
    const screenWidth = window.innerWidth; // Get screen width

    const transformations = [
        { scale: 1, translateX: 0, translateY: 0 },        // Section 1
        { scale: 2.2, translateX: 60, translateY: -30 },  // Section 2
        { scale: 1.5, translateX: 20, translateY: 80 }, // Section 3
        { scale: 2, translateX: -100, translateY: -200 }  // Section 4
    ];

    const scrollHandler = () => {
        const scrollPosition = window.scrollY + window.innerHeight / 2;

        sections.forEach((section, index) => {
            const sectionTop = section.offsetTop;
            const sectionHeight = section.offsetHeight;

            if (scrollPosition > sectionTop && scrollPosition < sectionTop + sectionHeight) {
                const transform = transformations[index];
                artwork.style.transform = `scale(${transform.scale}) translate(${transform.translateX}px, ${transform.translateY}px)`;

                // Hide text on small screens
                if (screenWidth <= 768) {
                    section.style.display = 'none';
                }
            } else {
                // Restore text visibility
                section.style.display = 'block';
            }
        });
    };

    window.addEventListener('scroll', scrollHandler);
    scrollHandler(); // Initial call to set the correct transform on load
});
.imscroll {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
}

.grid-test {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    width: 100%;
}

.text-section {
    position: relative;
    z-index: 1;
}

.interactive-container {
    position: sticky;
    top: 20px;
    height: 80vh;
    overflow: hidden;
    z-index: 2; /* Increase z-index */
    padding-bottom: 20px; /* Add padding */
}

.interactive-container img {
    position: absolute;
    width: 100%;
    height: auto;
    transition: transform 0.3s ease;
}

.content-section {
    padding: 20px 0;
    border-bottom: 1px solid #ddd;
}

/* Responsive Design */
@media (max-width: 768px) {
    .grid-test {
        display: flex;
        flex-direction: column;
    }

    .interactive-container {
        position: relative; /* Change position to relative 
        top: 0;
        height: auto; /* Reset height */
    }

    .interactive-container img {
        position: absolute;
        width: 100%; /* Make the image width 100% of its container */
        height: auto; /* Maintain aspect ratio */
        transition: transform 0.3s ease;
    }


@media (max-width: 768px) {
    .interactive-container {
        z-index: 2; /* Increase z-index */
        padding-bottom: 10px; /* Adjust padding for smaller screens */
    }
}
<div class="imscroll">
<div class="grid-test">


<div class="text-section">
<section class="content-section" id="section1">
<h2>Section 1</h2>

<p>Paragraph1 sit amet, consectetur adipiscing elit. Maecenas tempor nunc mauris, sit amet placerat tortor lobortis dapibus. Nam lectus eros, maximus ac magna vel, congue consequat eros. Fusce id pretium diam. Cras sit amet pharetra ante. Sed quis commodo quam, vel facilisis ipsum. Vestibulum sodales iaculis arcu, et fringilla nisi ullamcorper sed. Donec interdum sit amet est non accumsan. Donec non augue feugiat, fermentum nunc non, convallis est. Cras vel ligula nec odio faucibus ultricies. Sed vulputate tortor eget pretium convallis. Cras interdum elit eget mi porta suscipit. Morbi ut velit diam. Etiam finibus eros et efficitur rutrum. Quisque viverra metus ac eleifend imperdiet. Quisque pretium ut purus vitae tempus. Duis varius risus congue velit faucibus, sed interdum purus consectetur.</p>
</section>

<section class="content-section" id="section2">
<h2>Section 2</h2>

<p>Paragraph1 sit amet, consectetur adipiscing elit. Maecenas tempor nunc mauris, sit amet placerat tortor lobortis dapibus. Nam lectus eros, maximus ac magna vel, congue consequat eros. Fusce id pretium diam. Cras sit amet pharetra ante. Sed quis commodo quam, vel facilisis ipsum. Vestibulum sodales iaculis arcu, et fringilla nisi ullamcorper sed. Donec interdum sit amet est non accumsan. Donec non augue feugiat, fermentum nunc non, convallis est. Cras vel ligula nec odio faucibus ultricies. Sed vulputate tortor eget pretium convallis. Cras interdum elit eget mi porta suscipit. Morbi ut velit diam. Etiam finibus eros et efficitur rutrum. Quisque viverra metus ac eleifend imperdiet. Quisque pretium ut purus vitae tempus. Duis varius risus congue velit faucibus, sed interdum purus consectetur.</p>
</section>

<section class="content-section" id="section3">
<h2>Section 3</h2>

<p>Paragraph1 sit amet, consectetur adipiscing elit. Maecenas tempor nunc mauris, sit amet placerat tortor lobortis dapibus. Nam lectus eros, maximus ac magna vel, congue consequat eros. Fusce id pretium diam. Cras sit amet pharetra ante. Sed quis commodo quam, vel facilisis ipsum. Vestibulum sodales iaculis arcu, et fringilla nisi ullamcorper sed. Donec interdum sit amet est non accumsan ...</p>
</section>

<section class="content-section" id="section4">
<h2>Section 4</h2>

<p>... incididunt dolor consectetur adipiscing elit. Phasellus euismod lorem pharetra leo rhoncus condimentum...</p>
</section>
</div>
  <div class="interactive-container">
<p style=" margin-top: 100px;"><img src="http://www.reedyrace.com/images/b64d-chassis.jpg" alt="Artwork" id="artwork" style=" border: 1px solid gray;" /></p>
</div>
</div>
</div>

Answer №1

To ensure optimal display on smaller screens, implement the following CSS modifications max-width: 768px.

@media (max-width: 768px) {
    .grid-test {
        flex-direction: column-reverse; /* Adjust order to maintain image at the top */
    }

    .interactive-container {
        height: 50vh; /* Alter height for smaller screens */
        position: sticky;
    }

    .interactive-container img {
        width: 100%;
        position: relative;
    }
}

Edit out this portion in javascript.

if (screenWidth <= 768) {
    section.style.display = 'none';
}

document.addEventListener("DOMContentLoaded", function() {
    const artwork = document.getElementById('artwork');
    const sections = document.querySelectorAll('.content-section');
    const screenWidth = window.innerWidth; // Retrieve screen width

    const transformations = [
        { scale: 1, translateX: 0, translateY: 0 },        // Section 1
        { scale: 2.2, translateX: 60, translateY: -30 },  // Section 2
        { scale: 1.5, translateX: 20, translateY: 80 }, // Section 3
        { scale: 2, translateX: -100, translateY: -200 }  // Section 4
    ];

    const scrollHandler = () => {
        const scrollPosition = window.scrollY + window.innerHeight / 2;

        sections.forEach((section, index) => {
            const sectionTop = section.offsetTop;
            const sectionHeight = section.offsetHeight;

            if (scrollPosition > sectionTop && scrollPosition < sectionTop + sectionHeight) {
                const transform = transformations[index];
                artwork.style.transform = `scale(${transform.scale}) translate(${transform.translateX}px, ${transform.translateY}px)`;
            } else {
                // Restore text visibility
                section.style.display = 'block';
            }
        });
    };

    window.addEventListener('scroll', scrollHandler);
    scrollHandler(); // Execute initially to apply correct transform on load
});
.imscroll {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
}

.grid-test {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    width: 100%;
}

.text-section {
    position: relative;
    z-index: 1;
}

.interactive-container {
    position: sticky; /* Retain positioning as sticky */
    top: 20px;
    height: 80vh;
    overflow: hidden;
    z-index: 2; /* Maintain higher z-index */
}

.interactive-container img {
    position: absolute;
    width: 100%;
    height: auto;
    transition: transform 0.3s ease;
}

.content-section {
    padding: 20px 0;
    border-bottom: 1px solid #ddd;
}

/* Responsive Design */
@media (max-width: 768px) {
    .grid-test {
        display: flex;
        flex-direction: column;
    }

    .interactive-container {
        position: relative; /* Change position to relative */
        top: 0;
        height: auto; /* Reset height */
    }

.interactive-container img {
    position: absolute;
    width: 100%; /* Set image width to match container */
    height: auto; /* Maintain aspect ratio */
    transition: transform 0.3s ease;
} 
<div class="imscroll">
<div class="grid-test">


<div class="text-section">
<section class="content-section" id="section1">
<h2>Section 1</h2>

<p>Paragraph content here.</p>
</section>

... other sections ...

</div>
  <div class="interactive-container">
<p style=" margin-top: 100px;"><img src="image-url.jpg" alt="Artwork" id="artwork" style=" border: 1px solid gray;" /></p>
</div>
</div>
</div>

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

"Looking to swap out the Angular theme's CSS stylesheet for your entire application? Here's

I was initially facing an issue while trying to import CSS through index.html as I kept getting a MIME type error: enter image description here The browser refused to apply the stylesheet from 'http://localhost:4200/css/pink-bluegrey.css' because ...

What are the steps to manipulate the data within an EJS file after passing an array through Node.js as an object?

I'm currently developing a simple calendar application using Node.js and ejs. I am working on passing an array of months through express to my ejs file, with the goal of being able to cycle through each month by clicking the next button. How can I imp ...

Utilizing jquery.validate.min.js for efficient form validation

Here is my JavaScript validate function: $("form[id='form']").validate({ Name: "required", submitHandler: function() { formSubmit(); } }); Not only do I wa ...

How can I fetch the ID from a posted AJAX request in PHP?

Is there a way to retrieve the data from an ajax request in PHP? I am able to successfully return a string of data using ajax, but I'm having trouble accessing the variable passed as a json object. How can I access a json object that only contains one ...

Tips for maintaining the original value of a state variable on a child page in ReactJS. Keeping the initial value passed as props from the parent page

Whenever the 'isChildOpen' flag in the parent is true, my child page opens. The goal now is to ensure that the state variable filtered2 in the child component remains constant. While both filtered and filtered2 should initially receive the same v ...

One way to enhance user experience is by passing parameters dynamically from the database when an element is clicked. This allows for the retrieval of

Earlier, I tried to post a question but couldn't get it working due to incorrect code. As the title suggests, my objective is to retrieve data from a database and display it in a div. The idea is that when this data is clicked, it should be passed to ...

The AngularJS $filter(date) function is causing incorrect format outputs

Hey there! I've come across an issue with my AngularJS filter, where it's supposed to return a date in a specific format. However, when I try the following code: var input = '2015-08-11T13:00:00'; var format = 'yyyy MMM dd - hh:mm ...

leaving code block using Express and Node

My code is displayed below: // Implement the following operations on routes ending with "users" router.route('/users') .post(function(req, res, next) { var user = new User(); user.username = req.body.username; user.p ...

Eliminating an element from an array without the need for iteration

I've been reviewing some documentation, but I have a hunch that there may be a simpler way to eliminate one element from an array without having to utilize an iteration loop. http://jsfiddle.net/G97bt/1/ Check out the updated jsFiddle example: http: ...

Creating a reusable anonymous self-invoking function

Here is a function that I am working with: (function(e, t) { var n = function() { //code, code, code }; //code, code, code e.fn.unslider = function(t) { //code, code, code }; })(jQuery, false) To execute this function, I have impleme ...

Ensuring Proper Alignment of Headers in CSS

I'm struggling to align my header correctly. Despite getting close in Internet Explorer, it looks terrible in Firefox with the code below. I've scoured forums for solutions but the more I try to fix it, the worse it looks. All I want is for heade ...

Submitting a Yii 2 form automatically when it loads

Pjax::begin(); $form = ActiveForm::begin(); echo $form->field($model, 'testdata', [ 'inputOptions' => [ 'class' => 'form-control input-xsmall input-inline' ], ...

Unable to capture screenshot of hovered element using Cypress

Having an issue with taking a screenshot of an element with a hover effect. The screenshots always come out without the hover effect applied. tableListMaps.lineWithText('Hello world', 'myLine'); cy.get('@myLine').realH ...

Navigating through a multistep form in AngularJS using UI Router and arrow keys for seamless movement

Is there a way to navigate to the next or previous form step using arrow keys in AngularJS UI Router? The code provided below is currently allowing navigation with previous and next buttons. .config(function($stateProvider, $urlRouterProvider) { $stat ...

Techniques for parsing a String in Objective-C

I am looking to parse a string to replace certain elements within it. If the string contains an <ol> tag, I want to specifically focus on replacing the <li> elements with numbers. I understand that I can utilize the rangeOfString method to c ...

Is there a way to conditionally redirect to a specific page using NextAuth?

My website has 2 points of user login: one is through my app and the other is via a link on a third-party site. If a user comes from the third-party site, they should be redirected back to it. The only method I can come up with to distinguish if a user is ...

A set of six DIV's, divided into two columns of three each

I'm attempting to arrange two columns with three vertical DIVs side by side. The left column is designated for main text, while the right column is reserved for miscellaneous information. Each column consists of a top and bottom DIV that display image ...

HTML DOM parser in PHP with simple space handling

Currently, I am utilizing PHP Simple HTML DOM Parser to extract text that lies between specific div tags using $html->find(div.divname) Everything runs smoothly until the divname contains a space. I've experimented with [div name] and "div name ...

JavaScript JSON conversion from a list

If I have two different lists, such as: list1= ['blue', 'green', 'purple'] list2 = ['circle', 'square', 'triangle'] Is there a way to convert them into a JSON object structure by using another l ...

Arrange the selection options by price using jQuery

Sorting options by price is my goal, but despite trying various codes, I have not been successful! This is the original structure: <select id="product-list"> <option>product 1- [2$]</option> <option>product 2- [4$]< ...