Recognize CSS orientation in iFrame - css

Is it possible that an iframe can recognize the orientation of its parent website? At the moment the css media query is only working at my parent site.
I tried to fix this issue by sending a post message to my iframe and change the linked css file with javascript:
parent site:
window.addEventListener("orientationchange", function(){
var iframe = document.getElementById("plan_iframe");
iframe.contentWindow.postMessage({orientation: window.orientation}, iframe.src);
}, false)
iframe:
<link id="changing_css" rel="stylesheet" type="text/css" href=""/>
[...]
window.addEventListener("message", function(e){
var newOrientationValue = e.data.orientation;
if(newOrientationValue == 90 || newOrientationValue == -90){
document.getElementById('changing_css').href="css/vertretung_ios_landscape.css";
}
else{
document.getElementById('changing_css').href="css/vertretung_ios_portrait.css";
}
}, false)
This fix is very slow because javascript needs some time to load the file "onorientationchange" and apply the changes.
How does css recognizes the orientation?

In my case, I had control over the parent window. I solved this by putting an additional media query on the parent container's iFrame styles. Turns out that the CSS media query for orientation simply goes by whichever property is greater. For example...
An iFrame of greater height will render in portrait orientation. width: 400px; height: 600px;
An iFrame of greater width will render in landscape orientation. width: 600px; height: 400px;

Related

Setting a minimum width to fit on responsive website

I'm making a fully responsive website but it's really handy to have a min-height of the site set to 480px, instead of "industry standard" 320px. I know meta tag viewport and this pretty much does the job for me on smallest screens:
<meta name="viewport" content="width=480, user-scalable=no">
But this works only for a mobile, any device with screen reporting more than 480px isn't scaled properly. For these, this one works:
<meta name="viewport" content="width=device-width, user-scalable=no">
Is there please a way how to combine both these? Somehow set smallest possible width of the site with no regards to the actual screen size but use any higher value of screen that 480px.
Thanks a lot, Jakub
Use the latter meta viewport value and simply set the min-width CSS property for the body or your container element to be the 480px value you require and set the width to 100%. The min-width will override the width value (as you would expect) when the 100% width falls below 480px.
I'd strongly recommend that you set box-sizing: border-box so you can add padding to your body or container without exceeding the total 100% screen width.
Please also note that disabling user scaling ("user-scalable=no") is poor user experience for many users, and in particular for those with accessibility needs. I'd suggest you set initial-scale=1 instead. See http://dev.opera.com/articles/view/an-introduction-to-meta-viewport-and-viewport/
The final result should look something like this-
<meta name="viewport" content="width=device-width, initial-scale=1">
CSS-
#container {
-webkit-box-sizing: border-box;
box-sizing: border-box;
min-width: 480px;
padding: 20px;
width: 100%;
}
This will limit the mobile version to 520px;
<meta name="viewport" id="vp" content="user-scalable=no, width=520, initial-scale=0.5, maximum-scale=0.5">
<script>
window.onload = function() {
if (screen.width > 520) {
var mvp = document.getElementById('vp');
//mvp.setAttribute('content','');
mvp.setAttribute('content','width=device-width, initial-scale=1');
}
}
</script>
I'm not sure about the answer with container min-width, because Chrome mobile preview not understands it. Adding this hack(jQuery used):
jQuery(function($){
let upgradeViewport = function(){
let viewport = $('meta[name=viewport]');
let viewportMinWidth = parseInt($('head').attr('data-viewport-width'));
if (viewport.attr('content').indexOf('user-scalable=0')!=-1 || viewport.attr('content').indexOf('user-scalable=no')!=-1){
return;
}
if (!upgradeViewport.original) upgradeViewport.original = viewport.attr('content');
if(window.innerWidth <= viewportMinWidth) {
viewport.attr('content', 'width='+viewportMinWidth);
}else{
viewport.attr('content', upgradeViewport.original);
}
};
$(document).ready(upgradeViewport);
$(window).resize(upgradeViewport);
});
will dynamicly change viewport meta tag by the value in attribute data-viewport-width of head . Working fine, also with mobile-previewers.
First thing it is better to go with % rather than fixing the width=480px.(Example:- min-width: 45%). And the screen will automatically adjust itself based on the screen resolution.

Auto height content in an iframe (CORS?)

