Pure JavaScript function similar to jQuery.offset()? - javascript

In a small iframe-application at the Russian social network Ok.ru I use the following call to resize the iframe:
<div id="fb-root"></div>
<script src="http://api.odnoklassniki.ru/js/fapi.js"
type="text/javascript"></script>
<script type="text/javascript">
FAPI.init("http://api.odnoklassniki.ru/", "XXX_YYY",
function() {
alert("clientHeight " + document.getElementById("fb-root").clientHeight);
alert("offsetHeight " + document.getElementById("fb-root").offsetHeight);
FAPI.UI.setWindowSize(720, 1200);
}, function(error){
alert("API initialization failed");
});
</script>
</body>
</html>
i.e. the iframe-height is currently hardcoded to 1200.
It works okay, but I'd like to use the height/position of #fb-root element instead.
Does anybody please have an idea, which JavaScript or CSS function could be used here - if I don't want to include jQuery just for one $(#fb-root).offset() call?
I've also looked at their library http://api.odnoklassniki.ru//js/fapi.js but it doesn't include such function.
UPDATE
I've added two alert-calls to my source code above, but they only print
clientHeight 0
offsetHeight 0
UPDATE
The following code seem to work well for my iframe-app now in Google Chrome and Mozilla Firefox, regardless of how many s do I add for testing it. But with Internet Explorer it fails to resize the window and alert shows top=1107 instead of top=1157 in Google Chrome, thus the html table at the bottom is cut off:
... here my flash game + html table with players ...
<br>
<br>
<br>
<br>
<br>
<br>
<div id="fb-root"></div>
<script src="http://api.odnoklassniki.ru/js/fapi.js" type="text/javascript"></script>
<script type="text/javascript">
FAPI.init("http://api.odnoklassniki.ru/", "XXX_YYY",
function() {
var top = findTop(document.getElementById("fb-root"));
FAPI.UI.setWindowSize(720, Math.max(top, 1200));
}, function(error){
alert("API initialization failed");
});
function findTop(obj) {
if(!obj) return 0;
return obj.offsetTop + findTop(obj.offsetParent);
}
</script>
</body>
</html>

Looking at the code in jquery, the offset is calculated like this:
function getOffset(element)
{
if (!element.getClientRects().length)
{
return { top: 0, left: 0 };
}
let rect = element.getBoundingClientRect();
let win = element.ownerDocument.defaultView;
return (
{
top: rect.top + win.pageYOffset,
left: rect.left + win.pageXOffset
});
}

Quirksmode has a JavaScript tutorial/function that shows how to find the coordinates of an element here
Once you have its coordinates, you can use the offsetHeight property of the iframe to read its height.

If document.getElementById("fb-root").clientHeight returns 0, it certainly means that your "fb-root" div is either not displayed or still empty.
I have had a look at fapi.js, and it seems that calling the FAPI.init function creates a span which id is "FAPI_Flash_wrap", appends it to the body of the document, then embeds a flash object with id "FAPI_Flash" in this span.
So I would try retrieving an element with id "FAPI_Flash_wrap" or "FAPI_Flash" instead of "fb-root":<script type="text/javascript">
FAPI.init("http://api.odnoklassniki.ru/", "XXX_YYY",
function() {
alert("Height = " + document.getElementById("FAPI_Flash_wrap").offsetHeight);
alert("Width = " + document.getElementById("FAPI_Flash_wrap").offsetWidth);
FAPI.UI.setWindowSize(720, 1200);
}, function(error){alert("API initialization failed");}
);
</script>
I hope this works!
If it's the case, then just use
<script type="text/javascript">
FAPI.init("http://api.odnoklassniki.ru/", "XXX_YYY",
function() {
var height = document.getElementById("FAPI_Flash_wrap").offsetHeight;
var width = document.getElementById("FAPI_Flash_wrap").offsetWidth;
FAPI.UI.setWindowSize(width, height);
}, function(error){alert("API initialization failed");}
);
</script>

Use offsetHeight or clientHeight to get div's height:
document.getElementById("fb-root").offsetHeight // including border
document.getElementById("fb-root").clientHeight // excluding border
Use offsetLeft and offsetTop to get div's position relative to its offsetParent. offsetParent is its first parent box which position style is fixed, relative or absolute.

Related

JavaScript: Get window width minus scrollbar width

