Recuperar la posición (X, Y) de un elemento HTML en relación con la ventana del navegador

1882

Quiero saber cómo obtener la posición X e Y de elementos HTML como imgy diven JavaScript en relación con la ventana del navegador.

7
  • 7
    Había estado usando estas 7 líneas de código que funcionan en todos los navegadores con discrepancias en ie5,6,7 (no recordaba haber tenido ningún problema ... puede ser del tipo doc) ... quirksmode.org/js/findpos. html y lo había estado usando mucho durante tantos años. Puede ser que una sola persona pueda señalar los defectos, si los hay. 2/04/2015 a las 15:27
  • 121
    @AnthonyWJones, supongo que necesitabas el placer pedante, pero es obvio, como siempre lo es cuando no se especifica, que el OP se refiere al caso más general, o se refiere a las coordenadas de la ventana del navegador.
    Motes
    26 de mayo de 2015 a las 20:29
  • dieciséis
    @Mote, No, no es tan obvio. Dejemos a un lado la inferencia, la subjetividad y los falsos axiomas. Puede ser relativo a la ventana gráfica o la parte superior de la página (también conocido como document.documentElement). 22/10/2017 a las 2:27
  • 19
    Por defecto, el término más general no es una inferencia, es la progresión lógica, por lo que sería relativo a la ventana, o "parte superior de la página" podría ser el término como lo pones. En la teoría de juegos, se codifica como un concepto llamado punto de Schelling. Asegúrese de especificar cuándo no se refiere al caso más general.
    Motes
    22/10/2017 a las 18:45
  • 7
    El caso es que lo obvio para algunos no lo es para otros. Incluso si en teoría sabemos cuál es el caso, debido al conocimiento empírico, la claridad no lastima a nadie aquí, especialmente a aquellos que recién comienzan a programar. 22/01/19 a las 20:22
2098

El enfoque correcto es utilizar element.getBoundingClientRect():

var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);

Internet Explorer ha admitido esto desde que es probable que le interese y finalmente se estandarizó en las vistas CSSOM . Todos los demás navegadores lo adoptaron hace mucho tiempo .

Algunos navegadores también devuelven propiedades de alto y ancho, aunque esto no es estándar. Si le preocupa la compatibilidad de navegadores más antiguos, consulte las revisiones de esta respuesta para una implementación degradante optimizada.

Los valores devueltos por element.getBoundingClientRect()son relativos a la ventana gráfica. Si lo necesita en relación con otro elemento, simplemente reste un rectángulo del otro:

var bodyRect = document.body.getBoundingClientRect(),
    elemRect = element.getBoundingClientRect(),
    offset   = elemRect.top - bodyRect.top;

alert('Element is ' + offset + ' vertical pixels from <body>');
1
346

Las bibliotecas hacen todo lo posible para obtener compensaciones precisas para un elemento.
aquí hay una función simple que hace el trabajo en todas las circunstancias que he probado.

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}
var x = getOffset( document.getElementById('yourElId') ).left; 
1
  • 14
    cambie: el = el.parentNode por: el = el.offsetParent; y parece funcionar para iframes anidados ahora ... ¿Estoy pensando que eso es lo que pretendías?
    Adam
    29/07/2009 a las 20:19
311

Esta función devuelve la posición de un elemento en relación con todo el documento (página):

function getOffset(el) {
  const rect = el.getBoundingClientRect();
  return {
    left: rect.left + window.scrollX,
    top: rect.top + window.scrollY
  };
}

Usando esto podemos obtener la posición X:

getOffset(element).left

... o la posición Y:

getOffset(element).top

Versión de TypeScript:

export type ElementOffset = {
  left: number;
  top: number
};

/**
 * Returns an element's position relative to the whole document (page).
 *
 * If the element does not exist, returns O/O (top-left window corner).
 *
 * @example getOffset(document.getElementById('#element'));
 *
 * @param el
 * @see https://stackoverflow.com/a/28222246/2391795
 */
export const getElementOffset = (el: Element | null): ElementOffset => {
  const rect = el?.getBoundingClientRect();

  return {
    left: (rect?.left || 0) + window?.scrollX,
    top: (rect?.top || 0) + window?.scrollY,
  };
};

export default getElementOffset;
0
146

Si desea que se haga solo en javascript , aquí hay algunas líneas que usangetBoundingClientRect()

