kaerimasu kaerimasu - 2 months ago 9
HTML Question

Stop scrolling on zoomable iframe

I'm working on a webpage that embeds another page from a different domain inside an iframe. The content of this page fits the iframe exactly, so there's no overflowing content and no scrollbars. However, the content can be zoomed with the mousewheel.

But in Safari and Chrome, zooming with the mousewheel also scrolls the entire page. I don't want this scrolling to happen---only the zooming of the iframe. How can I stop this scrolling when the mouse is over the iframe?

I've attempted to recreate the problem in a minimal example on JSFiddle: https://jsfiddle.net/twodee/57a68k3h. When I zoom over the green iframe, the text zooms but the page also scrolls.



frame = document.getElementById('myframe');
frame_child = document.createElement('div');

var font_size = 12;
frame_child.addEventListener('wheel', function(e) {
font_size += e.wheelDelta;
frame_child.style.fontSize = font_size + 'px';
});

frame_child.style.width = '190px';
frame_child.style.height = '190px';
frame_child.innerHTML = 'this text should zoom';
frame.contentWindow.document.body.appendChild(frame_child);

#myframe {
background-color: #00FF00;
}

<ul>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
</ul>
<div>
<iframe id="myframe" height="200px" width="800px" src="about:blank"></iframe>
</div>
<ul>
<li>b</li>
<li>b</li>
<li>b</li>
<li>b</li>
<li>b</li>
<li>b</li>
<li>b</li>
<li>b</li>
<li>b</li>
<li>b</li>
<li>b</li>
<li>b</li>
<li>b</li>
</ul>





EDIT:
The example above is a little misleading in that the iframe source is not really generated dynamically by my own script. Instead, the source is generated by a separate website, which expects form input from the requester. Here's a CodePen that better demonstrates my issue: http://codepen.io/twodee/pen/PGqgyw. (JSFiddle only allows https:// sources.)

When I wheel over the iframe, the 3D cube zooms and the page scrolls.

EDIT:
The effect I'm after is what I see when Google Maps is embedded in a page. Or Sketchfab. When I embed these in an iframe, I don't have to do anything special in the page that's doing the embedding to make zooming happen without scrolling. There seems to be something about the embedded content itself that disables the scrolling, but I don't know what.

Answer

As others have stated, preventDefault() works fine for your first example, where it's a div.

But this does not appear to be possible on iframes to external sites, because only certain events are captured on the iframe. On this codepen, you can see that the mouseenter event is captured on the iframe, but the click and the wheel are not. Pay close attention to the console.log(target) statements and which work and which do not.

Codepen

<iframe id="myframe" src="http://www.w3schools.com">
</iframe>
<br>
<div id="div1">
  test
</div>
<div id="div2">
</div>

CSS

iframe {
  width:600px;
  height:200px;
  border: 10px solid red;
}
div {
 width:600px;
 height:40px;
 border: 10px solid blue;
}
#div2 {
 width:600px;
 height:800px;
 border: 10px solid green;
}

JS

frame = document.getElementById('myframe');
div = document.getElementById('div1');

frame.addEventListener('mouseenter', function(e) {
  console.log('entered');
  var target = e.target;
  console.log(target);
});
frame.addEventListener('click', function(e) {
  console.log('clicked');
  var target = e.target;
  console.log(target);
});
frame.addEventListener('wheel', function(e) {
  console.log('wheel');
  var target = e.target;
  console.log(target);
});

font_size = 12;
div1.addEventListener('wheel', function(e) {
  var target = e.target;
  console.log(target);
  font_size += -e.wheelDelta/100;
  this.style.fontSize = font_size + 'px';

  if(target.id === 'div1')
    e.preventDefault();
});

Updated: Since you say you have control over the iframe content, you can add the wheel event handler to the framed content. Try this...

HTML on the framed content

<div id="framedDiv">
  abc<br>
  def<br>
  ghi<br>
  jkl<br>
  mno<br>
  pqr<br>
  stu<br>
  vwx<br>
  abc<br>
  def<br>
  ghi<br>
  jkl<br>
  mno<br>
  pqr<br>
  stu<br>
  vwx<br>
  abc<br>
  def<br>
  ghi<br>
  jkl<br>
  mno<br>
  pqr<br>
  stu<br>
  vwx<br>
</div>

JS on the framed content

framed = document.getElementById('framedDiv');
font_size = 12;

framed.addEventListener('wheel', function(e) {
  var target = e.target.id;
  console.log(target);
  font_size += -e.wheelDelta/100;
  this.style.fontSize = font_size + 'px';
  e.preventDefault();
});
Comments