Scale and reposition iframe like background-size: cover
Asked Answered
O

2

41

html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}
.sized {
  height: 100%;
  position: relative;
  background: #eee;
  overflow:hidden;
  padding:0;
}
.sized iframe {
  position:absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}
@media (min-width: 320px) {
  height: 200%;
  top: -50%;
}
@media (min-width: 640px) {
  height: 180%;
  top: -40%;
}
<div class="sized">
  <iframe src="https://player.vimeo.com/video/135335257?autoplay=false" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
</div>

<h3>Original video</h3>
<iframe src="https://player.vimeo.com/video/135335257?autoplay=false" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>

As I get a cookies same origin error in the snippets result, here is a mirror:

https://jsfiddle.net/07Lffw5x/2/embedded/result/

[edit] Maybe this is a better demo, if you compare to this one, there is not much difference... why? [/edit]

I'm trying to reproduce a background-size cover for an iframe.

The thing is that it seems to rescale the video, for bigger sizes only,

Question,

Can the rescales take effect on every breakpoint? or the vimeo player might rescale by it's own anyway?

Ostensive answered 31/10, 2015 at 12:18 Comment(16)
I'm not entirely clear what you are asking for, do you want to keep the iframe at the correct aspect ratio so there are no black bars? Would you be able to provide a image showing exactly what you after, it may help clarify things.Ostrowski
There's a snippet. Does it not work for you? (But removing the black spaces is more important than the perfect aspect ratio)Ostensive
The snippet works but I'm not 100% clear what your desired result is. To check if I am on the right lines, is this what you are after? jsfiddle.net/ysgsaqs8Ostrowski
I need the same as you, with a fixed height. Any thoughts? thanks! ( that's why i think we need to rescale and reposition )Ostensive
Right, I think I understand, so you want the video to fill the whole iframe but rather than stretching the video you want parts of the video to be cut off (if required)?Ostrowski
That is correct! excuse my english.. !Ostensive
so you want a iframe that covers the intire page?Kaiserdom
just the entire container, but yes! (well, not the iframe; the video of the iframe; no black borders or anything, even if we have to miss some of it (just like in my jsfiddle, but for all resolutions)Ostensive
have you tried setting a fixed height (example: height:200px;) and overflow:hidden; ?Bullough
@EduardoLaHozMiranda the thing is I need it responsive... I don't think its a say to go.. ( rembember I'm trying to get rid of the black bars..)Ostensive
You could use media queries to handle the height at all your screen requirements.Bullough
I tried, but being an iframe and not a video, it doesn't work; the iframe must resize the video with media querys allready?Ostensive
Why not adjust the div element instead of the iframe; is it possible to within your site design to set the height of the containing div element to be zero and use a padding hack to keep the video aspect ratio? For example setting the padding-top or padding-bottom to the inverse of the video aspect ratio (56.25% for a 16:9 video) removes the black bars.Hamel
You didnt understan my issue... I want a fixed height for the containerOstensive
Ok, understand now, if you have a fixed div requirement have you tried looking at a jQuery solution? One that I have used in the past works in any div element (I used it for background video) is a plugin called bigvideo.js dfcb.github.io/BigVideo.jsHamel
Interesting! i might consider If question expires without a CSS solution! thank you !Ostensive
O
62

Similar to Alvaro Menendez's answer, credit needs to go to this answer https://mcmap.net/q/127219/-simulate-background-size-cover-on-lt-video-gt-or-lt-img-gt by Qwertman. I got as far as using the "padding percentage" trick, but this answer's clever use of viewport units is crucial to this working.

The key to implementing this behaviour is to ensure two things:

  1. That the iframe always maintains the same aspect ratio as its video content 16 : 9. This will ensure that no black "padding" is present around the outside of the video
  2. That the iframe always fills the height or width depending on the size of the viewport

One way to maintain the aspect ratio of an element is to use the "padding percentage" trick which takes advantage of the fact that top and bottom padding uses the width of the element as the basis for their value. Using the formula B / (A / 100) = C% we can calculate the required percentage for the padding. Given the video has a 16 : 9 ratio this translates to 9 / (16 / 100) = 56.25.

The only problem is that in your case the calculation is required for both the horizontal and vertical axis (as we don't know what dimensions the viewport will be) and this trick will not work with left and right padding to get the aspect ratio in relation to the height.

html, body {
    height: 100%;
    margin: 0;
    padding: 0;
}
.container {
    background: #eee;
    height: 100%;
    overflow: hidden;
    padding: 0;
    position: relative;
}
.inner {
    left: 50%;
    min-height: 43.75%;
    padding-top: 56.25%;
    position:absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 100%;
}
.container iframe {
    bottom: 0;
    height: 100%;
    left: 0;
    position:absolute;
    right: 0;
    top: 0;
    width: 100%;
}
<div class="container">
    <div class="inner">
        <iframe src="https://player.vimeo.com/video/135335257?autoplay=false" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
    </div>
</div>

https://jsfiddle.net/w45nwprn/ (Snippet doesn't show video, please see fiddle)

Luckily, in your case you want the video to fit the entire screen so viewport units can be used to calculate the aspect ratio instead of percentages. This allows use to calculate the width in relation to the height and vica versa:

  • left: 50%;, top: 50%; and transform: translate(-50%, -50%); are required to center the iframe in .container
  • min-height: 100%; and min-width: 100%; are required to ensure that the height and width are never smaller than that of .container
  • height: 56.25vw; will set the height in relation to the width of the viewport. This is calculated by doing 9 / (16 / 100) = 56.25
  • width: 177.77777778vh; will set the width in relation to the height of the viewport. This is calculated by doing 16 / (9 / 100) = 177.77777778

Because the height and width can never be below 100% but the must remain in the correct aspect ratio the video will always cover the whole viewport.

html, body {
    height: 100%;
    margin: 0;
    padding: 0;
}
.container {
    background: #eee;
    height: 100%;
    overflow: hidden;
    padding: 0;
    position: relative;
}
iframe {
    box-sizing: border-box;
    height: 56.25vw;
    left: 50%;
    min-height: 100%;
    min-width: 100%;
    transform: translate(-50%, -50%);
    position: absolute;
    top: 50%;
    width: 177.77777778vh;
}
<div class="container">
    <iframe src="https://player.vimeo.com/video/135335257?autoplay=false" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
</div>

https://jsfiddle.net/qk00ehdr/ (Snippet doesn't show video, please see fiddle)

Viewport units are widely supported, so as long as you are not targeting old browsers this method should work.

Ostrowski answered 9/11, 2015 at 20:43 Comment(6)
That's a clever use of css to achieve the solution. While I don't like (yet) the use of vw and hwI know it's the future (and a close one). You have my upvote and you may get the bounty if the op doesn't need much full "a bit older" brower compatibility.Leveroni
Thanks @AlvaroMenéndez. Between this and your answer I think we've got Toni's problem covered pretty well. I haven't had much use for viewport units either but it looks like they could come in handy every now and then. If IE8 support is required it should be possible to detect if viewport units are supported and switch to the JavaScript method when necessary.Ostrowski
Now the problem is mine because I don't know who to award to... haha!Ostensive
It's fine. Don't worry. You acepted the answer that works better for you as It should be. Gl with your projectLeveroni
I had a custom sized web view in an iOS application and the iframe would not scale to fit properly. This did it for me. Thank you!Faculty
Glad I could help @AlexNguyen.Ostrowski
T
8

Ok. The merit is NOT mine as I got the jquery here

I remembered that question as I used it on one of my old projects and I wanted to check if it would work the same with an iframe. It does.

basically with this css:

.container {
    position: absolute;
    top: 0;
    overflow: hidden;
}

and this jquery:

var min_w = 300; // minimum video width allowed
var vid_w_orig;  // original video dimensions
var vid_h_orig;

jQuery(function() { // runs after DOM has loaded

    vid_w_orig = parseInt(jQuery('iframe').attr('width'));
    vid_h_orig = parseInt(jQuery('iframe').attr('height'));

    jQuery(window).resize(function () { resizeToCover(); });
    jQuery(window).trigger('resize');
});

function resizeToCover() {

    // set the video viewport to the window size
    jQuery('.container').width(jQuery(window).width());
    jQuery('.container').height(jQuery(window).height());

    // use largest scale factor of horizontal/vertical
    var scale_h = jQuery(window).width() / vid_w_orig;
    var scale_v = jQuery(window).height() / vid_h_orig;
    var scale = scale_h > scale_v ? scale_h : scale_v;

    // don't allow scaled width < minimum video width
    if (scale * vid_w_orig < min_w) {scale = min_w / vid_w_orig;};

    // now scale the video
    jQuery('iframe').width(scale * vid_w_orig);
    jQuery('iframe').height(scale * vid_h_orig);
    // and center it by scrolling the video viewport
    jQuery('.container').scrollLeft((jQuery('iframe').width() - jQuery(window).width()) / 2);
    jQuery('.container').scrollTop((jQuery('iframe').height() - jQuery(window).height()) / 2);
};

You get this: JSFIDDLE

(I know you were looking for a pure css solution, which I don't think it's possible but I can be wrong, but I have posted this answer because it could help other people with same issue)

Thorn answered 6/11, 2015 at 10:12 Comment(2)
I was affraid of not finding a CSS solution, I'll give the bounty it's time, but this seems the way to go! (not plugins or anything, looks good!). And it seems that the trick is play with scrollLeft and scrollTop, not left & top!Ostensive
In the same link I posted where I got this script there are some css solutions. I have just checked them but I think none will work with an iframe but again... I may be wrong. I don't have time atm to propely checked them in a fiddle. maybe you want to give it a try.Leveroni

© 2022 - 2024 — McMap. All rights reserved.