window.scrollY + document.querySelector('#elementId').getBoundingClientRect().top // Y

window.scrollX + document.querySelector('#elementId').getBoundingClientRect().left // X

La primera línea devolverá offsetTopdecir Y en relación con el documento. La segunda línea devolverá, offsetLeftdigamos, X relativo al documento.

getBoundingClientRect() es una función de JavaScript que devuelve la posición del elemento en relación con la ventana gráfica de la ventana.

0
53

Los elementos HTML en la mayoría de los navegadores tendrán: -

offsetLeft
offsetTop

Estos especifican la posición del elemento en relación con su padre más cercano que tiene diseño. A menudo se puede acceder a este padre mediante la propiedad offsetParent.

IE y FF3 tienen

clientLeft
clientTop

Estas propiedades son menos comunes, especifican la posición de un elemento con su área de cliente principal (el área acolchada es parte del área de cliente, pero el borde y el margen no lo son).

0
37

Si la página incluye, al menos, cualquier "DIV", la función proporcionada por meouw arroja el valor "Y" más allá de los límites de la página actual. Para encontrar la posición exacta, necesita manejar tanto offsetParent's como parentNode's.

Pruebe el código que se proporciona a continuación (está marcado para FF2):


var getAbsPosition = function(el){
    var el2 = el;
    var curtop = 0;
    var curleft = 0;
    if (document.getElementById || document.all) {
        do  {
            curleft += el.offsetLeft-el.scrollLeft;
            curtop += el.offsetTop-el.scrollTop;
            el = el.offsetParent;
            el2 = el2.parentNode;
            while (el2 != el) {
                curleft -= el2.scrollLeft;
                curtop -= el2.scrollTop;
                el2 = el2.parentNode;
            }
        } while (el.offsetParent);

    } else if (document.layers) {
        curtop += el.y;
        curleft += el.x;
    }
    return [curtop, curleft];
};

2
  • 1
    al igual que con las otras soluciones, incluso con FF 24.4, el código anterior no funciona cuando existen anchos de borde como parte del diseño de posicionamiento.
    rob
    12 de mayo de 2014 a las 20:46
  • Eres un salvavidas. ¡Estoy trabajando en algunos errores de GWT bastante profundos en este momento y lanzar esto en un método JSNI resuelve todos mis problemas! 10/06/2015 a las 21:27
35

Puede agregar dos propiedades para Element.prototypeobtener la parte superior / izquierda de cualquier elemento.

Object.defineProperty( Element.prototype, 'documentOffsetTop', {
    get: function () { 
        return this.offsetTop + ( this.offsetParent ? this.offsetParent.documentOffsetTop : 0 );
    }
} );

Object.defineProperty( Element.prototype, 'documentOffsetLeft', {
    get: function () { 
        return this.offsetLeft + ( this.offsetParent ? this.offsetParent.documentOffsetLeft : 0 );
    }
} );

Esto se llama así:

var x = document.getElementById( 'myDiv' ).documentOffsetLeft;

Aquí hay una demostración que compara los resultados con los de jQuery offset().topy .left: http://jsfiddle.net/ThinkingStiff/3G7EZ/

1
  • dieciséis
    En Element.prototypegeneral, modificar se considera una mala idea . Conduce a un código realmente difícil de mantener. Además, este código no tiene en cuenta el desplazamiento. 22/06/2015 a las 21:58
25

Para recuperar la posición relativa a la página de manera eficiente y sin usar una función recursiva: (también incluye IE)

var element = document.getElementById('elementId'); //replace elementId with your element's Id.
var rect = element.getBoundingClientRect();
var elementLeft,elementTop; //x and y
var scrollTop = document.documentElement.scrollTop?
                document.documentElement.scrollTop:document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft?                   
                 document.documentElement.scrollLeft:document.body.scrollLeft;
elementTop = rect.top+scrollTop;
elementLeft = rect.left+scrollLeft;
1
  • Incluir todos los importantes scrollTop / scrollLeft hace que esta respuesta sea un poco más correcta. 6/12/14 a las 22:24
22

¿Qué tal algo como esto, al pasar el ID del elemento y devolverá la izquierda o la parte superior, también podemos combinarlos:

1) encontrar a la izquierda

function findLeft(element) {
  var rec = document.getElementById(element).getBoundingClientRect();
  return rec.left + window.scrollX;
} //call it like findLeft('#header');

2) encontrar la parte superior