Ok, I thought this would be really simple, but it's turning out not to be. I think I'm just messing something up in my HTML/CSS, but here goes.
I have a basic page like so:
HTML
<!DOCTYPE html>
<html>
<head>
<link href='test2.css' rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="test2.js"></script>
</head>
<body>
<div id="scroll"></div>
</body>
</html>
test2.css
* {
padding: 0;
margin: 0;
}
html, body {
height: 100%;
width: 100%;
}
#scroll {
height: 100%;
width: 100%;
overflow: scroll;
background-color: black;
}
test2.js
$(document).ready(function() {
// my resolution is 1440x900
alert('innerwidth should be 1425');
// all of these return 1440
alert('body innerwidth: ' + $('body').innerWidth());
alert('document width: ' + $(document).width());
alert('window width: ' + $(window).width());
alert('scroll div innerwidth: ' + $('#scroll').innerWidth());
alert('document.documentElement.clientWidth: ' + document.documentElement.clientWidth);
alert('document.documentElement.scrollWidth: ' + document.documentElement.scrollWidth);
});
So I've got one element on the page... a div that takes up the entire screen, or rather it should be taking up the entire screen minus the scrollbars. Now, I've been doing some snooping on how to grab the width and height of a page without the scrollbars, but unfortunately, none of them return the proper value... which makes me believe I'm missing the boat in my HTML or CSS.
I looked at the following:
jquery - how to get screen width without scrollbar?
how to get the browser window size without the scroll bars
So what I need is for a method to return the value of my viewable screen minus the respective scrollbar value... so for my width, my value should be 1425 because the scrollbar is 15 pixels wide. I thought that's what innerWidth's job was, but apparently I'm wrong?
Can anyone provide any insight? (I'm running Firefox 24.)
EDIT
To add some background, I've got a blank page. I will be adding elements one by one to this page, and I need to use the width of the page when calculating the sizes for these elements. Eventually, this page will grow and grow until the scrollbar appears, which is why I'm trying to force the scrollbar there from the start, but apparently, that still doesn't do anything.
EDIT2
Here's something even more interesting... if I do document.getElementById('scroll').clientWidth, I get the proper innerWidth, but if I do $('#scroll').width() or $('#scroll').innerWidth(), they both return the max resolution... sounds like a jQuery bug.
I got this somewhere and would give credit if I knew where, but this has been succesfull for me. I added the result as padding when setting the html overflow to hidden.
Problem is that the scrollbar is a feature of the browser and not the web page self. Measurement should be done dynamically. A measurement with a scrollbar and a measurement without a scrollbar will resolve into calculating the difference in width.
Found the source: http://www.fleegix.org/articles/2006/05/30/getting-the-scrollbar-width-in-pixels
scrollCompensate = function () {
var inner = document.createElement('p');
inner.style.width = "100%";
inner.style.height = "200px";
var outer = document.createElement('div');
outer.style.position = "absolute";
outer.style.top = "0px";
outer.style.left = "0px";
outer.style.visibility = "hidden";
outer.style.width = "200px";
outer.style.height = "150px";
outer.style.overflow = "hidden";
outer.appendChild(inner);
document.body.appendChild(outer);
var w1 = inner.offsetWidth;
outer.style.overflow = 'scroll';
var w2 = inner.offsetWidth;
if (w1 == w2) w2 = outer.clientWidth;
document.body.removeChild(outer);
return (w1 - w2);
}
var htmlpadding = scrollCompensate();
The correct answer is in this post marked as accepted:
CSS media queries and JavaScript window width do not match
This is the correct code:
function viewport() {
var e = window, a = 'inner';
if (!('innerWidth' in window )) {
a = 'client';
e = document.documentElement || document.body;
}
return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
}
Discovered a very hacky solution... by adding this before my alerts in test2.js, I get the proper width:
var p = $('body').append('<p style="height: 100%; width: 100%;"></p>');
alert(p.width());
$('body').remove('p');
And consequently, all of the alerts now have the proper width. I also don't even need overflow-y in the CSS if I do it this way. Curious why this solves it...
The real answer should be keeping the HTML and CSS as is, then using document.getElementById('scroll').clientWidth. Using clientWidth gets the viewable area minus the scrollbar width.
The correct width of the page is given by $(document).width().
Your problem is that you're using a scroll within the div (overflow: scroll).
Using $(document).width() the returned value is already discounting the visible width of the scroll, but how do you put a scroll within the div value returned is no longer the same.
As the width of the scroll is not standard and varies from system to system and browser to browser, it is difficult to solve.
I suggest you remove the scroll of the div and let the browser manage this by default in the body, then yes you have the correct width.

how to perfectly overlap two (identical) elements?

Inside a position:relativeelement box, I have
a absolutely positioned element parent at top:0 with a couple of static p and h1..h6inside. Those may all have different margin/padding values.
a few absolutely positioned elements where element name and content matches exactly one of the elements from above list #1.
The goal is to set the y-value of the 2nd element such that it exactly overlaps with the corresponding one from the set in 1. .
I've taken this approach (using closure, but anything could be used really), starting with an Array of elements contentfor generating list #1:
goog.dom.removeChildren(parent);
for (var i=0; i<content.length; i++) {
offsets.push(parent.offsetHeight);
goog.dom.appendChild(parent, content[i]);
}
return offsets;
Then, using the values from offsets:
var matchedElm = source[i].cloneNode(true);
goog.style.setStyle(matchedElm, {"top": offsets[i] + "px"});
goog.dom.appendChild(box, matchedElm);
Now this works for various paddings and margin=0, but fails when margins are non-0 on the p and h1..6. I have also tried "scrollHeight" but nothing seems to take into account margins.
I've then tried getting offsetTop directly from the rendered elements in list #1, but this seems to yield exact same results as above procedure to fill offsets.
How can I make the overlap work? I'm looking for a native javascript or closure-library solution.
What you are looking for may be goog.style.getPageOffset and because your overlapping element is absolutely positioned with a top setting you may have to deduct the top margin of the element you want to overlap using goog.style.getMarginBox. Here is some sample code:
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<div id="game" data-something="hello"></div>
<script type="text/javascript" src="js/goog/base.js"></script>
<script type="text/javascript">
goog.require("goog.dom");
goog.require("goog.style");
</script>
</body>
<div id="contentToOverLap" style="position:absolute;top:30px;left:30px">
<h1 style="margin:10px;padding:2px">h1 10px mar and 2px pad</h1>
</div>
<div id="overlappingContent" style="display:inline">
<h1 style="color:red;margin:15px;padding:2px;position:absolute">
h1 15px mar and 2px pa
</h1>
</div>
<script type="text/javascript">
(function () {
var pH = goog.dom.$("contentToOverLap").children[0];
var cH = goog.dom.$("overlappingContent").children[0];
var box = goog.style.getPageOffset(pH);
console.log("box is:", box);
var mar = goog.style.getMarginBox(cH);
console.log("mar is:", mar);
var t = box.y - mar.top;
var l = box.x - mar.left;
goog.style.setStyle(cH, { "top": t + "px", "left": l + "px" });
})();
</script>
</html>

How to change the height of div with the content of other div

I have two div in my website page one beside the other(one left and one right),I want to change the height of the left one with the content of the right one using javascript
I tried to have the dynamic height of the right div :
function getHeight() {
var doc = document.getElementById('div.right');
if (document.all) // ok I.E
{
H = doc.currentStyle.height;
}
else // ok FF
{
H = document.defaultView.getComputedStyle(doc, null).height;
}
}​
But I stopped here because I don't know how to pass the javascript variable to my page of style CSS,I mean I dont know how to apply this value in the other div(left div) in the same page automatically.
Any Idea?
Just use
document.getElementById('div.left').style.height = H;
Edit
AFAIK you cant modify an external stylesheet from javascript
Is the height of the div determined at the time the document is served, loaded or or any arbitrary time after the document has loaded?
The code I suggested above was to be used like this(I'm assuming your IE code is correct)
function getHeight() {
var doc = document.getElementById('div.right');
if (document.all) // ok I.E
{
H = doc.currentStyle.height;
}
else // ok FF
{
H = document.defaultView.getComputedStyle(doc, null).height;
}
document.getElementById('div.left').style.height = H;//✔
}
Just to help people I found a great code to change the height of two div autoamtically using a little of Jquery :
<script type='text/javascript'>
$(window).load(function(){
var lh = $('#div.right').height();
var rh = $('#div.left').height();
if (lh >= rh){
//alert('left : ' + lh);
$('#div.left').height(lh);
} else {
//alert('right : ' + rh);
$('#div.right').height(rh);
};
});
</script>
It's works for all navigators.

Make iframe automatically adjust height according to the contents without using scrollbar? [duplicate]

This question already has answers here:
Adjust width and height of iframe to fit with content in it
(35 answers)
Closed 6 years ago.
For example:
<iframe name="Stack" src="http://stackoverflow.com/" width="740"
frameborder="0" scrolling="no" id="iframe"> ...
</iframe>
I want it to be able to adjust its height according to the contents inside it, without using scroll.
Add this to your <head> section:
<script>
function resizeIframe(obj) {
obj.style.height = obj.contentWindow.document.documentElement.scrollHeight + 'px';
}
</script>
And change your iframe to this:
<iframe src="..." frameborder="0" scrolling="no" onload="resizeIframe(this)" />
As found on sitepoint discussion.
You can use this library, which both initially sizes your iframe correctly and also keeps it at the right size by detecting whenever the size of the iframe's content changes (either via regular checking in a setInterval or via MutationObserver) and resizing it.
https://github.com/davidjbradshaw/iframe-resizer
Their is also a React version.
https://github.com/davidjbradshaw/iframe-resizer-react
This works with both cross and same domain iframes.
Here is a compact version:
<iframe src="hello.html" sandbox="allow-same-origin"
onload="this.style.height=(this.contentWindow.document.body.scrollHeight+20)+'px';">
</iframe>
The suggestion by hjpotter92 does not work in safari!
I have made a small adjustment to the script so it now works in Safari as well.
Only change made is resetting height to 0 on every load in order to enable some browsers to decrease height.
Add this to <head> tag:
<script type="text/javascript">
function resizeIframe(obj){
obj.style.height = 0;
obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
}
</script>
And add the following onload attribute to your iframe, like so
<iframe onload='resizeIframe(this)'></iframe>
Avoid inline JavaScript; you can use a class:
<iframe src="..." frameborder="0" scrolling="auto" class="iframe-full-height"></iframe>
And reference it with jQuery:
$('.iframe-full-height').on('load', function(){
this.style.height=this.contentDocument.body.scrollHeight +'px';
});
The hjpotter92 answer works well enough in certain cases, but I found the iframe content often got bottom-clipped in Firefox & IE, while fine in Chrome.
The following works well for me and fixes the clipping problem. The code was found at http://www.dyn-web.com/tutorials/iframes/height/. I have made a slight modification to take the onload attribute out of the HTML. Place the following code after the <iframe> HTML and before the closing </body> tag:
<script type="text/javascript">
function getDocHeight(doc) {
doc = doc || document;
// stackoverflow.com/questions/1145850/
var body = doc.body, html = doc.documentElement;
var height = Math.max( body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight );
return height;
}
function setIframeHeight(id) {
var ifrm = document.getElementById(id);
var doc = ifrm.contentDocument? ifrm.contentDocument:
ifrm.contentWindow.document;
ifrm.style.visibility = 'hidden';
ifrm.style.height = "10px"; // reset to minimal height ...
// IE opt. for bing/msn needs a bit added or scrollbar appears
ifrm.style.height = getDocHeight( doc ) + 4 + "px";
ifrm.style.visibility = 'visible';
}
document.getElementById('ifrm').onload = function() { // Adjust the Id accordingly
setIframeHeight(this.id);
}
</script>
Your iframe HTML:
<iframe id="ifrm" src="some-iframe-content.html"></iframe>
Note if you prefer to include the Javascript in the <head> of the document then you can revert to using an inline onload attribute in the iframe HTML, as in the dyn-web web page.
jQuery's .contents() method method allows us to search through the immediate children of the element in the DOM tree.
jQuery:
$('iframe').height( $('iframe').contents().outerHeight() );
Remember that the body of the page inner the iframe must have its height
CSS:
body {
height: auto;
overflow: auto
}
This works for me (also with multiple iframes on one page):
$('iframe').load(function(){$(this).height($(this).contents().outerHeight());});
Try this for IE11
<iframe name="Stack" src="http://stackoverflow.com/" style='height: 100%; width: 100%;' frameborder="0" scrolling="no" id="iframe">...</iframe>
This works for me (mostly).
Put this at the bottom of your page.
<script type="application/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
<script type="application/javascript" src="/script/jquery.browser.js">
</script>
<script type="application/javascript" src="/script/jquery-iframe-auto-height.js">
</script>
<script type="application/javascript">
jQuery('iframe').iframeAutoHeight();
$(window).load(
function() {
jQuery('iframe').iframeAutoHeight();
}
);
// for when content is not html e.g. a PDF
function setIframeHeight() {
$('.iframe_fullHeight').each(
function (i, item) {
item.height = $(document).height();
}
);
};
$(document).ready( function () {
setIframeHeight();
});
$(window).resize( function () {
setIframeHeight();
});
</script>
The first half is from ???, and works when there is html in the iframe.
The second half sets the iframe to page height (not content height), when iframes class is iframe_fullHeight. You can use this if the content is a PDF or other such like, but you have to set the class. Also can only be used when being full height is appropriate.
Note: for some reason, when it recalculates after window resize, it gets height wrong.
function autoResize(id){
var newheight;
var newwidth;
if(document.getElementById){
newheight=document.getElementById(id).contentWindow.document.body.scrollHeight;
newwidth=document.getElementById(id).contentWindow.document.body.scrollWidth;
}
document.getElementById(id).height=(newheight) + "px";
document.getElementById(id).width=(newwidth) + "px";
}
add this to your iframe:
onload="autoResize('youriframeid')"
jq2('#stocks_iframe').load(function(){
var iframe_width = jq2('#stocks_iframe').contents().outerHeight() ;
jq2('#stocks_iframe').css('height',iframe_width); });
<iframe id='stocks_iframe' style='width:100%;height:0px;' frameborder='0'>
I did it with AngularJS. Angular doesn't have an ng-load, but a 3rd party module was made; install with bower below, or find it here: https://github.com/andrefarzat/ng-load
Get the ngLoad directive: bower install ng-load --save
Setup your iframe:
<iframe id="CreditReportFrame" src="about:blank" frameborder="0" scrolling="no" ng-load="resizeIframe($event)" seamless></iframe>
Controller resizeIframe function:
$scope.resizeIframe = function (event) {
console.log("iframe loaded!");
var iframe = event.target;
iframe.style.height = iframe.contentWindow.document.body.scrollHeight + 'px';
};
I wanted to make an iframe behave like a normal page (I needed to make a fullscreen banner inside an iframe element), so here is my script:
(function (window, undefined) {
var frame,
lastKnownFrameHeight = 0,
maxFrameLoadedTries = 5,
maxResizeCheckTries = 20;
//Resize iframe on window resize
addEvent(window, 'resize', resizeFrame);
var iframeCheckInterval = window.setInterval(function () {
maxFrameLoadedTries--;
var frames = document.getElementsByTagName('iframe');
if (maxFrameLoadedTries == 0 || frames.length) {
clearInterval(iframeCheckInterval);
frame = frames[0];
addEvent(frame, 'load', resizeFrame);
var resizeCheckInterval = setInterval(function () {
resizeFrame();
maxResizeCheckTries--;
if (maxResizeCheckTries == 0) {
clearInterval(resizeCheckInterval);
}
}, 1000);
resizeFrame();
}
}, 500);
function resizeFrame() {
if (frame) {
var frameHeight = frame.contentWindow.document.body.scrollHeight;
if (frameHeight !== lastKnownFrameHeight) {
lastKnownFrameHeight = frameHeight;
var viewportWidth = document.documentElement.clientWidth;
if (document.compatMode && document.compatMode === 'BackCompat') {
viewportWidth = document.body.clientWidth;
}
frame.setAttribute('width', viewportWidth);
frame.setAttribute('height', lastKnownFrameHeight);
frame.style.width = viewportWidth + 'px';
frame.style.height = frameHeight + 'px';
}
}
}
//--------------------------------------------------------------
// Cross-browser helpers
//--------------------------------------------------------------
function addEvent(elem, event, fn) {
if (elem.addEventListener) {
elem.addEventListener(event, fn, false);
} else {
elem.attachEvent("on" + event, function () {
return (fn.call(elem, window.event));
});
}
}
})(window);
The functions are self-explanatory and have comments to further explain their purpose.
I've had problems in the past calling iframe.onload for dynamically created iframes, so I went with this approach for setting the iframe size:
iFrame View
var height = $("body").outerHeight();
parent.SetIFrameHeight(height);
Main View
SetIFrameHeight = function(height) {
$("#iFrameWrapper").height(height);
}
(this is only going to work if both views are in the same domain)
<script type="text/javascript">
function resizeIframe(obj) {
obj.style.height = 0;
obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
}
</script>
this is not working for chrome. But working for firefox.

make iframe height dynamic based on content inside- JQUERY/Javascript

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>

Categories

Resources