I decided to give up trying to do it without JavaScript. I managed to get it to work smoothly by making sure it gets the position of the mouse cursor correctly, even when hovering over the iframe
. It requires access to the domain in the iframe
to use postMessage
to get the mouse coordinates but no problem, I am only going to use this to create debug tools on my own website anyway. It can be resized in all directions by dragging an edge or corner.
<!DOCTYPE html>
<style>
iframe {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 100%;
height: 100%;
border: none;
}
.frame_holder {
display: block;
top: 300px;
left: 200px;
height: 500px;
width: 350px;
position: absolute;
}
.resizer {
position: absolute;
width: 7px;
height: 7px;
z-index: 2;
}
.resizer.n {
top: -7px;
left: 0px;
width: 100%;
cursor: n-resize;
}
.resizer.s {
bottom: -7px;
left: 0px;
width: 100%;
cursor: s-resize;
}
.resizer.w {
top: 0px;
left: -7px;
height:100%;
cursor: w-resize;
}
.resizer.e {
top: 0px;
right: -7px;
height:100%;
cursor: e-resize;
}
.resizer.nw {
top: -7px;
left: -7px;
cursor: nw-resize;
}
.resizer.ne {
top: -7px;
right: -7px;
cursor: ne-resize;
}
.resizer.sw {
bottom: -7px;
left: -7px;
cursor: sw-resize;
}
.resizer.se {
bottom: -7px;
right: -7px;
cursor: se-resize;
}
</style>
<body>
<div class="frame_holder">
<div class="resizer n"></div>
<div class="resizer s"></div>
<div class="resizer w"></div>
<div class="resizer e"></div>
<div class="resizer ne"></div>
<div class="resizer nw"></div>
<div class="resizer sw"></div>
<div class="resizer se"></div>
<iframe class="frame" src="https://stackoverflow.com/questions/74724195/how-can-i-make-an-iframe-resizeable-without-javascript"></iframe>
</div>
</body>
<script>
$ = typeof $ == "undefined" ? [] : $;
$[window.location.pathname]=function()
{
window.addEventListener('contextmenu', (e) => {e.preventDefault()});
const el = document.querySelector(".frame_holder");
const iframe = document.querySelector(".frame");
const resizers = document.querySelectorAll(".resizer");
var currentResizer = 0;
var prevX;
var prevY;
function resize(el, size)
{
Object.keys(size).forEach((i) =>
{
el.style[i] = size[i] + "px";
});
}
window.onmessage = function(e)
{
try
{
var msg = JSON.parse(e.data);
}
catch (e)
{
return;
}
if (msg.type == "mouseUp")
{
el.isResizing=false;
//window.removeEventListener("mousemove", mousemove);
//window.removeEventListener("mouseup", mouseup);
return
}
if (!el.isResizing)
{
try
{
window.removeEventListener("mousemove", mousemove);
//window.removeEventListener("mouseup", mouseup);
}
catch (e)
{ }
return;
}
const rect = el.getBoundingClientRect();
let mouseX = msg.mouseX + rect.left;
let mouseY = msg.mouseY + rect.top;
//let top = Math.min(rect.top - (prevY - mouseY), 0);
//let left = Math.min(rect.left - (prevX - mouseX), 0);
let top = rect.top - (prevY - mouseY);
let left = rect.left - (prevX - mouseX);
let width = rect.width + (prevX - mouseX);
let width1 = rect.width - (prevX - mouseX);
let height= rect.height - (prevY - mouseY);
let height1 = rect.height + (prevY - mouseY);
//let vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
//let vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0)
let currentResizer = this.currentResizer;
if (currentResizer.classList.contains("n"))
resize(el, {top: top, height: height1});
else if (currentResizer.classList.contains("w"))
resize(el, {left: left, width: width});
else if (currentResizer.classList.contains("s"))
resize(el, {height: height});
else if (currentResizer.classList.contains("e"))
resize(el, {width: width1});
else if (currentResizer.classList.contains("sw"))
resize(el, {left: left, width: width, height: height});
else if (currentResizer.classList.contains("ne"))
resize(el, {top: top, width: width1, height: height1});
else if (currentResizer.classList.contains("nw"))
resize(el, {top: top, left: left, width: width, height: height1});
else if (currentResizer.classList.contains("se"))
resize(el, {width: width1, height: height});
else
resize(el, {left: left, top: top});
prevX = mouseX;
prevY = mouseY;
};
for (let resizer of resizers)
{
if (resizer.classList.contains("n"))
iframe.style.borderTop = "groove 2px";
else if (resizer.classList.contains("s"))
iframe.style.borderBottom = "groove 2px";
else if (resizer.classList.contains("w"))
iframe.style.borderLeft = "groove 2px";
else if (resizer.classList.contains("e"))
iframe.style.borderRight = "groove 2px";
resizer.addEventListener("mousedown", mousedown);
function mousedown(e)
{
currentResizer = e.target;
//window.currentResizer = e.target;
window.currentResizer = currentResizer;
el.isResizing = true;
prevX = e.clientX;
prevY = e.clientY;
window.addEventListener("mousemove", mousemove);
window.addEventListener("mouseup", mouseup);
//msg.mouseX=344, msg.mouseY=830
//e.clientX=551, e.clientY=800
function mousemove(e)
{
if (!el.isResizing)
{
window.removeEventListener("mousemove", mousemove);
window.removeEventListener("mouseup", mouseup);
return;
}
const rect = el.getBoundingClientRect();
//let top = Math.min(rect.top - (prevY - e.clientY), 0);
//let left = Math.min(rect.left - (prevX - e.clientX), 0);
let top = rect.top - (prevY - e.clientY);
let left = rect.left - (prevX - e.clientX);
let width = rect.width + (prevX - e.clientX);
let width1 = rect.width - (prevX - e.clientX);
let height= rect.height - (prevY - e.clientY);
let height1 = rect.height + (prevY - e.clientY);
if (currentResizer.classList.contains("n"))
resize(el, {top: top, height: height1});
else if (currentResizer.classList.contains("w"))
resize(el, {left: left, width: width});
else if (currentResizer.classList.contains("s"))
resize(el, {height: height});
else if (currentResizer.classList.contains("e"))
resize(el, {width: width1});
else if (currentResizer.classList.contains("sw"))
resize(el, {left: left, width: width, height: height});
else if (currentResizer.classList.contains("ne"))
resize(el, {top: top, width: width1, height: height1});
else if (currentResizer.classList.contains("nw"))
resize(el, {top: top, left: left, width: width, height: height1});
else if (currentResizer.classList.contains("se"))
resize(el, {width: width1, height: height});
else
resize(el, {left: left, top: top});
prevX = e.clientX;
prevY = e.clientY;
}
function mouseup()
{
el.isResizing = false;
console.log("mouseup");
window.removeEventListener("mousemove", mousemove);
//window.removeEventListener("mouseup", mouseup);
}
}
}
}
if (document.readyState!='loading') $[window.location.pathname](); else document.addEventListener('DOMContentLoaded', $[window.location.pathname]);
</script>
This code goes inside the iframe
:
if (!window.isTop)
{
function mouseup(e)
{
window.top.postMessage(JSON.stringify({ type: "mouseUp" }), '*');
}
function mousemove(e)
{
window.top.postMessage(JSON.stringify({ type: "mouseMove", mouseX: e.clientX, mouseY: e.clientY }), '*');
}
window.addEventListener("mouseup", mouseup);
window.addEventListener("mousemove", mousemove);
}