function findTop(element) {
  var rec = document.getElementById(element).getBoundingClientRect();
  return rec.top + window.scrollY;
} //call it like findTop('#header');

o 3) encontrar la izquierda y la parte superior juntas

function findTopLeft(element) {
  var rec = document.getElementById(element).getBoundingClientRect();
  return {top: rec.top + window.scrollY, left: rec.left + window.scrollX};
} //call it like findTopLeft('#header');
dieciséis

jQuery .offset () obtendrá las coordenadas actuales del primer elemento, o establecerá las coordenadas de cada elemento, en el conjunto de elementos coincidentes, en relación con el documento.

2
  • 1
    Por alguna razón, no da los mismos resultados en IE en comparación con otros navegadores. Creo que en IE está dando una posición relativa a la ventana, por lo que si se desplaza, obtendrá resultados diferentes en IE en comparación con otros 10/0813 a las 16:19
  • 1
    offset () se confunde con el zoom, al menos en Android Chrome, por lo que es inútil. stackoverflow.com/a/11396681/1691517 muestra la forma tolerante al zoom. 31 de mayo de 2015 a las 18:45
15

Es posible que le sirva mejor si utiliza un marco de JavaScript, que tiene funciones para devolver dicha información (¡y mucho más!) De forma independiente del navegador. A continuación, presentamos algunos:

Con estos marcos, podría hacer algo como: $('id-of-img').top obtener la coordenada de píxel y de la imagen.

0
12
/**
 *
 * @param {HTMLElement} el
 * @return {{top: number, left: number}}
 */
function getDocumentOffsetPosition(el) {
    var position = {
        top: el.offsetTop,
        left: el.offsetLeft
    };
    if (el.offsetParent) {
        var parentPosition = getDocumentOffsetPosition(el.offsetParent);
        position.top += parentPosition.top;
        position.left += parentPosition.left;
    }
    return position;
}

Gracias a ThinkingStiff por la respuesta , esta es solo otra versión.

10

Tomé la respuesta de @ meouw, agregué en el clientLeft que permite el borde, y luego creé tres versiones:

getAbsoluteOffsetFromBody - similar a @ meouw's, esto obtiene la posición absoluta relativa al cuerpo o elemento html del documento (dependiendo del modo peculiar)

getAbsoluteOffsetFromGivenElement: devuelve la posición absoluta relativa al elemento dado (relativoEl). Tenga en cuenta que el elemento dado debe contener el elemento el, o este se comportará igual que getAbsoluteOffsetFromBody. Esto es útil si tiene dos elementos contenidos dentro de otro elemento (conocido) (opcionalmente varios nodos en el árbol de nodos) y desea que estén en la misma posición.

getAbsoluteOffsetFromRelative: devuelve la posición absoluta relativa al primer elemento principal con posición: relativa. Esto es similar a getAbsoluteOffsetFromGivenElement, por la misma razón, pero solo llegará hasta el primer elemento coincidente.

getAbsoluteOffsetFromBody = function( el )
{   // finds the offset of el from the body or html element
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}

getAbsoluteOffsetFromGivenElement = function( el, relativeEl )
{   // finds the offset of el from relativeEl
    var _x = 0;
    var _y = 0;
    while( el && el != relativeEl && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}

getAbsoluteOffsetFromRelative = function( el )
{   // finds the offset of el from the first parent with position: relative
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
        if (el != null)
        {
            if (getComputedStyle !== 'undefined')
                valString = getComputedStyle(el, null).getPropertyValue('position');
            else
                valString = el.currentStyle['position'];
            if (valString === "relative")
                el = null;
        }
    }
    return { top: _y, left: _x };
}

Si aún tiene problemas, particularmente relacionados con el desplazamiento, puede intentar buscar en http://www.greywyvern.com/?post=331 - Noté al menos una pieza de código cuestionable en getStyle que debería estar bien asumiendo que los navegadores se comportan bien , pero no he probado el resto en absoluto.

3
  • Interesante ... pero en Edge getAbsoluteOffsetFromBody (element) .top devuelve un valor diferente a medida que me desplazo, en Chrome se mantiene constante a medida que me desplazo. Parece que Edge se está ajustando con la posición de desplazamiento. Cuando el elemento se desplaza fuera de la vista, obtengo un valor negativo. 13/01/18 a las 16:13
  • getAbsoluteOffsetFromRelative me alegró el día, tuve que reproducir la información sobre herramientas de bootstrap sin Javascript de bootstrap, me ayudó mucho.
    Nolyurn
    13/08/18 a las 15:52
  • En caso de que Meouw cambie su nombre de usuario, enlace para responder: stackoverflow.com/a/442474/3654837 . (No quiero toparme con este viejo hilo, así que sí, puse un comentario)
    Mukyuu
    10 de enero de 2020 a las 7:22
