Auto-resize iFrame zonder scrollbar

Auto-resize iFrame zonder scrollbar

Een iFrame dat zie zich in afmetingen automatisch aanpast aan de getoonde pagina. Zonder scrollbar natuurlijk. Het is een bekend probleem waar heel veel oplossingen voor zijn te vinden. Deze methode is echter mooi in eenvoud en werkt op nieuwe browsers altijd. Bovendien is het responsive.

Het onderstaande iframe neemt automatische de afmetingen van de getoonde inhoud aan. Een mooie bijkomstigheid is dat het iframe, zonder media queries, volledig responisve is.

Tonen in iFrame:

(Iframe afmeting: 400 x 520px)

Als voorbeeld wordt de foto gallery genomen.
Hier wisselt de iframe-hoogte per getoonde foto en verliest na een muisklik de parent window zijn focus niet.

1. De webpagina waar het iframe komt te staan

Als eerste de webpagina waar het iframe in getoond wordt, de 'index.html'

..
...
<body>
    <iframe id="myIframe" src="content.html" frameborder="0" scrolling="no"></iframe>
    <script src="js/iframe.js" type="text/javascript"></script>
</body>

Het bestand 'iframe.js' bevat in eerste instantie de volgende code


window.addEventListener("message", function receiveSize(event) {
    if (typeof event.data == 'object') {
        // Pas hoogte iframe aan
        document.getElementById("myIframe").style.height = event.data.height + "px";
        document.getElementById("myIframe").style.width = event.data.width + "px";
    }
}, true);

Met window.addEventListener kan een willekeurige gebeurtenis (event) bijvoorbeeld een muis- of scrollbeweging gedetecteerd worden. Hier wordt als event-type "message" gebruikt.
De message event komt in actie als er met de method postMessage een bericht wordt verzonden. In dit geval wordt postMessage gebruikt in het Iframe en stuurt het een post-bericht naar de parent-window.

addEventListener
postMessage

In het iframe ziet het er zo uit


var obj = {'height': 300, 'width': 400};
window.parent.postMessage(obj, '*');

In dit geval geeft  'event.data.height' 300 en 'event.data.width' 400 als waarde

2. De webpagina getoond in het iframe

In dit voorbleeld staat de foto gallerij uit het voorbeeld hierboven (bestand 'content.html').

Er is in dit voorbeeld gebruikt gemaakt van JQuery

..
...
<body>        
    <div class="wrapper">
        <div class="spacer">           
            <div class="image-box">
                <div id="block" class="block"><img  src="img/abandoned.thumb.jpg" alt="Abandoned place"/></div>
            </div>
            <div class="thumbnails">
                <a href="#"><img  src="img/abandoned.thumb.jpg" alt="Abandoned place"/></a>
                <a href="#"><img  src="img/bridge.thumb.jpg" alt="Bridge"/></a>
                <a href="#"><img  src="img/bunker.thumb.jpg" alt="Bunker"/></a>
                <a href="#"><img  src="img/tsjernobyl.thumb.jpg" alt="Tsjernobyl"/></a>
            </div>
        </div>
    </div>
    <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script>
    $(function () {
        // links/thumbnails doorlopen
        $(".thumbnails a").each(function (i) {

            // Naam afbeelding en haal .thumb eraf halen
            var href = $(this).children().first().attr('src').replace(".thumb.jpg", ".jpg");

            $(this).bind('click tab', (function () {
                // actuele afbeelding vervangen
                $("#block img").attr("src", href).one("load", function () {
                    post_message();
                });
            }));
        });

        //iframe aanpassen voor start afbeelding
        post_message();
    })

    // Afmeting iframe-pagina bepalen en versturen
    var post_message = function () {
        var obj = {'height': $('body').height(), 'width': $('body').width()};
        window.parent.postMessage(obj, '*');
    }

    // Scrollwheel, niet iframe maar parent venster scrollen
    // Luisteren naar gebruik van muiswiel
    window.addEventListener("wheel", function(event) {
        var obj = {'deltaY': event.deltaY};
        window.parent.postMessage(obj, '*');
    }, false);
    </script>
</body>

Het belangrijkste in het script is de method postMessage die data verstuurt naar de parent window. Dus de data verstuurd naar het browser verster waar het iframe zich in bevindt.

In post_message wordt de actuele hoogte en de breedte van de pagina in het iframe bepaald. Deze waarden worden als object door gegeven aan het 'parent' venster.

Om zonder problemen over het iFrame heen te kunnen scrollen, ook na het klikken in of op het iframe, is er een event listener "wheel" toegevoegd. Deze listener komt in actie als er aan het scrollwiel van de muis wordt gedraaid. WheelEvent.deltaYrepresenteerd de waarde van de verticale scroll-beweging.

Wheel / WheelEvent

Om iets met dit WheelEvent te kunnen doen moet het bestand 'iframe.js' iets aangepast worden.


window.addEventListener("message", function receiveSize(event) {
    if (typeof event.data == 'object') {
        if ('height' in event.data) {
            // Pas hoogte iframe aan
            document.getElementById("myIframe").style.height = event.data.height + "px";
            document.getElementById("myIframe").style.width = event.data.width + "px";
        }
        else if ('deltaY' in event.data) {
            // Scroll (parent) browser-venster als de focus in het iframe ligt
            var y = $(window).scrollTop();
            $(window).scrollTop(y + (event.data.deltaY * 15));
        }
    }
}, true);

Zo wordt de scroll actie in het iframe toch uitgevoerd in de parent window.

Javascript zonder Jquery in het bestand content2.html

    <script>
    document.addEventListener("DOMContentLoaded", function(event) {

        var a = document.getElementsByTagName('a'), // Klikbare thumbnails
            img = document.getElementById('block').childNodes[0], // img-tag van actuele getoonde afbeelding
            body = document.getElementsByTagName('body')[0],// Container om afm. te bepalen
            link = a[0]; // eerste afbeelding direct weergeven.

        // onclick Event thumbnails
        for(i=0;i<a.length;i++) {
            a[i].addEventListener("click", function() {
                link = this.childNodes[0].getAttribute('src').replace(".thumb.jpg",".jpg");
                img.setAttribute('src',link);
                img.addEventListener("load",post_message,false);
            }, false);
        }

        // Afmeting iframe-pagina bepalen en versturen
        var post_message  = function() {
            var height = Math.max( body.scrollHeight,body.offsetHeight, body.clientHeight),
                width  = Math.max( body.scrollWidth, body.offsetWidth, body.clientWidth ),
                obj    = {'height': height,'width':width};

            window.parent.postMessage(obj, '*');
        }

        // iframe aanpassen voor start afbeelding
        post_message();

        // Scrollwheel, niet iframe maar parent venster scrollen
        // Luisteren naar gebruik van muiswiel
        window.addEventListener("wheel", function(event) {
            var obj = {'deltaY': event.deltaY};
            window.parent.postMessage(obj, '*');
        }, false);
    });
</script>

Voorbeeld bestanden:iframe-auto-resize.zip