I am working with a client. Their webpage is using this DOCTYPE
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
I need to deliver content to pages on their site. My content looks like this
<div style="height:1000px">
<iframe frameborder="0" src="..." width="550" height="220"></iframe>
<br/>
<br/>
<iframe frameborder="0" src="..." width="550" height="220"></iframe>
</div>
I can place the content on the clients page by giving them a couple of lines of css, and, currently, and iframe:
<style>
.iframecontent
{
background-color:blue;
position: relative;
height: 100%;
width: 100%
}
</style>
<iframe class="iframecontent" frameborder="0" src="..." width="100%" scrolling="no"> </iframe>
Because the height of the content is dynamic, I cannot provide a specific height to the client - instead I need it to stretch.
I've read many posts, but am still not sure of the best way to do this. Possibly CORS? Something else?
Here is one solution offered: http://sly777.github.com/Iframe-Height-Jquery-Plugin/ - it works on the same domain, but for cross-domain talk it relies on PostMessage which is an HTML 5 thing.
I've tried http://blog.johnmckerrell.com/2006/10/22/resizing-iframes-across-domains/ but have not be able to get it to work.
I might just get the client to set the frame to 1500px so that it should fit whatever I choose to be in the content and be done with it, but is there a better way?
Could you just set the html,body{height:100%;} then your iframe{height:100%}?
A percentage height is directly dependant on it's parent's height (of a block element). ie: iframe is 100% of what? In this case, it's parent is the body.
You may use the postMessage Plugin http://benalman.com/projects/jquery-postmessage-plugin/
It enables you to post messages from inside an iframe to the parent element. In combination the the setInterval javascript function you may send the current needed size to the parent element.
Inside the iframe
var currentIframeSize = 0;
window.setInterval(function() {
var size = $('body').outerHeight(true);
//just post, if the size has changed
if ( currentIframeSize != size ){
currentIframeSize = size;
$.postMessage({if_height : size}, source_url, parent);
}
}, 1000); //do that every second
In the head section of the parent element
id = "theIdOfYourIframe";
$.receiveMessage(function(e){
var rec_height = Number( e.data.replace( /.*if_height=(\d+)(?:&|$)/, '$1' ) );
if ( !isNaN( rec_height ) && rec_height > 0 && rec_height !== current_height ) {
current_height = rec_height;
$('#' + id).height(rec_height);
}
});
Based on those two snippets, you should get your problem solved
I updated my plugin that you tried (http://sly777.github.com/Iframe-Height-Jquery-Plugin/) and i added tutorial how to use this plugin for cross-domain fix. I hope it helps.

How to set up twitter's embedded timeline width in percentage (responsive/fluid design)

I'm looking to set up twitter's embedded timeline, it's quite easy when you're having a fixed design, but that's not my case and I'm actually building a fluid and responsive design for a new website.
My question is, how can I set up twitter's embedded timeline with a fluid width since its an iframe and you're supposed to set up the with in px in your twitter account ?
Thanks :)
This seems to work for me:
#twitter-widget-0 {
width:100%;
}
where #twitter-widget-0 is the iframe it generates, placed in an appropriately-styled container.
It's not perfect: the widget generates its contents a bit differently depending on width, and margins, etc. won't be exactly the same after resizing; but this seems minor.
I'm curious as to why simple CSS didn't work for you - sorry if I'm missing something.
Thanks to all of you I found my way through:
It was almost as lack said, but we had to focus on the iframe instead:
.MyClassForTheDivThatContainTheiFrame iframe{
width:100%;
}
of course .MyClassForTheDivThatContainTheiFrame is also fluid with a % width
This logic will work to change at least the width and height:
#twitter-widget-0, #twitter-widget-1 {
float: none;
width: 100% !important;
height: 250px !important;
}
The only problem with shortening the height is that it hides the text box for people to send tweets but it does shorten the height. My guess is that if you want to add other CSS styling you can just put the !important clause. I also assume that if you have three widgets you would define #twitter-widget-2, etc.
Super hacky, but you can also do this :
<script type="text/javascript">
var checkTwitterResize = 0;
function resizeTwitterWidget() {
if ($('#twitter-widget-0').length > 0) {
checkTwitterResize++;
if ($('#twitter-widget-0').attr('width') != '100%') checkTwitterResize = 0;
$('#twitter-widget-0').attr('width', '100%');
// Ensures it's checked at least 10 times (script runs after initial resize)
if (checkTwitterResize < 10) setTimeout('resizeTwitterWidget()', 50);
} else setTimeout('resizeTwitterWidget()', 50);
}
resizeTwitterWidget();
</script>
This was a helpful thread, thanks. I'm working on a site that uses an older Twitter profile Widget, which I find easier to customise. So an alternative method, uses this to display the feed (customised to suit):
<script>
new TWTR.Widget({
version: 2,
type: 'profile',
rpp: 5,
interval: 6000,
width: 300,
height: 400,
theme: {
shell: {
background: 'transparent',
color: '#151515'
},
tweets: {
background: 'transparent',
color: '#151515',
links: '#007dba'
}
},
features: {
shell: false,
scrollbar: true,
loop: false,
live: true,
hashtags: true,
timestamp: true,
avatars: true,
behavior: 'all'
}
}).render().setUser('BlueLevel').start();
</script>
Then override the width by adding this to your stylesheet:
.twtr-doc {
width:100% !important;
}
You can see the various classes to modify by using IE9 in compatibility mode, then using F12 Developer Tools to see the html/css.
Hope that helps someone!
You can give your iframe a class, and try to apply CSS to it. At least to change the width to %.
This is not possible. You can set an exact width and height using the html width and height in the anchor tab. Other than that you are out of luck. No responsive or fluid capabilities.
It also has a min-width of 220px and a max-width of 520px.
<a class="twitter-timeline" width="520" height="700" data-dnt=true href="https://twitter.com/vertmob" data-widget-id="WIDGET_ID_HERE">Tweets by #vertmob</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
If you absolutely must do a fluid, you can code a javascript that changes that iframe's width after a resize event or using some javascript timers.
Can we see some code of yours to make some js code for this?
Attribute selector should work:
iframe[id*="twitter-widget"] {
width: 100%;
}
More here.

