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

Having trouble getting the alert text on the left side of a Bootstrap button with the alert class

Hey there, I managed to create two buttons aligned on opposite sides of my webpage - one on the left and one on the right. Each button, when clicked, displays an alert text on its corresponding side, similar to what you see in this picture The code snippe ...

What is the iPad version of the onmousemove event?

I am currently facing an issue with a website on my iPad. Everything seems to be in order except for the onmousemove method. I am looking for a way to have onmousemove activated when the user swipes their finger across the screen. ...

Invoking a nested function within an array

I need to trigger a function with a button click. The function I want to call is nested within another function, which is part of an array. demo = { volej: function(param) { (new initChartist).users(param); }, initPickColor: function(){ ...

Is there a way to transfer a JSON object to Excel using Nextjs/React?

How can I create a button that exports data from a JSON object to multiple file formats, including Excel (.xlsx)? "data": [ { "id": 1, "temaIndicador": "Indian", "codigo": "001", "observacion ...

Determine the status of a script in PHP by incorporating AJAX

I am having trouble with my file upload page in the application. I want to display "Uploading" while the file is uploading and then show "Processing" while the file is being processed. Eventually, after the script completes, my page should redirect to a sp ...

What is the method for setting autofocus to the first input element within a loop?

I am currently working on a loop to display inputs, and I would like to be able to add focus to the first input element when it is clicked. Does anyone have any suggestions on how I can select that first element and set autofocus on it? ...

Passing array data from JavaScript to PHP using POST method in Joomla 3.x

Looking for a way to send an array from JavaScript to a Joomla 3.x PHP file? var data = ['foo', 'bar']; $.post('index.php?option=component&view=componentview&Itemid=123&tmpl=component&layout=xlsx', {'xls ...

Limit the options in jQuery UI auto-complete to search by name from a variety of JSON responses

I am looking to enhance my search functionality by utilizing jqueryUi's auto-complete feature to specifically target Names and exclude other array values such as fax. Here is how I have implemented it in php: <?php require_once 'db_conx.php&a ...

The horizontal scrolling with overflow-x is not functioning correctly as it is displaying the scrollbar for the vertical

I am perplexed as to why I am unable to scroll horizontally to view the other pink thumbs. Despite adding an overflow of scroll-x to the thumbs container, which should theoretically allow horizontal scrolling, it only seems to scroll vertically. Could som ...

Using i18next to alter language in a React app

Implementing the i18next translation system into my React app was a breeze thanks to a helpful guide I found. However, I'm facing an issue with changing the language manually. The guide covered the setup process perfectly, but lacked information on ho ...

Warnings from Webpack may appear while running the Next.js development server

Encountering these warnings when running npm dev: <w> [webpack.cache.PackFileCacheStrategy] Restoring pack from /Users/pdeva/code/monorepo/web/app/.next/cache/webpack/client-development.pack failed: TypeError: Cannot read properties of undefined (rea ...

I'm having an issue with my Bootstrap tabs - they seem to be unresponsive when clicked

I've been working on a Bootstrap website and have run into some issues that I can't seem to resolve. One problem I encountered was with a set of tabs that were supposed to be interactive, but for some reason, they weren't working as expected ...

When using the Node JS driver to find elements by their class name and retrieve the text, an error is encountered

While working on Selenium tests, I am seeking feedback and the closest solution I have found is using: driver.findElement(By.className('classname')).getText(); However, in order to make it more efficient, I need to find all elements with the sa ...

Error: Unable to convert Mongoose object to ObjectId

Currently tackling an issue with my small blog app and I seem to be stuck at this error- { "message": "Cast to ObjectId failed for value \" 597c4ce202ca9c353fc80e8a\" at path \"_id\" for model \"Blog\"", "name": "CastErr ...

Struggling with aligning two divs side by side on an HTML page

Recently, I've been experimenting with Electron and attempting to create 2 divs side by side. Despite trying various alignment options found here, nothing seems to be working for me. Here's the code I have so far: Code body, html { hei ...

Prevent Click Event in JQuery

I have a requirement to disable all click events on my webpage. However, even after using the appropriate code to prevent these events from firing, some of them are still getting called. Let me explain with an example. <div id='parent'> ...

What is the best way to showcase all tab content within a single tab menu labeled "ALL"?

I have created a tab menu example below. When you click on the button ALL, it will display all the tabcontent. Each tab content has its own tab menu. Thanks in advance! function openCity(evt, cityName) { var i, tabcontent, tablinks; tabcontent = doc ...

Emails not being sent by Nodemailer

I recently configured my glitch project with a contact form and I'm attempting to set it up so that it sends me an email when someone fills out the form. The issue I'm experiencing is that while the server console logs indicate that the message h ...

Tips for navigating through pagination indexes with Angular 6

Hey there, I'm currently working on a project where I need to automatically click through each pagination index. Initially, only the first index can be clicked. After that, the following page indexes are not clickable. Here's the code snippet: ...

What methods can be utilized to enhance the visual appeal of a threejs model

I'm currently working on enhancing the visual quality of my 3D models, aiming for smoother edges and more realistic shadows. To achieve this, I am experimenting with an OBJ file format. Here's the code snippet I'm using to load and display t ...