This is a tricky question to word correctly, so I created a Fiddle to more accurately represent what I'm trying to do:
http://jsfiddle.net/LAtPJ/
.thumbnailContainer.video_embed
{
position: relative;
padding-bottom: 56.25%;
padding-top: 30px;
height: 0;
overflow: hidden;
}
.thumbnailContainer.video_embed iframe
{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
The above code works perfectly for very nice, responsive YouTube videos. But...
If you imagine this in the context of a media gallery where images and videos should co-exist in a completely responsive design.
There will be rows and rows of media, and there is likely to be a difference in aspect ratio between the images and the videos and so therefore we're left with something that is no longer uniform.
Effectively, the YouTube video should be 100% wide, but it's height should be no taller and no shorter than that of the images. I previously had a version of this that was all fixed widths and heights so quite simply every image and every iframe was 200 x 200. Now, I want something more mobile friendly so although images I have exactly how I need them, videos are not.
Any ideas?
The end solution (if there is one) should preferably be CSS only and not necessarily specific to YouTube (some of the videos will be other services, but mostly rendered via an iframe like YouTube).
You guys are awesome so hopefully you'll come up with something cool. Thank you so much.
100% height is challenging, as you can see here: How to Force Child Div to 100% of Parent's Div Without Specifying Parent's Height?
Your best bet might be to use jQuery, if that's an option.
You might try giving both the .thumbnailContainer and .thumbnailContainer.video_embed iframe classes a min- and max-height. This is untested on mobile, of course, and I'm not certain how aspect ratio would be affected for non-responsive video embeds. Hope this helps.
DEMO here. Code snippet below:
.thumbnailContainer
{
overflow: hidden;
position: relative;
width: 100%;
min-height: 200px;
max-height: 200px;
}
.thumbnailContainer.video_embed iframe
{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
min-height: 200px;
max-height: 200px;
}
I thought it might be useful to document how I've decided to do this.
#ivarPrudnikov kindly suggested grabbing the YouTube thumbnails from the API. Something I had considered already, but, of course, it doesn't really matter whether the thumbnail container contains an iframe, text, or indeed an image, the same problem exists.
There's no straight forward way of keeping that container the same size as the other containers without there being an image in there of the exact aspect ratio.
There may be other ways... but I was beginning to feel they were too complicated, would be difficult to manage going forward and perhaps suffer from compatibility issues with certain browsers.
So, I've resorted to doing everything server side.
It's all written in PHP anyway, so I actually pass the YouTube video ID to a PHP script, fetch the thumbnail directly from YouTube and then I crop and resize it based on the desired thumbnail width. height and aspect ratio.
That all happens on the fly. I will more than likely implement some sort of basic caching mechanism whereby I actually save the image locally eventually.
Until then, problem solved and I thank you so much to everyone who too the time to answer and/or comment.
Much appreciated, always!
Chris
This is what I use. It sets the padding based on the embed width and height attribute and calculates the aspect ratio.
As long as you have 2 divs around the iframe (you can tweak for embed) and the width and height set as an attribute in the iframe, this will work.
jQuery(document).ready(function() {
jQuery('.embed-wrapper').each(function(){
dcembedheight = jQuery('iframe', this).attr( "height" );
dcembedwidth = jQuery('iframe', this).attr( "width" );
ratio = ((dcembedheight/dcembedwidth)*100).toPrecision(4) + '%';
jQuery(this).attr("style" , "max-width:"+ dcembedwidth + "px");
jQuery('.embed-container', this).css({"padding-bottom": ratio});
});
});
HTML - exclude embed-wrapper for 100% width and to only use the css in 16:9 ratio
<div class="embed-wrapper">
<div class="embed-container">
<iframe src="//giphy.com/embed/BVNbHPjIfSNOw" width="480" height="480" frameborder="0" allowfullscreen="allowfullscreen"></iframe>
</div>
</div>
CSS - notice that the padding is set by the jquery but the css contains default 16:9 ratio padding
.embed-container {
position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%;
}
.embed-container iframe, .embed-container object, .embed-container embed {
position: absolute; top: 0; left: 0; width: 100%; height: 100%;
}
Related
UPDATE:
The idea behind my attempts so far has been focused on adjusting the iframe container and fixing it based on the intrinsic ratio of the Iframe so that it would then as it responds to change in proportion the contents would also change proportionally. This does not seem to work as some elements of the iframe remain fixed. I would really like to have a responsive Strava Iframe but for some reason cannot figure out to achieve this. I have made a Codepen Collection with current attempts thus far.
I have recently added a shortcode for embedding Strava iframes into my Hugo site (academic theme). On the desktop, devices the iframes render properly and appear to be responsive in browsers, yet on mobile devices, this isn't the case. The issue at hand can be seen on this webpage and my GitHub repo. I would be very grateful for any help in resolving this.
I have been trying multiple tried CSS tweaks and variation recommended on the Hugo forum and on other online sources.
Current Shortcode:
{{ if and (.Get "id") (.Get "hash") }}
<div class="responsive-object">
<iframe height='405' width='590' frameborder="0" allowtransparency='true' scrolling='no' src="https://www.strava.com/activities/{{ .Get "id" }}/embed/{{ .Get "hash" }}"></iframe>
</div>
{{ end }}
Current CSS:
.responsive-object iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.responsive-object {
position: relative;
padding-bottom: 67.5%;
height: 0;
margin: 10px 0;
overflow: hidden;
}```
Despite trying to make the iframe container responsive, the same result occurs where it seems responsive on desktop browsers yet not on mobile devices. I am unsure of how to proceed from this point, or if I am missing something.
Do you add <meta name="viewport" content="width=device-width, initial-scale=1.0">
To your <Head> ?
If yes imma gonna edit my post with the solution :)
EDIT
The best article I've found thus far on creating responsive iframes is How To Make Responsive Iframes - It's Easy!.
There are three salient points:
Set no attributes in the iframe opening tag, specifically not width and height
Put a div container around the iframe, and use CSS height: 0; and then padding-bottom: nn%; to give the container a height expressed as the height:width ratio as a percentage.
Style the div inline with -webkit-overflow-scrolling: touch and overflow: auto which are necessary to handle scrolling on mobile devices and are unstable in CSS.
This code works for me:
// HTML (in an embed block, not a code block)
<div class="iframe-container iframe-container-for-wxh-500x350" style="-webkit-overflow-scrolling: touch; overflow: auto;">
<iframe src="http://www.targetWebsiteURL.com"> <p style="font-size: 110%;"><em><strong>IFRAME: </strong> There is iframe content being displayed here but your browser version does not support iframes.</em> Please update your browser to its most recent version and try again.</p> </iframe>
</div>
// CSS
.iframe-container { position: relative; margin: 5px; height: 0; overflow: hidden; }
.iframe-container-for-wxh-500x350 {
padding: 25px 25px 70% 25px; /* padding-bottom = h/w as a % */
}
.iframe-container iframe {
position: absolute;
top: 0;
left: 0;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
border: 1px inset #7a8b8b;
/* put following styles (necessary for overflow and
scrolling handling) in div container around iframe
because not stable in CSS
-webkit-overflow-scrolling: touch;
overflow: auto; */
} Use a separate class to style the padding-bottom so that, if you have more than one iframe and they are of differing wxh ratios, all you have to do is code a class for each and set padding-bottom to the different percentages.
To have responsive images that scale down proportionally on a small screen, I currently use max-width: 100%; (or a fixed max width). As opposed to specifying a fixed size, this has a terrible downsize in that when the page is loading, the browser allocates no space for the image and can only do that after it starts downloading it. This causes a lot of layout reflows and a bad experience before all images are loaded.
This seems like it could be easily fixed - after all, I just have to tell the browser what the real size is so that it can figure out the aspect ratio and the final size before downloading it. First, I was wondering if that's what the width and height html attributes are for, but I know that that's not their purpose as they can be used to rescale the image and change the final size.
What I really want is something like "srcwidth" and "srcheight" that would tell the browser the actual size of the image file so that it doesn't have to load before knowing the aspect ratio to make use of the max-width styling. But from what I could find, there is no such thing like these attributes. Is there really no way to achieve this?
I tried using the actual width and height html attributes in this way and then overriding it with CSS, but browsers simply don't care about that.
The most common way I've seen this addressed is to put all your images in containers and use the padding-bottom property to "pre-allocate" the height.
<div class="responsive-container">
<img src="image.jpg"/>
</div>
To do this, you need to know the aspect ratio of the image to calculate the padding.
Using the Aspect Ratio to work out the height
For example, for an aspect ratio of 16:9 (e.g. 800 x 450px) the height is 56.25% of the width so that will be the value for the padding.
.responsive-container {
width: 100%;
padding-bottom: 56.25%; /* 9/16 = aspect ratio of image */
position: relative;
height: 0;
overflow: hidden;
}
.responsive-container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
}
Different Aspect Ratios
If your images will have different aspect ratios, but you will still know then ahead of time, you set up different classes for each, e.g.
.responsive-container {
width: 100%;
position: relative;
height: 0;
overflow: hidden;
}
.ratio-16-9{
padding-bottom:56.25%; /* 9/16*100 */
}
.ratio-4-3{
padding-bottom:75%; /* 3/4*100 */
}
.ratio-1-1{
padding-bottom:100%;
}
And to use it in the html:
<div class="responsive-container ratio-16-9">
<img src="image.jpg"/>
</div>
Calculate height dynamically
Finally, if you want the CSS to calculate the height dynamically for each image, you can use CSS calc() to calculate the height like this:
calc((image_height/image_width)*100%)
So your CSS would be:
.responsive-container {
width: 100%;
position: relative;
height: 0;
overflow: hidden;
}
And you use it like this:
<div class="responsive-container" style="padding-bottom: calc((426/640)*100%);" >
<img src="image.jpg"/>
</div>
References
Responsive images – how to prevent reflow
Responsive Images Without Browser Reflow
MDN Web Docs for CSS calc()
So, I'm having quite a bit of a problem in making my iframes work in mobile devices. It's only covering about a half or more of the screen. I suspect it is because of some lines of css I put in my iframes.
.Wrapper2 {
position: relative;
padding-bottom: 56.25%; /* 16:9 */
padding-top: 25px;
height: 0;
}
.Wrapper2 iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
I would also like to add that for my text, I am using viewport sizing(vw, vh, vmin, vmax) if that would be of any help as I am also getting problems with long blocks of texts producing scrollbars. I also think (???) that it may have to do something with my iframe css and/or text sizing. What would be the necessary change that I need to implement? Thank you in advance!
Please post your html to make it easier for us to understand what the problem is.
Try this -- If you look into your iframe in html then you'll find :
<iframe width="560" height="315" src="https://www.youtube.com/embed/HDI9inno86U" frameborder="0" allowfullscreen></iframe>
So, there's width & height already defined inside the iframe element. All you have to do i change it to width="100%";
I wanted to make a Tumblr theme with various post widths to choose from, setting video posts up has been quite difficult because of this.
This code:
.video-container {
position: relative;
padding-bottom: 56.25%;
padding-top: 30px;
height: 0;
overflow: hidden;
}
.video-container iframe,
.video-container object,
.video-container embed {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
and
{block:Video}
<div class="video-container">
{Video-500}
</div>
{block:Caption}
{Caption}
{/block:Caption}
{/block:Video}
works flawlessly with YouTube videos, but it trims down Tumblr hosted videos.
Latest default Tumblr theme Optica has something that makes this work, meaning Tumblr hosted videos stay of their original height, but I don't know what... Could anyone help with this? Not necessarily the same way this works in Optica theme, just... Any way?
Sadly Tumblr doesn't seem to follow a specific aspect ratio for its videos, unlike Youtube.
padding-bottom: 56.25% gives you an aspect ratio of 16:9 (http://css-tricks.com/fluid-width-youtube-videos/).
Each Tumblr video may have a different aspect ratio, so each one will need a different padding-bottom value.
Simplest solution would be to use fitVids.js:
jQuery version: http://fitvidsjs.com/
Javascript version: https://github.com/rosszurowski/vanilla-fitvids
You can roll your own, the source of either version explains pretty well what is needed to make the calculation.
Enable Tumblr Videos with Fitvids.js
The src is a little different for videos host by Tumblr. They do some javascript magic.
$(".videos").fitVids({ customSelector: "iframe[src='about:blank']"});
I'm currently trying to have an iframe fit the size of my screen, and any other user using it at different resolutions, except no matter what I try I'll either end up with the iframe being too small or the height being too large causing a double scroll bar. (The iframe and the page itself having scroll bars).
My objective is having the iframe fit only 85% width of the page (which works!), 100px from the top of the screen (also works), and then for the bottom to fit the edge of the bottom of my browser (that's where I'm stuck...)
HTML
<div id="maindiv" class="maindiv">
<iframe id="theiframe" class="iframeautowidth" seamless src="http://whateverdomain.com></iframe>
</div>
CSS:
.maindiv {
width: 85%;
top: 100px;
}
.iframeautowidth {
left: 0px;
top: 0px;
bottom: 0px;
width: 85%;
height: 100%;
border: 0
overflow: hidden;
display: block;
margin: 0;
float: left;
}
If it counts for anything, I have the latest jquery running on my page if it'll help. Thanks in advance!
Use the onload() event of your iframe and the onresize() event of the window to resize the iframe to the required size.
This Microsoft Support article explains it well.
FYI, in javascript screen.width & screen.height will give you the screen resolution.
If you had Fx4, a simple height: -moz-calc(100%-100px) would work a wonder. A pity this feature is introduced and supported so late in CSS3.
If the 100px top is for tabs navigating the iframe, there may be a workaround. Just fill up your iframe to 100% height and then put those tabs inside the iframes as another iframe with a fixed size. Or just resort to frameset.
Whether this works for you or not depends on your exact design, but hope that helps.