8

si usa jQuery, el complemento de dimensiones es excelente y le permite especificar exactamente lo que desea.

p.ej

Posición relativa, posición absoluta, posición absoluta sin relleno, con relleno ...

Continúa, digamos que hay muchas cosas que puedes hacer con él.

Además, la ventaja de usar jQuery es su tamaño de archivo liviano y fácil de usar, no volverá a JavaScript sin él después.

0
8

Si está utilizando jQuery, esta podría ser una solución simple:

<script>
  var el = $("#element");
  var position = el.position();
  console.log( "left: " + position.left + ", top: " + position.top );
</script>
8

Diferencia entre pequeño y pequeño

function getPosition( el ) {
    var x = 0;
    var y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
    x += el.offsetLeft - el.scrollLeft;
    y += el.offsetTop - el.scrollTop;
    el = el.offsetParent;
    }
    return { top: y, left: x };
}

Mira un ejemplo de coordenadas: http://javascript.info/tutorial/coordinates

2
  • Desafortunadamente, esto no funciona para todos los elementos que se pueden encontrar dentro de un documento HTML moderno. Embedded <svg>elementos, por ejemplo, no tienen offsetLeft, offsetTopy offsetParentpropiedades. 19/10/2016 a las 9:39
  • Es justo DIVo IMGno SVG. ¿Ver "Mira un ejemplo de coordenadas"? puede encontrar el objeto svg en la llamada de posición getOffsetRect , intente y dependa del trabajo del objeto. 19/10/2016 a las 20:24
7

El enfoque más limpio que he encontrado es una versión simplificada de la técnica utilizada por jQuery offset. Similar a algunas de las otras respuestas con las que comienza getBoundingClientRect; luego usa el windowy el documentElementpara ajustar la posición de desplazamiento, así como cosas como el margen en el body(a menudo el predeterminado).

var rect = el.getBoundingClientRect();
var docEl = document.documentElement;

var rectTop = rect.top + window.pageYOffset - docEl.clientTop;
var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;

var els = document.getElementsByTagName("div");
var docEl = document.documentElement;

for (var i = 0; i < els.length; i++) {

  var rect = els[i].getBoundingClientRect();

  var rectTop = rect.top + window.pageYOffset - docEl.clientTop;
  var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;

  els[i].innerHTML = "<b>" + rectLeft + ", " + rectTop + "</b>";
}
div {
  width: 100px;
  height: 100px;
  background-color: red;
  border: 1px solid black;
}
#rel {
  position: relative;
  left: 10px;
  top: 10px;
}
#abs {
  position: absolute;
  top: 250px;
  left: 250px;
}
<div id="rel"></div>
<div id="abs"></div>
<div></div>
6

Este es el mejor código que he logrado crear (también funciona en iframes, a diferencia del offset () de jQuery). Parece que webkit tiene un comportamiento un poco diferente.

Basado en el comentario de meouw:

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        // chrome/safari
        if ($.browser.webkit) {
            el = el.parentNode;
        } else {
            // firefox/IE
            el = el.offsetParent;
        }
    }
    return { top: _y, left: _x };
}
3
  • 1
    Tenga en cuenta que jQuerydeberá utilizar $.browser.webkit; Tendrás que jugar con él navigator.userAgentpara hacer lo mismo con puro JavaScript.
    S P
    7 de marzo de 2012 a las 2:47
  • 3
    $ .browser ya no está disponible en la última versión de jQuery
    Gus
    12/01/2014 a las 18:22
  • desafortunadamente, incluso con FF 24.4, el código anterior no funciona cuando existen anchos de borde como parte del diseño de posicionamiento.
    rob
    12 de mayo de 2014 a las 20:43
6

Si bien es muy probable que esto se pierda en la parte inferior de tantas respuestas, las principales soluciones aquí no funcionaron para mí.
Por lo que pude ver, ninguna de las otras respuestas habría ayudado.

