最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Prevent location.hash in an iframe from scrolling the parent window in Chrome - Stack Overflow

programmeradmin1浏览0评论

The scenario:

I'm building a kiosk app to run in Chrome. In it i'm loading an iframe from another domain into a modal via a link with an anchor (http:/www.whatever/#specific_content).

The problem:

When that content loads, the iframe jumps down to the #specific_content but the parent page also jumps.

It's a single page kiosk app so the position of the parent page is very important. The actual details of the scenario are a bit more plicated than just the above:

  1. To inhibit scrolling in the app I have body {overflow:hidden;}
  2. To allow for positioning I use a wrapper container set to the size of the viewport.
  3. To simulate the scrolling I am either repositioning the wrapper absolutely, or positioning content within the wrapper absolutely.

To demonstrate the problem I have set up a jsFiddle but you need to see the output without the jsFiddle chrome to see the full scope of the problem:

Step 1) Click 'Link to content', that will reposition the wrapper

Step 2) Click 'Link to load', that will load the iFrame content

Demo: /

Fiddle: /

The code:

CSS:

html, body { height:100%; padding:0; margin: 0;overflow:hidden; }
.background {
    width : 100%;
    height:400%;
    background:#333 url('.jpg');
}
.wrapper { position:absolute;width:100%;height:200%; }
iframe  { width:50%;height:50%;position:fixed;top:25%;left:50%;margin-left:-25%;border:2px solid red;background-color:#ddd; }
.link   { width:100%;height:25px;position:absolute;top:25px;background-color:green; }
.anchor { position:absolute;top:400px;width:100%;height:25px;background-color:red; }

HTML

<div class="wrapper">
    <div class="background"></div>

    <a class="link" href="#linked">Link to content</a>
    <a class="anchor" name="linked" href="#footer" >Link to Load iFrame</a>
</div>
<iframe></iframe>

JS

$(function(){
    $('.link').on('click',function(){ $('.wrapper').css({top:'-400px'}); });
    $('.anchor').on('click',function(e){
        e.preventDefault();
        var href = $(this).prop('href');
        $('iframe')
        .attr({
            src: href,
            name: 'testing'
        });
    });
});

The scenario:

I'm building a kiosk app to run in Chrome. In it i'm loading an iframe from another domain into a modal via a link with an anchor (http:/www.whatever./#specific_content).

The problem:

When that content loads, the iframe jumps down to the #specific_content but the parent page also jumps.

It's a single page kiosk app so the position of the parent page is very important. The actual details of the scenario are a bit more plicated than just the above:

  1. To inhibit scrolling in the app I have body {overflow:hidden;}
  2. To allow for positioning I use a wrapper container set to the size of the viewport.
  3. To simulate the scrolling I am either repositioning the wrapper absolutely, or positioning content within the wrapper absolutely.

To demonstrate the problem I have set up a jsFiddle but you need to see the output without the jsFiddle chrome to see the full scope of the problem:

Step 1) Click 'Link to content', that will reposition the wrapper

Step 2) Click 'Link to load', that will load the iFrame content

Demo: http://jsfiddle/w47GT/8/embedded/result/

Fiddle: http://jsfiddle/w47GT/8/

The code:

CSS:

html, body { height:100%; padding:0; margin: 0;overflow:hidden; }
.background {
    width : 100%;
    height:400%;
    background:#333 url('http://incurablystircrazy.files.wordpress./2012/04/runner-at-sunset.jpg');
}
.wrapper { position:absolute;width:100%;height:200%; }
iframe  { width:50%;height:50%;position:fixed;top:25%;left:50%;margin-left:-25%;border:2px solid red;background-color:#ddd; }
.link   { width:100%;height:25px;position:absolute;top:25px;background-color:green; }
.anchor { position:absolute;top:400px;width:100%;height:25px;background-color:red; }

HTML

<div class="wrapper">
    <div class="background"></div>

    <a class="link" href="#linked">Link to content</a>
    <a class="anchor" name="linked" href="http://www.smashingmagazine.#footer" >Link to Load iFrame</a>
</div>
<iframe></iframe>

JS

$(function(){
    $('.link').on('click',function(){ $('.wrapper').css({top:'-400px'}); });
    $('.anchor').on('click',function(e){
        e.preventDefault();
        var href = $(this).prop('href');
        $('iframe')
        .attr({
            src: href,
            name: 'testing'
        });
    });
});
Share Improve this question asked Apr 8, 2013 at 15:54 natepersnatepers 5334 silver badges14 bronze badges 1
  • Well, well, @DJDavid98 nicely done. – natepers Commented Apr 8, 2013 at 17:56
Add a ment  | 

3 Answers 3

Reset to default 5

Answer can be found here: Loading iframe with an #element specified moves the parent viewpoint to the same location

The Solution:

Hide the iFrame until after it's fully loaded which bypasses the anchor effecting the parent page.

Demo: http://jsfiddle/w47GT/12/embedded/result/

Fiddle: http://jsfiddle/w47GT/12/

JS

$(function(){
    // Move the content wrapper up to simulate scroll
    $('.link').on('click',function(){ $('.wrapper').css({top:'-400px'}); });

    // Load iFrame content (previously hidden via CSS)
    $('.anchor').on('click',function(e){
        e.preventDefault();
        var href = $(this).prop('href');
        $('iframe')
        .attr({
            src: href,
            name: 'testing'
        }).on('load',function(){
            $(this).show();
        });
    });
});

thanks to @DJdavid98 for pointing to this answer.

I came up with a less conventional approach that certainly has some drawbacks.

First, the drawbacks: on any page you apply this solution, it will prevent you from effectively using hashes in your urls to scroll down to elements, and scrollIntoView is also blocked/affected. If you know your page won't need to do those things, this may be a good option for you.

The approach is to use a CSS scroll-padding-top property on your parent document with a large enough value that the "padding" pushes your scroll position back to the very top of the page, preventing the hash from scrolling anywhere. Depending on how your page is set up, the style can be applied to the document's html tag like so:

<style>
    html {
        scroll-padding-top: 99999px;
    }
</style>

You could also set it to a smaller value, like 200px, if you know that the iframe will be rendered within that distance from the top of the page.

One advantage of this approach over the excellent accepted answer is that in this approach the iframe contents will be scrolled to whatever the hash pointed at, which may have been the purpose of using a hash in the iframe URL in the first place. The accepted answer's trick with hiding the iframe to prevent scrolling on the parent window has the side effect of skipping over the scrolling that would have happened inside the iframe.

I am shooting in the dark a little here, but have you tried something like this attached to the outside page's DOM?

$(window).on("hashchange", function(e) {
  e.preventDefault();
});
发布评论

评论列表(0)

  1. 暂无评论