(This is a follow-up on my previous question if anybody is interested in the background story for entertainment purposes. It will probably not help you understand this question.)
Here are two elements <aside> and <main> who have got their width and height via JavaScript so that their combined width is the width of your screen (note that their display is inline-block). If you run this code in your web browser (a maximized browser so that the width of your browser equals the width of your screen) you might note that the body surprisingly does not properly fit the elements:
<!DOCTYPE html>
<html>
<body>
<aside></aside><!-- comment to remove inline-block whitespace
--><main></main>
<script>
var h = screen.height/100;
var w = screen.width/100;
var e = document.getElementsByTagName("aside")[0].style;
e.display = "inline-block";
e.backgroundColor = "lightblue";
e.width = 14*w + "px";
e.height = 69*h + "px";
e.marginRight = 0.5*w + "px";
e = document.getElementsByTagName("main")[0].style;
e.display = "inline-block";
e.backgroundColor = "green";
e.width = 85.5*w + "px";
e.height = 69*h + "px";
e = document.getElementsByTagName("body")[0].style;
e.margin = e.padding = "0";
e.backgroundColor = "black";
</script>
</body>
</html>
If you however give the JavaScript a delay, the elements are rendered properly. This suggests that the body somehow "needs time" to figure out its correct width:
<script>
setTimeout(function() {
[...]
}, 200);
</script>
It is also possible to give the body the specified width of screen.width instead of introducing the delay, by adding the following line. This supports the previous guess that the body does not immediately know its correct width (unless specified):
<script>
[...]
e.width = 100*w + "px";
</script>
Even though I have taken the freedom to throw wild guesses to explain this, I do not actually have a clue to what is going on.
Why are the elements not placed properly in the first place, and why do these two solutions work?
(Note: It is also possible to fix this by setting the whitespace of the body to nowrap with e.whiteSpace = "nowrap";, but I suspect this does not do the same thing as the other two. Instead of creating space for the elements inside the body, this simply forces the elements to be next to each other even though there is not enough room in the body.)
You should wait for the DOM to be available before running your code, see here: pure JavaScript equivalent to jQuery's $.ready() how to call a function when the page/dom is ready for it. That is possibly why setTimeout works. Also you should assign seperate variable names for your different elements.
// self executing function before closing body tag
(function() {
// your code here
// the DOM will be available here
})();
Is there a reason you are using Javascript and not CSS to accomplish this task? I suggest giving your elements css ids ie id="aside", then set your css styles:
html,body {
width: 100%;
height: 100%;
}
#aside {
display:inline-block;
position: relative;
float: left;
width: 14%;
height: 69%;
background: blue;
}
#main {
display:inline-block;
position: relative;
float: left;
width: 86%;
height: 31%;
background: azure;
}
I am loading an aspx web page in an iframe. The content in the Iframe can be of more height than the iframe's height. The iframe should not have scroll bars.
I have a wrapper div tag inside the iframe which basically is all the content. I wrote some jQuery to make the resize happen :
$("#TB_window", window.parent.document).height($("body").height() + 50);
where
TB_window is the div in which the Iframe is contained.
body - the body tag of the aspx in the iframe.
This script is attached to the iframe content. I am getting the TB_window element from the parent page. While this works fine on Chrome, but the TB_window collapses in Firefox. I am really confused/lost on why that happens.
You can retrieve the height of the IFRAME's content by using:
contentWindow.document.body.scrollHeight
After the IFRAME is loaded, you can then change the height by doing the following:
<script type="text/javascript">
function iframeLoaded() {
var iFrameID = document.getElementById('idIframe');
if(iFrameID) {
// here you can make the height, I delete it first, then I make it again
iFrameID.height = "";
iFrameID.height = iFrameID.contentWindow.document.body.scrollHeight + "px";
}
}
</script>
Then, on the IFRAME tag, you hook up the handler like this:
<iframe id="idIframe" onload="iframeLoaded()" ...
I had a situation a while ago where I additionally needed to call iframeLoaded from the IFRAME itself after a form-submission occurred within. You can accomplish that by doing the following within the IFRAME's content scripts:
parent.iframeLoaded();
A slightly improved answer to Aristos...
<script type="text/javascript">
function resizeIframe(iframe) {
iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
}
</script>
Then declare in your iframe as follows:
<iframe onload="resizeIframe(this)" ...
There are two minor improvements:
You don't need to get the element via document.getElementById - as you already have it in the onload callback.
There's no need to set the iframe.height = "" if you're going to reassign it in the very next statement. Doing so actually incurs an overhead as you're dealing with a DOM element.
Edit:
If the content in the frame is always changing then call:
parent.resizeIframe(this.frameElement);
from within the iframe after the update. Works for same origin.
Or to auto detect:
// on resize
this.container = this.frameElement.contentWindow.document.body;
this.watch = () => {
cancelAnimationFrame(this.watcher);
if (this.lastScrollHeight !== container.scrollHeight) {
parent.resizeIframeToContentSize(this.frameElement);
}
this.lastScrollHeight = container.scrollHeight;
this.watcher = requestAnimationFrame(this.watch);
};
this.watcher = window.requestAnimationFrame(this.watch);
I found that the accepted answer didn't suffice, since X-FRAME-OPTIONS: Allow-From isn't supported in safari or chrome. Went with a different approach instead, found in a presentation given by Ben Vinegar from Disqus. The idea is to add an event listener to the parent window, and then inside the iframe, use window.postMessage to send an event to the parent telling it to do something (resize the iframe).
So in the parent document, add an event listener:
window.addEventListener('message', function(e) {
var $iframe = jQuery("#myIframe");
var eventName = e.data[0];
var data = e.data[1];
switch(eventName) {
case 'setHeight':
$iframe.height(data);
break;
}
}, false);
And inside the iframe, write a function to post the message:
function resize() {
var height = document.getElementsByTagName("html")[0].scrollHeight;
window.parent.postMessage(["setHeight", height], "*");
}
Finally, inside the iframe, add an onLoad to the body tag to fire the resize function:
<body onLoad="resize();">
Add this to the iframe, this worked for me:
onload="this.height=this.contentWindow.document.body.scrollHeight;"
And if you use jQuery try this code:
onload="$(this).height($(this.contentWindow.document.body).find(\'div\').first().height());"
you could also add a repeating requestAnimationFrame to your resizeIframe (e.g. from #BlueFish's answer) which would always be called before the browser paints the layout and you could update the height of the iframe when its content have changed their heights. e.g. input forms, lazy loaded content etc.
<script type="text/javascript">
function resizeIframe(iframe) {
iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
window.requestAnimationFrame(() => resizeIframe(iframe));
}
</script>
<iframe onload="resizeIframe(this)" ...
your callback should be fast enough to have no big impact on your overall performance
There are four different properties you can look at to get the height of the content in an iFrame.
document.documentElement.scrollHeight
document.documentElement.offsetHeight
document.body.scrollHeight
document.body.offsetHeight
Sadly they can all give different answers and these are inconsistant between browsers. If you set the body margin to 0 then the document.body.offsetHeight gives the best answer. To get the correct value try this function; which is taken from the iframe-resizer library that also looks after keeping the iFrame the correct size when the content changes,or the browser is resized.
function getIFrameHeight(){
function getComputedBodyStyle(prop) {
function getPixelValue(value) {
var PIXEL = /^\d+(px)?$/i;
if (PIXEL.test(value)) {
return parseInt(value,base);
}
var
style = el.style.left,
runtimeStyle = el.runtimeStyle.left;
el.runtimeStyle.left = el.currentStyle.left;
el.style.left = value || 0;
value = el.style.pixelLeft;
el.style.left = style;
el.runtimeStyle.left = runtimeStyle;
return value;
}
var
el = document.body,
retVal = 0;
if (document.defaultView && document.defaultView.getComputedStyle) {
retVal = document.defaultView.getComputedStyle(el, null)[prop];
} else {//IE8 & below
retVal = getPixelValue(el.currentStyle[prop]);
}
return parseInt(retVal,10);
}
return document.body.offsetHeight +
getComputedBodyStyle('marginTop') +
getComputedBodyStyle('marginBottom');
}
Other answers were not working for me so i did some changes. Hope this will help
$('#iframe').on("load", function() {
var iframe = $(window.top.document).find("#iframe");
iframe.height(iframe[0].ownerDocument.body.scrollHeight+'px' );
});
Just in case this helps anyone. I was pulling my hair out trying to get this to work, then I noticed that the iframe had a class entry with height:100%. When I removed this, everything worked as expected. So, please check for any css conflicts.
I am using jQuery and the code below working for me,
var iframe = $(window.top.document).find("#iframe_id_here");
iframe.height(iframe.contents().height()+'px' );
You can refer related question here - How to make width and height of iframe same as its parent div?
To set dynamic height -
We need to communicate with cross domain iFrames and parent
Then we can send scroll height/content height of iframe to parent window
And codes - https://gist.github.com/mohandere/a2e67971858ee2c3999d62e3843889a8
Rather than using javscript/jquery the easiest way I found is:
<iframe style="min-height:98vh" src="http://yourdomain.com" width="100%"></iframe>
Here 1vh = 1% of Browser window height. So the theoretical value of height to be set is 100vh but practically 98vh did the magic.
All other answers are correct but what if the iframe has some dynamic content like a map that loads later and dynamically changes your iframe scroll height. This is how I achieved it.
var iFrameID = document.getElementById('idIframe');
intval = setInterval(function(){
if(iFrameID.scrollHeight == iFrameID.contentWindow.document.body.scrollHeight){
clearInterval(intval);
}else{
iFrameID.height = iFrameID.contentWindow.document.body.scrollHeight + "px";
}
},500)
I simply wrap the code inside setInterval which matches the iframe scroll height with iframe content scroll height then clear the interval.
in my project there is one requirement that we have make dynamic screen like Alignment of Dashboard while loading, it should display on an entire page and should get adjust dynamically, if user is maximizing or resizing the browser’s window.
For this I have created url and used iframe to open one of the dynamic report which is written in cognos BI.In jsp we have to embed BI report. I have used iframe to embed this report in jsp. following code is working in my case.
<iframe src= ${cognosUrl} onload="this.style.height=(this.contentDocument.body.scrollHeight+30) +'px';" scrolling="no" style="width: 100%; min-height: 900px; border: none; overflow: hidden; height: 30px;"></iframe>
I found the answer from Troy didn't work. This is the same code reworked for ajax:
$.ajax({
url: 'data.php',
dataType: 'json',
success: function(data)
{
// Put the data onto the page
// Resize the iframe
var iframe = $(window.top.document).find("#iframe");
iframe.height( iframe[0].contentDocument.body.scrollHeight+'px' );
}
});
To add to the chunk of window that seems to cut off at the bottom, especially when you don't have scrolling I used:
function resizeIframe(iframe) {
var addHeight = 20; //or whatever size is being cut off
iframe.height = iframe.contentWindow.document.body.scrollHeight + addHeight + "px";
}
This one is useful when you require a solution with no jquery. In that case you should try adding a container and set a padding to it in percentages
HTML example code:
<div class="iframecontainer">
<iframe scrolling="no" src="..." class="iframeclass"width="999px" height="618px"></iframe>
</div>
CSS example code:
.iframeclass{
position: absolute;
top: 0;
width: 100%;
}
.iframecontainer{
position: relative;
width: 100%;
height: auto;
padding-top: 61%;
}
The simple solution is to measure the width and height of the content area, and then use those measurements to calculate the bottom padding percentage.
In this case, the measurements are 1680 x 720 px, so the padding on the bottom is 720 / 1680 = 0.43 * 100, which comes out to 43%.
.canvas-container {
position: relative;
padding-bottom: 43%; // (720 ÷ 1680 = 0.4286 = 43%)
height: 0;
overflow: hidden;
}
.canvas-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
A slightly improved answer to BlueFish...
function resizeIframe(iframe) {
var padding = 50;
if (iframe.contentWindow.document.body.scrollHeight < (window.innerHeight - padding))
iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
else
iframe.height = (window.innerHeight - padding) + "px";
}
This takes in consideration the height of the windows screen(browser, phone) which is good for responsive design and iframes that have huge height.
Padding represents the padding you want above and below the iframe in the case it goes trough whole screen.
jQuery('.home_vidio_img1 img').click(function(){
video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
jQuery(this).replaceWith(video);
});
jQuery('.home_vidio_img2 img').click(function(){
video = <iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>;
jQuery('.home_vidio_img1 img').replaceWith(video);
jQuery('.home_vidio_img1 iframe').replaceWith(video);
});
jQuery('.home_vidio_img3 img').click(function(){
video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
jQuery('.home_vidio_img1 img').replaceWith(video);
jQuery('.home_vidio_img1 iframe').replaceWith(video);
});
jQuery('.home_vidio_img4 img').click(function(){
video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
jQuery('.home_vidio_img1 img').replaceWith(video);
jQuery('.home_vidio_img1 iframe').replaceWith(video);
});
Sample using PHP htmlspecialchars() + check if height exists and is > 0:
$my_html_markup = ''; // Insert here HTML markup with CSS, JS... '<html><head></head><body>...</body></html>'
$iframe = '<iframe onload="if(this.contentWindow.document.body.scrollHeight) {this.height = this.contentWindow.document.body.scrollHeight;}" width="100%" src="javascript: \''. htmlspecialchars($my_html_markup) . '\'"></iframe>';
Script
<script type="text/javascript" language="javascript">
$(document).ready(function(){
var height = $(window).height();
$('.myIframe').css('height', height - 200);
});
</script>
iframe
<iframe class="myIframe" width="100%"></iframe>
It's working in my case.
$(document).height() // - $('body').offset().top
and / or
$(window).height()
See Stack Overflow question How to get the height of a body element.
Try this to find the height of the body in jQuery:
if $("body").height()
It doesn't have a value if Firebug. Perhaps that's the problem.
just make iframe container position:absolute and iframe will automatically change its height according to its content
<style>
.iframe-container {
display: block;
position: absolute;
/*change position as you need*/
bottom: 0;
left: 0;
right: 0;
top: 0;
}
iframe {
margin: 0;
padding: 0;
border: 0;
width: 100%;
background-color: #fff;
}
</style>
<div class="iframe-container">
<iframe src="http://iframesourcepage"></iframe>
</div>
I am attempting to make a DIV fall when a piece of text is hovered upon. This is the original effect and this:
var $dropDiv = $('#dropDiv');
$('#holder p').on('hover', function () {
// Get position of clicked div
var offset = $(this).offset();
// Get dimensions of said div
var h = $(this).outerHeight();
var w = $(this).outerWidth();
// Get dimensions of dropping div
var dh = $dropDiv.outerHeight();
var dw = $dropDiv.outerWidth();
// Determine middle position
var initLeft = offset.left + ((w / 2) - (dw / 2));
// Animate drop
$dropDiv.css({
left: initLeft,
top: $(window).scrollTop() - dh,
opacity: 0,
display: 'block'
}).animate({
left: initLeft,
top: offset.top - dh,
opacity: 1
}, 800, 'easeOutBounce');
});
is my code. At first I thought it was a problem with my libraries, so I switched to the versions the fiddle has.
<script src="fall.js"></script>
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
The fiddle also had some CSS so I matched up to it
#holder {
position: absolute;
top: 200px;
left: 100px;
}
#dropDiv {
display: none;
position: absolute;
top: -20px;
background: #ccc;
}
I even checked the error console and there are no errors, but it still doesn't work. What am I doing wrong and how can I fix it? I am using Safari Version 5.1.10 and expect it to work for me and Chrome users at least.
This should be the order.
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
<script src="fall.js"></script>
try wrapping the code inside -
$(document).ready(function() {
//code here
});
It is possible that your javascript is not getting executed to to the problem of the same being run prior to the elements being loaded to the DOM
+
If your specified javascript is inside fall.js, since it uses jquery load the fall.js file after jquery.
Where have you include your code ? I had similar problem.
<html>
<head>
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
</head>
<body>
YOUR HTML CODE
<script type="text/javascript"> your code</script>
or
<script src="fall.js"></script>
</body>
</html>
Include your jQuery code after the html code. bottom in tag
that should work
also put your code inside ready function
$(document).ready(function(){
your code here...
})
You need to take 2 Steps -
1) ORDERING - The js file/code using jquery lib. functions should always come jquery file is included
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
<script src="fall.js"></script>
2) ELEMENT SHOULD BE AVAILABLE IN DOM - Either the js/script should be the last thing in the body or use jquery dom ready event
(More Detail Here)
I can spot a little Javascript vs. CSS confusion here.
$('#holder p').on( 'mouseover', function() {
// code
});
You can use:
$(function(){
//you code here
})
<body>
`
<div id="page-wrap"> .... </div>
<script>
(function ($) {
jQuery(window).resize(function () {
var width = jQuery('#page-wrap').css('margin-left');
jQuery('#left-link').css({ width: width });
jQuery('#right-link').css({ width: width });
});
var width = jQuery('#page-wrap').css('margin-left');
jQuery('#left-link').css({ width: width });
jQuery('#right-link').css({ width: width });
})(jQuery);
</script>
</body>
and I create this script but don't play in Firefox and I cannot find the bug . Chrome and IE play correct .
What is it then that doesn't work?
Is it the code that is supposed to be executed on resize? Test it by using breakpoints in firebug or just print something to the console. Btw. you could make it look better by writing it like this
$(window).on("resize", function() { /* your stuff here */ });
or does it fail to adjust the width of the two elements you're trying to manipulate? In this case you should take a closer look at what value your width variable holds, maybe it is somehow computed in firefox.
I did a Google search and I cannot find a way to do a loading with percentage. Anyone know how I can find an example of that?
I need a preload for a website from 0-100 without bar, before show the content, but I cannot find any example.
I recommend this plugin. Its amazing
download from http://demo.inwebson.com/download/jpreloader.zip
see in action here http://www.inwebson.com/demo/jpreloader/
<script type="text/javascript" src="js/jpreLoader.js"></script>
<script type="text/javascript">// <![CDATA[
$(document).ready(function() {
$('body').jpreLoader();
});
// ]]></script>
here are the links to new version jpreloader 2.1
http://demo.inwebson.com/download/jpreloader-v2.zip
http://www.inwebson.com/demo/jpreloader-v2/
If you mean you want to show the content only when it is fully loaded, you may try following two options:
1) wrap all content inside a <div id="wrapper" style="display:none;"></div> tag and on load complete event show it like this:
$(function(){
$("#wrapper").show();
});
2) If this still does not solves your purpose, you can load empty page and fetch content using ajax:
$(function(){
$.ajax({
.......//AJAX params
.......
success:function(msg){
$("#wrapper").html(msg);//DO NEEDFUL WITH THE RETURNED VALUE
});
});
EDIT: Using queryLoader script provided by gayadesign I was able to achieve some success :D
I had to made some changes to the queryLoader.js file from line 127 to 151. The changed script is as follows. Try it yourself.
$(QueryLoader.loadBar).css({
position: "relative",
top: "50%",
font-size:40px;
font-weight:bold;
line-height:50px;
height:50px;
width:100px;
});
},
animateLoader: function() {
var perc = (100 / QueryLoader.doneStatus) * QueryLoader.doneNow;
if (perc > 99) {
$(QueryLoader.loadBar).stop().animate({
width: perc + "%"
}, 5000, "linear", function() {
$(this).html("<strong>100%</strong>");//MY EDIT
QueryLoader.doneLoad();
});
} else {
$(QueryLoader.loadBar).stop().animate({
width: perc + "%"
}, 5000, "linear", function() {
//MY EDIT
$(this).html("<strong>"+Math.round(perc)+"%</strong>");
});
}
},
You can't.
As zzzzBov said, it isn't known how much content there will be, or what size that content is.
You could 'fake' it, with something like this (for the example I am using images):
var percentCounter = 0;
$.each(arrayOfImageUrls, function(index, value) {
$('<img></img>').attr('src', value) //load image
.load(function() {
percentCounter = (index / arrayOfImageUrls.length) * 100; //set the percentCounter after this image has loaded
$('#yourProgressContainer').text(percentCounter + '%');
});
});
As I mentioned this isn't a TRUE percentage of the sites loading, but a rough estimate of the images that have loaded, assuming each image is roughly the same size.
See this Project. It does what you want nicely.
http://www.gayadesign.com/diy/queryloader-preload-your-website-in-style/
The demo is hosted here
http://www.gayadesign.com/scripts/queryLoader/
Download it here
http://www.gayadesign.com/scripts/queryLoader/queryLoader.zip