Situación :
En una página HTML5 tenía un menú que era un elemento de navegación dentro de un encabezado (no EL encabezado sino un encabezado en otro elemento).
Quería que la navegación se mantuviera en la parte superior una vez que un usuario se desplazara hasta ella, pero antes de esto, el encabezado estaba en una posición absoluta (por lo que podría superponerlo ligeramente sobre algo más).
Las soluciones anteriores nunca provocaron un cambio porque .offsetTop no iba a cambiar ya que este era un elemento posicionado absoluto. Además, la propiedad .scrollTop era simplemente la parte superior del elemento más superior ... es decir, 0 y siempre sería 0.
Cualquier prueba que realicé utilizando estos dos (y lo mismo con los resultados de getBoundingClientRect) no me diría si la parte superior de la barra de navegación alguna vez se desplazó hasta la parte superior de la página visible (nuevamente, como se informó en la consola, simplemente permanecieron en los mismos números mientras se desplazaban ocurrió).

Solución
La solución para mí estaba utilizando

window.visualViewport.pageTop

El valor de la propiedad pageTop refleja la sección visible de la pantalla, lo que me permite rastrear dónde está un elemento en referencia a los límites del área visible.

Probablemente sea innecesario decirlo, cada vez que estoy lidiando con el desplazamiento, espero usar esta solución para responder programáticamente al movimiento de los elementos que se desplazan.
Espero que ayude a alguien más.
NOTA IMPORTANTE: Esto parece funcionar en Chrome y Opera actualmente y definitivamente no en Firefox (6-2018) ... hasta que Firefox admita visualViewport, recomiendo NO usar este método (y espero que lo hagan pronto ... hace mucho más sentido que el resto).


ACTUALIZACIÓN:
Solo una nota sobre esta solución.
Aunque todavía encuentro lo que descubrí que es muy valioso para situaciones en las que "... responden programáticamente al movimiento de los elementos que se desplazan". es aplicable. La mejor solución para el problema que tuve fue usar CSS para establecer la posición: pegajosoen el elemento. Al usar Sticky, puede hacer que un elemento permanezca en la parte superior sin usar javascript (NOTA: hay ocasiones en que esto no funcionará tan eficazmente como cambiar el elemento a fijo, pero para la mayoría de los usos, el enfoque adhesivo probablemente sea superior)

ACTUALIZACIÓN01:
Entonces me di cuenta de que para una página diferente, tenía un requisito en el que necesitaba detectar la posición de un elemento en una configuración de desplazamiento ligeramente compleja (paralaje más elementos que se desplazan como parte de un mensaje). En ese escenario me di cuenta de que lo siguiente proporcionaba el valor que utilicé para determinar cuándo hacer algo:

  let bodyElement = document.getElementsByTagName('body')[0];
  let elementToTrack = bodyElement.querySelector('.trackme');
  trackedObjPos = elementToTrack.getBoundingClientRect().top;
  if(trackedObjPos > 264)
  {
    bodyElement.style.cssText = '';
  }

Espero que esta respuesta sea más útil ahora.

3
  • es muy probable que esté en la parte superior de tantas respuestas cuando hace clic en activo para ordenar las respuestas
    lucchi
    1 de junio de 2018 a las 11:48
  • @lucchi: D bueno, supongo que podría eliminar el texto @ en la parte superior ... aunque acabo de pasar en este caso de nuevo y me di cuenta de que había encontrado una mejor solución para mi propio problema ... aunque mi respuesta es más una pie de página para las respuestas más completas. Sospecho que mis requisitos tal vez no eran tan comunes que las otras respuestas no funcionaron para mí.
    MER
    1 de junio de 2018 a las 20:14
  • 1
    De todos modos, agradezco tu respuesta, fue solo para decirte que cualquiera que esté dispuesto sabrá que escribiste algo nuevo. Usted no está solo....
    lucchi
    1 de junio de 2018 a las 22:22
6

Para obtener el desplazamiento total de un elemento, puede sumar de forma recursiva todos los desplazamientos principales:

function getParentOffset(el): number {
if (el.offsetParent) {
    return el.offsetParent.offsetTop + getParentOffset(el.offsetParent);
} else {
    return 0;
}
}

con esta función de utilidad, el desplazamiento superior total de un elemento dom es:

