How can I make an iframe click-through, but make that iframe's body still be clickable?
I tried:
iframe.style.width = '100%'
iframe.style.height = '100%'
iframe.style.display = 'block'
iframe.style.position = 'fixed'
iframe.style.backgroundColor = 'transparent'
iframe.style.pointerEvents = 'none'
iframe.style.border = '0'
iframe.frameborder = '0'
iframe.scrolling = 'no'
iframe.allowTransparency = 'true'
and inside of my I frame I'm using the following css:
html, body {
/* background:none transparent; */
pointer-events:auto;
}
This results in body being visible (which is what I want), but it is click-through like the rest of the iframe. I want the body of the iframe to be clickable, but all the rest of the actual iframe element should be click-through.
The iframe is always bigger than the body inside of it.
Unfortunately I cannot access the the iframe content from the main site (so accessing the scrollHeight etc isn't possible), I can only change its actual source code.
DISCLAIMER: OP created this question almost two years ago, my answer follows Ian Wise's bumping the question and elaborating on it (see comments).
What you are describing here involves logic between a document and a child document: "If a click event did nothing inside child document, apply that click event to parent document", and therefore cannot be approached using HTML/CSS.
Iframes are different documents. They do have a child-parent relationship with their containers, but an event that occurs within the iframe will be handled by the iframe.
An idea that requires some code but will work:
function clickOnCover(e, i) {
if(e && e.preventDefaule) e.preventDefault();
if(i && i >= iframes.length) {
console.log("No action.");
return;
}
var iframe = iframes[i || 0];
if(iframe.contentWindow && iframe.contentWindow.postMessage) {
iframe.contentWindow.postMessage({ x: e.clientX, y: e.clientY, i: i });
}
}
function iframeResponse(e) {
var response = e.data, iframeIndex = response.i;
if(response.success)
console.log("Action done on iframe index -> " + iframeIndex);
else
clickOnCover({ clientX: response.x, clientY: response.y }, iframeIndex+1);
}
clientX, clientY
and checks for possible activies in that position (might be tricky!).window.addEventListener("message", function(e) {
// Logic for checking e.x & e.y
e.success = actionExists; // Some indicator if an action occurred.
if(window.parent && window.parent.postMessage) {
window.parent.postMessage(e);
}
});
This solution keeps managing the event within the parent document and only requires iterating through whatever amount of stacked iframes.
Found a relevant SO question to further support my claim: Detect Click in Iframe
This is not possible with CSS.
The easiest way is to resize the iframe properly. Assuming you have access to iframe content, the following solution is possible:
You might add a little JS to allow the parent page to know the iframe height
mainpage.js
var iframe = getIframe();
setIntervalMaybe(() => {
// ask for size update
iframe.contentWindow.postMessage({action: "getSize"}, document.location.origin);
}, 100)
window.addEventListener("message", function receiveMessage(event) {
switch(event.data.action) {
case "returnSize":
// updateIFrameSize(event.data.dimensions);
console.log(event.data.dimensions);
break;
}
}, false);
iframe.js
window.addEventListener("message", function receiveMessage(event) {
switch(event.data.action) {
case "getSize":
event.source.postMessage({action: "returnSize", dimensions: {
width: document.body.offsetWidth,
height: document.body.offsetHeight
}}, event.origin);
break;
}
}, false);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With