Scale iFrame css width 100% like an image - css

I want to scale an iFrame through CSS to width: 100%, and the height should scale proportionally to the width.
With an <img> tag this works fine.
Both the image and the iFrame have defined width and height in the html.
Here some examples:
<html>
<style>
#a{ width: 500px; }
img{ width: 100%; height: auto }
</style>
<body>
<div id="a">
<img src="http://lorempixel.com/200/150/" width="200" height="150" />
</div>
</body>
This works great on images, but I would like the same behaviour for iFrames:
<html>
<style>
#a{ width: 900px; background: grey;}
iframe{ width: 100%; height: auto }
</style>
<body>
<div id="a">
<iframe width="560" height="315" src="http://www.youtube.com/embed/RksyMaJiD8Y" frameborder="0" allowfullscreen></iframe>
</div>
</body>
The iFrame renders 100% wide but does not scale it's height proportional like the image does.

Big difference between an image and an iframe is the fact that an image keeps its aspect-ratio. You could combine an image and an iframe with will result in a responsive iframe.
Hope this answerers your question.
Check this link for example : http://jsfiddle.net/Masau/7WRHM/
HTML:
<div class="wrapper">
<div class="h_iframe">
<!-- a transparent image is preferable -->
<img class="ratio" src="http://placehold.it/16x9"/>
<iframe src="http://www.youtube.com/embed/WsFWhL4Y84Y" frameborder="0" allowfullscreen></iframe>
</div>
<p>Please scale the "result" window to notice the effect.</p>
</div>
CSS:
html,body {height:100%;}
.wrapper {width:80%;height:100%;margin:0 auto;background:#CCC}
.h_iframe {position:relative;}
.h_iframe .ratio {display:block;width:100%;height:auto;}
.h_iframe iframe {position:absolute;top:0;left:0;width:100%; height:100%;}
note: This only works with a fixed aspect-ratio.

I suppose this is a cleaner approach.
It works with inline height and width properties (I set random value in the fiddle to prove that) and with CSS max-width property.
HTML:
<div class="wrapper">
<div class="h_iframe">
<iframe height="2" width="2" src="http://www.youtube.com/embed/WsFWhL4Y84Y" frameborder="0" allowfullscreen></iframe>
</div>
<p>Please scale the "result" window to notice the effect.</p>
</div>
CSS:
html,body {height: 100%;}
.wrapper {width: 80%; max-width: 600px; height: 100%; margin: 0 auto; background: #CCC}
.h_iframe {position: relative; padding-top: 56%;}
.h_iframe iframe {position: absolute; top: 0; left: 0; width: 100%; height: 100%;}
http://jsfiddle.net/7WRHM/1001/

I like this solution best. Simple, scalable, responsive. The idea here is to create a zero-height outer div with bottom padding set to the aspect ratio of the video. The iframe is scaled to 100% in both width and height, completely filling the outer container. The outer container automatically adjusts its height according to its width, and the iframe inside adjusts itself accordingly.
<div style="position:relative; width:100%; height:0px; padding-bottom:56.25%;">
<iframe style="position:absolute; left:0; top:0; width:100%; height:100%"
src="http://www.youtube.com/embed/RksyMaJiD8Y">
</iframe>
</div>
The only variable here is the padding-bottom value in the outer div. It's 75% for 4:3 aspect ratio videos, and 56.25% for widescreen 16:9 aspect ratio videos.

You could use viewport units here instead of %. Like this:
iframe {
max-width: 100vw;
max-height: 56.25vw; /* height/width ratio = 315/560 = .5625 */
}
DEMO (Resize to see the effect)
body {
margin: 0;
}
.a {
max-width: 560px;
background: grey;
}
img {
width: 100%;
height: auto
}
iframe {
max-width: 100vw;
max-height: 56.25vw;
/* 315/560 = .5625 */
}
<div class="a">
<img src="http://lorempixel.com/560/315/" width="560" height="315" />
</div>
<div class="a">
<iframe width="560" height="315" src="http://www.youtube.com/embed/RksyMaJiD8Y" frameborder="0" allowfullscreen></iframe>
</div>

#Anachronist is closest here, #Simone not far off. The caveat with percentage padding on an element is that it's based on its parent's width, so if different to your container, the proportions will be off.
The most reliable, simplest answer is:
body {
/* for demo */
background: lightgray;
}
.fixed-aspect-wrapper {
/* anything or nothing, it doesn't matter */
width: 60%;
/* only need if other rulesets give this padding */
padding: 0;
}
.fixed-aspect-padder {
height: 0;
/* last padding dimension is (100 * height / width) of item to be scaled */
padding: 0 0 56.25%;
position: relative;
/* only need next 2 rules if other rulesets change these */
margin: 0;
width: auto;
}
.whatever-needs-the-fixed-aspect {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
/* for demo */
border: 0;
background: white;
}
<div class="fixed-aspect-wrapper">
<div class="fixed-aspect-padder">
<iframe class="whatever-needs-the-fixed-aspect" src="/"></iframe>
</div>
</div>

None of these solutions worked for me inside a Weebly "add your own html" box. Not sure what they are doing with their code. But I found this solution at https://benmarshall.me/responsive-iframes/ and it works perfectly.
CSS
.iframe-container {
overflow: hidden;
padding-top: 56.25%;
position: relative;
}
.iframe-container iframe {
border: 0;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
/* 4x3 Aspect Ratio */
.iframe-container-4x3 {
padding-top: 75%;
}
HTML
<div class="iframe-container">
<iframe src="https://player.vimeo.com/video/106466360" allowfullscreen></iframe>
</div>

Related

How to keep video and lesson menu same height

I'm trying to do a video layout like the following:
The video embed will be with an iframe. I'd like to keep the height of lesson items on the left to be same height as the video and to have different container on the bottom that comes after the video and lesson container.
html
<div>
<div class='container'>
<div class='video-container'>
<iframe class='iframe' src="https://www.youtube.com/embed/I2UBjN5ER4s" width="640" height="360" frameBorder="0"
allow="autoplay; fullscreen" allowFullScreen title="https://player.vimeo.com/video/459785420">
</iframe>
</div>
<div class='menu-items'>
<div class='lesson'>
lesson menu
</div>
...
</div>
</div>
</div>
css:
.container {
display: flex;
height: 100px;
}
.video-container {
overflow: hidden;
padding-bottom: 56.25%;
height: 0;
position: relative;
outline: 1px solid black;
flex: 0 0 75%;
}
.iframe {
left:0;
top:0;
height:100%;
width:100%;
position:absolute;
}
.menu-items {
padding: 10px;
flex: 0 0 25;
}
.lesson {
padding-bottom: 20px;
}
I've created a codepen: https://codepen.io/cagaroos/pen/XWdoROw?editors=1100
try this
.video-container {
height: auto;
}
instead of
.video-container {
padding-bottom: 56.25%;
height: 0;
}
add bottom and right
.iframe {
bottom:0;
right:0;
}
remove padding-bottom of last lesson div
.lesson:last-child {
padding-bottom:0;
}
also remove width and height <iframe> tag in html
Codepen demo

Cropping the top 10% of an image using CSS?

How to crop the top of an image has already been described in this question. However, I am trying to crop an image by a percentage when the image dimensions are not known ahead of time. The container's resulting height should then be dependent on the size of the image.
Using the following, I can crop the top of an image, but it requires manually specifying the amount of the image to show in pixels. Is there a way I can specify I want to crop the top 10% of the image without knowing the image size ahead of time?
.container {
overflow: hidden;
position: relative;
height: 370px;
}
.container img {
position: absolute;
margin-left: auto;
margin-right: auto;
bottom: 0;
left: 0;
right: 0;
}
<div class="container">
<img class="img" src="http://placekitten.com/400/500" />
</div>
Here is an idea that rely on scale. You keep the image in-flow (don't use position:absolute) then you scale the container by 0.9 which is 90% of the total height then you scale the image by 1.1 to keep it's original size. This will trim the image by 10% but since transform is only a visual effect you may have space at the top or the bottom of the container (based on the transform-origin)
.container {
overflow: hidden;
outline:1px solid red;
display:inline-block;
}
.container img {
display:block;
}
.cut {
transform:scaleY(0.9);
transform-origin:top; /* The extra space will be on the bottom*/
}
.cut img {
transform:scaleY(1.1);
transform-origin:bottom; /* This should be bottom to cut the top*/
}
<div class="container">
<img class="img" src="http://placekitten.com/300/200" >
</div>
<div class="container cut">
<img class="img" src="http://placekitten.com/300/200" >
</div>
To be more precise we can consider calc() like below:
.container {
overflow: hidden;
outline:1px solid red;
display:inline-block;
}
.container img {
display:block;
}
.cut {
transform:scaleY(0.9);
transform-origin:top; /* The extra space will be on the bottom*/
}
.cut img {
transform:scaleY(calc(1/0.9));
transform-origin:bottom; /* This should be bottom to cut the top*/
}
<div class="container">
<img class="img" src="http://placekitten.com/300/200" >
</div>
<div class="container cut">
<img class="img" src="http://placekitten.com/300/200" >
</div>
I think the best approach to this without Javascript would be to translate the image up a certain percent, then scale it to fill the original height of the container. Anything else will leave a gap at the bottom.
.img_container img {
transform: translateY(-50%) scale(2);
}
https://jsfiddle.net/amoliski/n4ojdzyr/
This should do the trick, using translateY (got that from How can I get the height of an element using css only)
As you can see, the .container does not have a hardcoded height, however, it will load with the original image height, which is 500px, even though the image is loading as 450px (500px - 10%)
.container {
overflow: hidden;
position: relative;
}
.container img {
margin-left: auto;
margin-right: auto;
bottom: 0;
left: 0;
right: 0;
transform: translateY(-10%);
}
<div class="container">
<img class="img" src="http://placekitten.com/400/500" />
</div>
You can do this with a little bit of JavaScript (I've inlined it for simplicity's sake but you could move it to it's own function)
<div class="container">
<img class="img" src="http://placekitten.com/400/500" onload="javascript:this.parentElement.style.height = (this.height * 0.9)+'px';" />
</div>
Here's a working JSfiddle.
An alternative would be to use the top CSS property in a negative fashion on a relative image like the snippet below. This works for an image of an arbitary width and height. Just adjust your top value, accordingly.
html,body{ height:100%; margin:0; padding:0; }
.container {
overflow: hidden;
position: relative;
height: 100%;
width: 100%;
display:flex;
margin-bottom: -10%;
align-items:center;
justify-content:center;
}
.container img {
position: relative;
bottom: 0;
left: 0;
height: 100%;
top: -10%;
right: 0;
}
<div class="container">
<img class="img" src="http://placekitten.com/400/500" />
</div>
To remove the extra bottom margin, just subtract the margin-bottom equal to the amount you subtracted from the top. Here it is margin-bottom: -10%;
Adjust the top value according to your dynamic images. Also note, I added height:100% to your container so you can see the full image but the top part is cropped. I used flex for centering. Test for another image but this time, it is cropped 50% from the top
html,body{ height:100%; margin:0; padding:0; }
.container {
overflow: hidden;
position: relative;
height: 100%;
width: 100%;
margin-bottom: -50%;
display:flex;
align-items:center;
justify-content:center;
}
.container img {
position: relative;
bottom: 0;
left: 0;
height: 100%;
top: -50%;
right: 0;
}
<div class="container">
<img class="img" src="https://www.fujifilm.com/products/digital_cameras/x/fujifilm_x_t3/sample_images/img/index/ff_x_t3_002.JPG" />
</div>

Don't want iframe to take up 100% width after 759px

I have a problem with youtube iframe videos. I want the iframe to take up the 100% width of the page and maintain aspect ratio on mobile devices. I do not want the video to get bigger than its 560 width or 315 height. I then want the 2 videos to be displayed inline-block on a tablet and for the desktop. I want the iframes side by side on a tablet and desktop. I can't seem to figure this out. I have exhaustively searched this and can't find an answer that works. Here is my code.
HTML
<div class="video_responsive">
<div class="video-container">
<iframe width="560" height="315" src="https://www.youtube.com/embed/9_zGXEmNKPo" frameborder="0" allowfullscreen></iframe>
</div>
<div class="video-container">
<iframe width="560" height="315" src="https://www.youtube.com/embed/zEI8CT7cElQ" frameborder="0" allowfullscreen></iframe>
</div>
</div>
CSS
.video_responsive{
padding-left: 1em;
padding-right: 1em;
}
.video-container{
position: relative;
padding-bottom: 56.25%;
padding-top: 35px;
margin-top: 20px;
height: 0;
overflow: hidden;
}
.video-container iframe{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
Any help would be appreciated. I am doing this for a class. Professor has no idea how to fix this problem. Thanks
Update 2
OP mentioned an interest in tables. Although they can make a layout simple, it's not meant for layout, they're meant to represent data. Fortunately, there's are several display values that allow an element to behave like a table. On both demos, when in desktop mode, the posters (images displayed when video is idle) overlap and are distorted, but the video isn't.
The most important ones are:
table element will behave like <table>
table-row element will behave like <tr>
table-cell element will behave like <td>
Here's an article with tips on how to use display: table
This Plunker is using display: table/table-cell
Update 1
The code editor on this site isn't good for complex CSS so I moved the demo over to Plunker
Summary
2 major properties in use are:
media query
flexbox
Mobile mode 758px or less in width for viewport
flexbox layout is stacked (flex-flow: column nowrap)
Desktop mode 759px or more in width for viewport
media query triggers at 759px or more
flex-flow is now row nowrap
Use media query:
#media only screen and (min-width: 759px) {
.video_responsive {
display: table;
}
.video-cpntainer {
display: table-cell;
max-width: 45vw;
}
.video_responsive {
padding-left: 1em;
padding-right: 1em;
}
.video-container {
position: relative;
padding-bottom: 56.25%;
padding-top: 35px;
margin-top: 20px;
height: 0;
overflow: hidden;
}
.video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#media only screen and (min-width: 759px) {
.video_responsive {
flex-flow: row nowrap;
}
.video-container {
min-width: 380px;
max-width: 48vw;
min-height: 214px;
max-height: 27vh;
}
}
<div class="video_responsive">
<div class="video-container">
<iframe width="560" height="315" src="https://www.youtube.com/embed/9_zGXEmNKPo" frameborder="0" allowfullscreen></iframe>
</div>
<div class="video-container">
<iframe width="560" height="315" src="https://www.youtube.com/embed/zEI8CT7cElQ" frameborder="0" allowfullscreen></iframe>
</div>
</div>
In your CSS set max-width: 759px; for your iframe.

oversized image centering with max-width and max-height

I have an img tag which contains an image and needs to be reduced to either max-width: 200px or max-height: 200px, which depends on whether the image is tall or wide. The current code I have:
CSS:
div#music_artwork {
position: relative;
width: 200px;
height:200px;
background:#eee;
}
.img-container {
position: relative;
overflow: hidden;
width:200px;
height:200px;
}
img {
position: absolute;
top: -9999px;
bottom: -9999px;
left: -9999px;
right: -9999px;
margin: auto;
}
HTML:
<div id="music_artwork">
<div class="img-container">
<img class="first" src="http://entertainmentmv.nl/wp-content/uploads/2014/06/breaking-1.png">
</div>
</div>
You'll see two containers which contain images. One of them is tall, one of them is wide. I'm looking for a way to combine these codes, without JavaScript.
Code in JSFiddle (http://jsfiddle.net/L9BnL/298/
)
There is currently no way for CSS to detect orientation of an image and to apply different rules based on that information. However, if you are able to alter your HTML and use background-images instead of img tags, this can easily be resolved by using background-size: cover;. Also, the required total CSS is much clearer.
Please not: this currently works in Chrome and Opera, only, with partial support in Safari. Firefox and IE do not support that feature, yet. See http://caniuse.com/#search=cover for more information.
.img-container {
width: 200px;
height: 200px;
margin: 20px;
background-size: cover;
}
<div class="music_artwork">
<div class="img-container" style="background-image: url('http://entertainmentmv.nl/wp-content/uploads/2014/06/breaking-1.png');">
</div>
</div>
<div class="music_artwork" style="margin-top:20px;">
<div class="img-container" style="background-image: url('http://cdn1.sciencefiction.com/wp-content/uploads/2013/08/Bryan-Cranston.jpg');">
</div>
</div>

img { max-height: 100%; } causes img to exceed bounds

Is this a Chrome bug?
Here's the HTML:
<div><img src="test.png"></div>
Here's the CSS:
* { box-sizing: border-box; }
div { height: 200px; padding: 75px 0 60px; }
img { max-height: 100%; }
Expected result: The img should have a height of 65px.
Result in Chrome (v. 27.0.1453.116) on Mac OS (v. 10.6.8): The img has height of 135px and "bleeds" into the parent div's padding. If I change the padding of the div to 50px 0, oddly it renders properly.
Play with this in a codepen: http://codepen.io/anon/pen/jhbKz
Screenshots:
First block has padding of 50px 0. Second block has padding of 75px 0 60px.
Firefox (correct result)
Chrome (wrong?)
Try adding a container to your Image with width and height of 100%. This will give you the same output on chrome and FF.
<div class="b">
<div style='height:100%;width:100%;'>
<img src="some image url">
</div>
</div>
I cannot explain why this fix works currently, but I myself am trying to reason with it.
Years later, the issue seems to have spread to Firefox.
Pav's workaround did not work for me, maybe because I have "a" not "div". The only way in my case was to display as table:
<div style="display: table;">
<a style="height: 100px; display: table-cell;" href="#">
<img style="max-height: 100%; width: auto;" src="some image url">
</a></div>
An additional benefit of "table" is that vertical-align: middle; can be used to center the image (or other content) vertically.
You can achieve it using position: absolute for your image.
<div class="wrap">
<img class="img" src="https://cdn.photoswipe.com/photoswipe-demo-images/photos/1/img-2500.jpg" alt="">
</div>
body {
height: 100vh;
}
.wrap {
display: inline-block;
position: relative;
max-height: 500px;
height: 100%;
width: 100%;
background: rgba(0,0,0,0.1);
}
.img {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
height: 100%;
}
jsfiddle

Resources