Responsive design on site that is viewed via an iframe

I am working on an app that will be deployed to Facebook therefore viewed from an iframe inside of Facebook's chrome.
I have some basic media queries that linearise the content at a set viewport size.
When the site is viewed in the browser locally the media queries work fine but when tested inside Facebook's chrome then they do not work.
I assume that the resizing of the viewport is not detected by the child of the iframe therefore the media queries will have no effect. Is there a way to get this working?
You could add a little jQuery to detect a window resize and then swap out a separate stylesheet.
$(window).resize(function(){
var currentWidth = $(document).width();
var allStyleSheets = $("link");
allStyleSheets.each(function(){
var $this = $(this);
//assume sheet1.css is for pages with widths equal and over 700 and sheet 2 is for widths under 700px
if(currentWidth >= 700 && $this.attr("href").indexOf("sheet2.css") > 0){
$this.remove();
$(head).append('<link href="sheet1.css" type="text/css" rel="stylesheet" />');
}
if(currentWidth < 700 && $this.attr("href").indexOf("sheet1.css") > 0){
$this.remove();
$(head).append('<link href="sheet2.css" type="text/css" rel="stylesheet" />');
}
});
});
As my adapted code was using media queries in a common CSS file, I prefer to toggle a fbIframe class on the body element, and add specific CSS rules in context of this class. The jQuery code thus becomes simpler:
function adaptToWindowSize(){
$("body").toggleClass("fbIframe", $(window).width() < 820);
};
$(window).resize(adaptToWindowSize);
$(adaptToWindowSize);

Iframe transparent background

My app has a modal dialog with an iframe inside it. I've written my jQuery code such that when the dialog opens, it sets the appropriate 'src' attribute of the iframe so the content loads up. However, during the delay between the dialog opening and the content loading, the iframe appears conspicuously as a white box. I'd prefer the iframe have a transparent background.
I've tried setting allowtransparency="yes" on the iframe. Any ideas? Thanks!
I've used this creating an IFrame through Javascript and it worked for me:
// IFrame points to the IFrame element, obviously
IFrame.src = 'about: blank';
IFrame.style.backgroundColor = "transparent";
IFrame.frameBorder = "0";
IFrame.allowTransparency="true";
Not sure if it makes any difference, but I set those properties before adding the IFrame to the DOM.
After adding it to the DOM, I set its src to the real URL.
<style type="text/css">
body {background:none transparent;
}
</style>
that might work (if you put in the iframe)
along with
<iframe src="stuff.htm" allowtransparency="true">
Set the background color of the source page to none and allow transparency in the iframe element.
Source page (for example, source.html):
<style type="text/css">
body
{
background:none transparent;
}
</style>
Page with iframe:
<iframe src="source.html" allowtransparency="true">Error, iFrame failed to load.</iframe>
Why not just load the frame off screen or hidden and then display it once it has finished loading. You could show a loading icon in its place to begin with to give the user immediate feedback that it's loading.
You need to make the iframe's body transparently. It works for me:
const iframe = document.createElement( 'iframe' );
iframe.onload = function() {
const doc = iframe.contentWindow.document,
head = doc.querySelector( 'head' ),
style = doc.createElement( 'style' );
style.setAttribute( 'type', 'text/css' );
style.innerHTML = 'body { background: transparent!important; }';
head.appendChild( style );
}

Resources