el.offsetTop + getParentOffset(el);
2
  • Esta respuesta se parece a lo que me gustaría, excepto que aparece el error "Error de referencia no detectado: getParentOffset no está definido". Falta una 's', ¿verdad? Así que cambié la línea de retorno de la función para agregar una 's' a 'getParentOffset'. No hay error ahora, pero saber que hubo un error me preocupa ... 18 de feb a las 18:28
  • 1
    ty para el comentario de error tipográfico, el fragmento de código se actualiza 17 de septiembre a las 11:43
5

Lo hice así para que fuera compatible con navegadores antiguos.

// For really old browser's or incompatible ones
    function getOffsetSum(elem) {
        var top = 0,
            left = 0,
            bottom = 0,
            right = 0

         var width = elem.offsetWidth;
         var height = elem.offsetHeight;

        while (elem) {
            top += elem.offsetTop;
            left += elem.offsetLeft;
            elem = elem.offsetParent;
        }

         right = left + width;
         bottom = top + height;

        return {
            top: top,
            left: left,
            bottom: bottom,
            right: right,
        }
    }

    function getOffsetRect(elem) {
        var box = elem.getBoundingClientRect();

        var body = document.body;
        var docElem = document.documentElement;

        var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;
        var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;

        var clientTop = docElem.clientTop;
        var clientLeft = docElem.clientLeft;


        var top = box.top + scrollTop - clientTop;
        var left = box.left + scrollLeft - clientLeft;
        var bottom = top + (box.bottom - box.top);
        var right = left + (box.right - box.left);

        return {
            top: Math.round(top),
            left: Math.round(left),
            bottom: Math.round(bottom),
            right: Math.round(right),
        }
    }

    function getOffset(elem) {
        if (elem) {
            if (elem.getBoundingClientRect) {
                return getOffsetRect(elem);
            } else { // old browser
                return getOffsetSum(elem);
            }
        } else
            return null;
    }

Más sobre coordenadas en JavaScript aquí: http://javascript.info/tutorial/coordinates

4

    
HTML program to show (x, y) of an
element by dragging mouse over it  you just copied it and use it on your own 
<!DOCTYPE html>
<html>
    <head>
        <title>
            position of an element
        </title>
        
        <!-- scropt to get position -->
        <script type = "text/javascript">
            function getPositionXY(element) {
                var rect = element.getBoundingClientRect();
                document.getElementById('text').innerHTML
                = 'X: ' + rect.x + '<br>' + 'Y: ' + rect.y;
            }
        </script>
    </head>
    
    <body>
        <p>Move the mouse over the text</p>
        
        <div onmouseover = "getPositionXY(this)">
            Position:
            <p id = 'text'></p>
        </div>
    
    </body>
</html>                 
3

Aquí hay un 1-liner moderno que usa Vanilla JS para iterar de forma recursiva element.offsetTopy element.offsetParent:

Función:

getTop = el => el.offsetTop + (el.offsetParent && getTop(el.offsetParent))

Uso:

const el = document.querySelector('#div_id');
const elTop = getTop(el)

Ventaja:

Siempre devuelve el desplazamiento vertical absoluto, independientemente de la posición de desplazamiento actual.


Sintaxis tradicional:

function getTop(el) {
  return el.offsetTop + (el.offsetParent && getTop(el.offsetParent));
}
2

Utilicé con éxito la solución de Andy E para colocar un modal de bootstrap 2 dependiendo del enlace en una fila de la tabla en el que hace clic el usuario. La página es una página de Tapestry 5 y el javascript a continuación se importa en la clase de página de Java.

javascript:

function setLinkPosition(clientId){
var bodyRect = document.body.getBoundingClientRect(),
elemRect = clientId.getBoundingClientRect(),
offset   = elemRect.top - bodyRect.top;
offset   = offset + 20;
$('#serviceLineModal').css("top", offset);

}

Mi código modal:

<div id="serviceLineModal" class="modal hide fade add-absolute-position" data-backdrop="static" 
 tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="top:50%;">
<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
    <h3 id="myModalLabel">Modal header</h3>
</div>

<div class="modal-body">
    <t:zone t:id="modalZone" id="modalZone">
        <p>You selected service line number: ${serviceLineNumberSelected}</p>
    </t:zone>
</div>

<div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
    <!-- <button class="btn btn-primary">Save changes</button> -->
</div>

El enlace en el bucle:

