Search code examples
htmlcssiframe

Have iframe become smaller when scrolling down, so iframe top stays at window top (until a threshold size, then scroll away with page)


When user scrolls down, once an iframe's top reaches the top of the window, I want the iframe to start shrinking with the scrolling so that its top doesn't go above the top of the window (while the bottom continues with the scrolling), until it reaches a set minimum size, and only then it's let scroll offscreen. How do I do this with CSS and (minimum of) Javascript? (Note I also have text to the right of the iframe that I want to scroll normally and not be affected by this functionality; right now the iframe and the text are items in a flex container so I can have them side by side).


Solution

  • If your page is structured something like this, where you have a container div, an iframe-wrapper div, and a text-content div. The container div is used to hold the iframe and the text content side by side using CSS flexbox. The iframe-wrapper div is used to set the iframe's positioning and size, while the text-content div holds your text content.

    <div class="container">
            <div class="iframe-wrapper">
                <iframe id="shrinkable-iframe" src="https://example.com"></iframe>
            </div>
            <div class="text-content">
                <!-- Your text content here -->
            </div>
        </div>
    

    First, you need to reset the default margin and padding of the body element to prevent any unwanted spacing.

        body {
        margin: 0;
        padding: 0;
    }
    

    Next, Apply the display: flex property, which enables the container div to use the flexbox layout, positioning its child elements (the iframe-wrapper and text-content divs) side by side

    .container {
        display: flex;
    }
    

    Next, set the iframe-wrapper div to have a sticky position with a top value of 0, meaning it will stick to the top of the viewport when scrolling down. The width and height are set to occupy 50% of the container's width and the full height of the viewport, respectively. The overflow is set to hidden to prevent the iframe from overflowing its container.

    .iframe-wrapper {
        position: sticky;
        top: 0;
        width: 50%;
        height: 100vh;
        overflow: hidden;
    }
    
    

    Now set the iframe to have a width and height of 100%, ensuring it fills its wrapper div completely. The border is set to none to remove the default iframe border.

    #shrinkable-iframe {
        width: 100%;
        height: 100%;
        border: none;
    }
    
    

    After that, set the width of the text content div to 50%, making it occupy the remaining half of the container's width. The padding is set to 20px to create some space around the text content.

    .text-content {
        width: 50%;
        padding: 20px;
    }
    

    Now, you got add some JavaScript to select the iframe-wrapper and shrinkable-iframe elements and set the minHeight variable to the desired minimum height (in pixels) for the iframe and a scroll event listener to the window object. This function will be called every time the user scrolls. Inside the scroll event listener function, calculate the wrapper's top position relative to the viewport, the scroll distance (ensuring it's not negative), and the new height for the iframe based on the scroll distance and the minHeight. Update the iframe's height based on the newHeight value

    const iframeWrapper = document.querySelector(".iframe-wrapper");
    const shrinkableIframe = document.getElementById("shrinkable-iframe");
    const minHeight = 300; // Set the minimum height in pixels
    
    window.addEventListener("scroll", () => {
        const wrapperTop = iframeWrapper.getBoundingClientRect().top;
        const scrollDistance = Math.max(0, -wrapperTop);
        const newHeight = Math.max(minHeight, iframeWrapper.offsetHeight - scrollDistance);
        
        shrinkableIframe.style.height = `${newHeight}px`;
    });