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

javascript - How to get the position of an iframe relative to the top window's viewport? - Stack Overflow

programmeradmin4浏览0评论

I've got html like so:

<body>
    [some stuff]
    <iframe src="pageWithMyScript.html"></iframe>
    [more stuff]
</body>

I want to find the location of the iframe relative to window.top (and/or the top.document) from a script running inside the iframe. (Ideally this would be without any frameworks, though I can always deconstruct how they do it, I suppose.)

I've got html like so:

<body>
    [some stuff]
    <iframe src="pageWithMyScript.html"></iframe>
    [more stuff]
</body>

I want to find the location of the iframe relative to window.top (and/or the top.document) from a script running inside the iframe. (Ideally this would be without any frameworks, though I can always deconstruct how they do it, I suppose.)

Share Improve this question asked Mar 12, 2012 at 22:01 sprugmansprugman 19.8k36 gold badges115 silver badges164 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 7

This can only work if both the iframe and the container share the same origin, otherwise CORS will have to be set up (to do this you will need access to both domains)

/**
 * Calculate the offset of the given iframe relative to the top window.
 * - Walks up the iframe chain, checking the offset of each one till it reaches top
 * - Only works with friendly iframes. https://developer.mozilla/en-US/docs/Web/Security/Same-origin_policy#Cross-origin_script_API_access 
 * - Takes into account scrolling, but es up with a result relative to 
 *   top iframe, regardless of being visibile withing intervening frames.
 * 
 * @param window win    the iframe we're interested in (e.g. window)
 * @param object dims   an object containing the offset so far:
 *                          { left: [x], top: [y] }
 *                          (optional - initializes with 0,0 if undefined) 
 * @return dims object above
 */
var puteFrameOffset = function(win, dims) {
    // initialize our result variable
    if (typeof dims === 'undefined') {
        var dims = { top: 0, left: 0 };
    }

    // find our <iframe> tag within our parent window
    var frames = win.parent.document.getElementsByTagName('iframe');
    var frame;
    var found = false;

    for (var i=0, len=frames.length; i<len; i++) {
        frame = frames[i];
        if (frame.contentWindow == win) {
            found = true;
            break;
        }
    }

    // add the offset & recur up the frame chain
    if (found) {
        var rect = frame.getBoundingClientRect();
        dims.left += rect.left;
        dims.top += rect.top;
        if (win !== top) {
            puteFrameOffset(win.parent, dims);
        }
    }
    return dims;
};

Most answers do not consider border and padding of the frame element.
Sometimes they are not 0, so it should be included in the conversion process.
Actual border and padding size of an element can be acquired from the "puted style".

    function getTopBoundingClientRect( e )
    {
        const rcInit = e.getBoundingClientRect();
        let f = e.ownerDocument.defaultView.frameElement;
        if ( !f )
            return rcInit;
        const rc = { left: rcInit.left, top: rcInit.top, right: rcInit.right, bottom: rcInit.bottom };
        do {
            const frc = f.getBoundingClientRect();
            const cs = f.ownerDocument.defaultView.getComputedStyle( f );
            const lm = +cs.getPropertyValue( 'border-left-width' ).slice( 0, -2 )
                + +cs.getPropertyValue( 'padding-left' ).slice( 0, -2 );
            const tm = +cs.getPropertyValue( 'border-top-width' ).slice( 0, -2 )
                + +cs.getPropertyValue( 'padding-top' ).slice( 0, -2 );
            rc.left += frc.left + lm;
            rc.top += frc.top + tm;
            rc.right += frc.left + lm;
            rc.bottom += frc.top + tm;
            f = f.ownerDocument.defaultView.frameElement;
        } while ( f );
        return rc;
    }

Of course, in cross-domain iframe, any code cannot access parent document (especially frameElement in above code.)

A bit more simple like this :

function puteFrameOffset(win, dims ) {
    dims = (typeof dims === 'undefined')?{ top: 0, left: 0}:dims;
    if (win !== top) {
        var rect = win.frameElement.getBoundingClientRect();
        dims.left += rect.left;
        dims.top += rect.top;
        puteFrameOffset(win.parent, dims );
    }
    return dims;
};

A small correction:

function puteFrameOffset(win, dims ) {
  dims = (typeof dims === 'undefined')?{ top: 0, left: 0}:dims;
  if (win !== top) {
      var rect = win.frameElement.getBoundingClientRect();
      dims.left += rect.left;
      dims.top += rect.top;
      dims = puteFrameOffset(win.parent, dims ); // recursion
  }
  return dims;
};
发布评论

评论列表(0)

  1. 暂无评论