<t:loop source="servicesToDisplay" value="service" encoder="encoder">
<tr style="border-right: 1px solid black;">       
    <td style="white-space:nowrap;" class="add-padding-left-and-right no-border"> 
        <a t:type="eventLink" t:event="serviceLineNumberSelected" t:context="service.serviceLineNumber" 
            t:zone="pageZone" t:clientId="modalLink${service.serviceLineNumber}"
            onmouseover="setLinkPosition(this);">
            <i class="icon-chevron-down"></i> <!-- ${service.serviceLineNumber} -->
        </a>
    </td>

Y el código java en la clase de página:

void onServiceLineNumberSelected(String number){
    checkForNullSession();
    serviceLineNumberSelected = number;
    addOpenServiceLineDialogCommand();
    ajaxResponseRenderer.addRender(modalZone);
}

protected void addOpenServiceLineDialogCommand() {
    ajaxResponseRenderer.addCallback(new JavaScriptCallback() {
        @Override
        public void run(JavaScriptSupport javascriptSupport) {
            javascriptSupport.addScript("$('#serviceLineModal').modal('show');");
        }
    });
}

Espero que esto ayude a alguien, esta publicación ayudó.

1
  • Este código js me ayudó, tengo una aplicación de formularios web antigua que usa múltiples marcadores de posición para inyectar páginas .aspx y no pude averiguar cómo agregarChild () de un cuadro emergente que estaba creando para colocarlo en la ventana gráfica porque todo el árbol DOM está bloqueado con los marcadores de posición múltiples y el marcado incorrecto. Usar body.getBoundingClientRect () y luego usar su parte superior en el posicionamiento era lo que necesitaba. Gracias. 14/08/15 a las 21:32
1

Después de mucha investigación y pruebas, esto parece funcionar.

function getPosition(e) {
    var isNotFirefox = (navigator.userAgent.toLowerCase().indexOf('firefox') == -1);
    var x = 0, y = 0;
    while (e) {
        x += e.offsetLeft - e.scrollLeft + (isNotFirefox ? e.clientLeft : 0);
        y += e.offsetTop - e.scrollTop + (isNotFirefox ? e.clientTop : 0);
        e = e.offsetParent;
    }
    return { x: x + window.scrollX, y: y + window.scrollY };
}

ver http://jsbin.com/xuvovalifo/edit?html,js,output

1

Solo pensé en tirar esto por ahí también.
No he podido probarlo en navegadores más antiguos, pero funciona en el último de los 3 principales :)

Element.prototype.getOffsetTop = function() {
    return ( this.parentElement )? this.offsetTop + this.parentElement.getOffsetTop(): this.offsetTop;
};
Element.prototype.getOffsetLeft = function() {
    return ( this.parentElement )? this.offsetLeft + this.parentElement.getOffsetLeft(): this.offsetLeft;
};
Element.prototype.getOffset = function() {
    return {'left':this.getOffsetLeft(),'top':this.getOffsetTop()};
};
1

Esto es tan fácil como dos líneas en JS:

var elem = document.getElementById("id");    
alert(elem.getBoundingClientRect());
1
  • 2
    Esta respuesta está incompleta y no agrega nada a las respuestas anteriores.
    mfluehr
    2 dic.20 a las 15:18
0

Dado que los diferentes navegadores están representando el borde, el relleno, el margen, etc. de manera diferente. Escribí una pequeña función para recuperar las posiciones superior e izquierda de un elemento específico en cada elemento raíz que desee en una dimensión precisa:

function getTop(root, offset) {
    var rootRect = root.getBoundingClientRect();
    var offsetRect = offset.getBoundingClientRect();
    return offsetRect.top - rootRect.top;
}

Para recuperar la posición izquierda debe regresar:

    return offsetRect.left - rootRect.left;
-1

Get position of div in respect to left and Top

  var elm = $('#div_id');  //get the div
  var posY_top = elm.offset().top;  //get the position from top
  var posX_left = elm.offset().left; //get the position from left 
3
  • Voté en contra porque la parte inferior y la derecha no son propiedades de offset () 8 de mayo de 2018 a las 14:39
  • @MacroMan, respeto tu decisión pero ya he explicado en el texto que "abajo y derecha el código no está probado". Además, actualizaré mi código muy pronto. 8 de mayo de 2018 a las 16:56
  • Creo que es el.offsetTopy el.offsetLeft(el OP no dice nada sobre jQuery ... tampoco estoy seguro de por qué su respuesta usa jQuery ...) 10 de julio de 2018 a las 6:57