toddmotto/fluidvids

Have video not extend further than width

Closed this issue ยท 10 comments

@jaydenseric Made a pull request for this but it was somehow overwritten so it is not there anymore. I also saw that you made some changes. I recreated it. This is what I got and it works. I also added the YouTube privacy version of the url.

(function ( window, document, undefined ) {

    /*
     * Grab all iframes on the page or return
     */
    var iframes = document.getElementsByTagName( 'iframe' );

    /*
     * Loop through the iframes array
     */
    for ( var i = 0; i < iframes.length; i++ ) {

        var iframe = iframes[i],

        /*
         * RegExp, extend this if you need more players
         */
        players = /www.youtube.com|www.youtube-nocookie.com|player.vimeo.com/;

        /*
         * If the RegExp pattern exists within the current iframe
         */
        if ( iframe.src.search( players ) > 0 ) {

            /*
             * Calculate the video ratio based on the iframe's w/h dimensions
             */
            var width             = iframe.width;
            var height            = iframe.height;
            var videoRatio        = ( height / width ) * 100;

            /*
             * Replace the iframe's dimensions and position
             * the iframe absolute, this is the trick to emulate
             * the video ratio
             */
            iframe.style.position = 'absolute';
            iframe.style.top      = '0';
            iframe.style.left     = '0';
            iframe.width          = '100%';
            iframe.height         = '100%';

            /*
             * Wrap the iframe in a new <div> which uses a
             * dynamically fetched padding-top property based
             * on the video's w/h dimensions
             */
            var wrap              = document.createElement( 'div' );
            wrap.className        = 'video-wrap';
            wrap.style.width      = '100%';
            wrap.style.position   = 'relative';
            wrap.style.paddingTop = videoRatio + '%';

            /*
             * Add the iframe inside our newly created <div>
             */
            var iframeParent      = iframe.parentNode;
            iframeParent.insertBefore( wrap, iframe );
            wrap.appendChild( iframe );

            /*
             * Wrap the div in a new <div> which is used
             * to set a max width accordin to the video's dimensions
             */
            var outerWrap        = document.createElement( 'div' );
            outerWrap.className  = 'outer-video-wrap';
            outerWrap.style.maxWidth   = width + 'px';

            /*
             * Add the div wrap inside our newly created <div>
             */
            var wrapParent       = wrap.parentNode;
            wrapParent.insertBefore( outerWrap, wrap );
            outerWrap.appendChild( wrap );

        }

    }

})( window, document );

Hey Ulrich, yes that's right a pull request was made, however it prevents a lot of fluidity as it stops the iframe video going past it's original width, e.g. 580px wide, which when it comes to responsive design isn't the best in terms of getting videos to fit successfully in the window space, especially between viewport breakpoints and other. Having it always 100% width of the content wrapper regardless of it's width is by far the more predicted choice, it's also how FitVids works.

When you make images responsive, you set max-width and not width to 100%. Same should be for video. Otherwise your layouts will be restricted to full width videos only. The only way to give yourself the option (you can still set 100% width to the wrapper in the CSS) to make certain videos not full width whilst using this wrapper technique is to add a second wrapper.

To be honest, I made my script the other day that is only a few lines and does not involve wrappers at all. It respects the size atributes and uses the same CSS max-width behaviour responsive images have these days. This means it works with any sort of layout you want and works in situations where dynamically inserted wrappers could be layout destructive. I will try to put it up on Github sometime soon.

Fluidvids is a great script if you don't mind all you videos taking up the full width :)

Videos aren't images though. In my opinion videos should max-width 100% to the container they're in, not their original size as you'll have lots of odd-shaped videos if they're from Vimeo, YouTube all on the same page, why would you not want them all to obey the width of the container? Videos don't need to take up the full width, you simply create two/three columns... Am I missing something?

Videos are moving images (hence the word "movie"). HTML5 video behaves like an image regarding size. Picture this: You have a CMS managed section where users can set any size on videos and float them around text, just like images. At desktop, you want them to respect their natural inline sizing. Iframe size atributes exist for a reason, they are not a decoration and can be changed to whatever you need. Now resize the window width down to mobile size. The video widths should fluidly stay within the width of the container. This is super easy with images: max-width 100%. How would your script allow that basic layout without adding a wrapper around each video wrapper to hold the max-width?

The metrics priority for images goes native size > inline size > CSS size. Iframes skip native size as they don't one. To have a catch-all script that can be included in any project to make iframes responsive it is best to respect that basic order.

In my pull request, only a max-width is set on the outer wrapper. You can therefore put a 100% width on it in your stylesheet if you want to achieve the original behaviour of your script. At least you would have the option.

I feel that the user should be able to define the width of the video and not just have the video take up the whole width.

There are two solutions to this. I am not sure which is better as they both have their pros and cons.

The first being that the script allows a max width.

The other being that the user wraps the iframe in a div of his own.

<div class="outer-video-wrap" style="max-width: 560px;">
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/_F2xmoOmzqI?rel=0" frameborder="0" allowfullscreen></iframe>
</div>

@toddmotto If you decide that the first is not a solution it might be good to have the second in the readme.

@jaydenseric I look forward to see your solution ๐Ÿ˜„

Here is a sneak-peak:

// Make iframes responsive
$(document).ready(function() {
    function resizeIframes() {
        $("iframe").each(function() {
            var ratio = $(this).attr('height') / $(this).attr('width');
            $(this).css('height', $(this).width() * ratio);
        });
    }
    resizeIframes();
    $(window).resize(function() {
        resizeIframes();
    });
});

All the JS does is make sure the height is in ratio to the width at all times. It is up to you to put iframe { max-width: 100% } in your stylesheet. I just add iframe to the code already there for img.
The original iframe size atributes are not directly overwritten and there are no wrappers. This could be written in vanilla JS and be extended to only affect iframes containing videos. Personally, I am a minimalist.

@jaydenseric I have seen a similar solution before. The reason I did not like it is that the script needs to be run every time the browser is resized. I am not sure if there are any performance implications from that.

Performance is not really an issue. 9/10 times the code fires once (page load) and the window is never resized. In large browser windows there will be no discernable effect as the hight is the same as the inline atribute. For mobile devices, where performance is more of an issue, the browser can not be resized in the first-place. In my testing with several videos on a page it performed perfectly. Re-rendering when resizing a window does not have to be performant at all anyway. Page-load and interactivity does.

There are performance gains when there is less JS to download and parse. There should be less of a flash when loading pages as elements are not being tossed around the DOM. The improvements to semantics are a no-brainer as there are no wrappers. On a human level, it is easier to get your head around what is going on than with the CSS ratio hack. But each to his own :)