¿Cómo recupero el ancho y alto real de un elemento HTML?

895

Supongamos que tengo un <div>que deseo centrar en la pantalla del navegador (ventana gráfica). Para hacerlo, necesito calcular el ancho y la altura del <div>elemento.

¿Qué debo usar? Incluya información sobre la compatibilidad del navegador.

snortasprocket
fuente
99
Tenga en cuenta que obtener la altura de un elemento a través de cualquier método siempre tiene un impacto en el rendimiento, ya que hace que el navegador recalcule la posición de todos los elementos en la página (reflujo). Por lo tanto, evite hacerlo demasiado. Consulte esta lista para saber qué tipo de cosas provocan un reflujo.
Marcelo Lazaroni

Respuestas:

1290

Debe usar las propiedades .offsetWidthy .offsetHeight. Tenga en cuenta que pertenecen al elemento, no .style.

var width = document.getElementById('foo').offsetWidth;

La función.getBoundingClientRect() devuelve las dimensiones y la ubicación del elemento como números de punto flotante después de realizar transformaciones CSS.

> console.log(document.getElementById('id').getBoundingClientRect())
DOMRect {
    bottom: 177,
    height: 54.7,
    left: 278.5,​
    right: 909.5,
    top: 122.3,
    width: 631,
    x: 278.5,
    y: 122.3,
}
Greg
fuente
174
¡Tener cuidado! offsetHeight / offsetWidth puede devolver 0 si ha realizado ciertas modificaciones DOM al elemento recientemente. Puede que tenga que llamar a este código en una llamada setTimeout después de haber modificado el elemento.
Dan Fabulich
37
Documentación sobre .offsetWidthy .offsetHeight: developer.mozilla.org/en/Determining_the_dimensions_of_elements
Denilson Sá Maia
31
¿En qué circunstancias devuelve 0?
Cheetah
46
@JDandChips: offsetWidthserá 0 si el elemento es display:none, mientras que el calculado widthaún podría tener un valor positivo en este caso. visibility:hiddenno afecta a la offsetWidth.
MrWhite
21
@Supuhstar ambos tienen diferentes significados. offsetWidthdevuelve el cuadro "completo" que incluye contenido, relleno y bordes; while clientWidthdevuelve solo el tamaño del cuadro de contenido (por lo que tendrá un valor menor siempre que el elemento tenga un relleno o borde diferente de cero). (Mod editado para mayor claridad)
Edurne Pascual
200

Echa un vistazo a Element.getBoundingClientRect().

Este método devolverá un objeto que contiene las width, heighty algunos otros valores útiles:

{
    width: 960,
    height: 71,
    top: 603,
    bottom: 674,
    left: 360,
    right: 1320
}

Por ejemplo:

var element = document.getElementById('foo');
var positionInfo = element.getBoundingClientRect();
var height = positionInfo.height;
var width = positionInfo.width;

Creo que esto no tiene los problemas que .offsetWidthy a .offsetHeightveces regresan 0(como se discute en los comentarios aquí )

Otra diferencia es que getBoundingClientRect()puede devolver píxeles fraccionarios, donde .offsetWidthy .offsetHeightse redondeará al entero más cercano.

Nota IE8 : getBoundingClientRectno devuelve altura y ancho en IE8 y menos. *

Si debe admitir IE8, use .offsetWidthy .offsetHeight:

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

Vale la pena señalar que el Objeto devuelto por este método no es realmente un objeto normal . Sus propiedades no son enumerables (así, por ejemplo,Object.keys no funciona de forma inmediata).

Más información sobre esto aquí: la mejor manera de convertir un ClientRect / DomRect en un objeto simple

Referencia:

Zach Lysobey
fuente
8
getboundingClientRect () devolverá el ancho y la altura reales de los elementos escalados a través de css, mientras que offsetHeighty offsetWidthno lo hará.
Lucas
66

NOTA : esta respuesta se escribió en 2008. En ese momento, la mejor solución para varios navegadores para la mayoría de las personas era usar jQuery. Dejo la respuesta aquí para la posteridad y, si estás usando jQuery, esta es una buena manera de hacerlo. Si está utilizando algún otro marco o JavaScript puro, la respuesta aceptada es probablemente el camino a seguir.

A partir de jQuery 1.2.6 puede usar una de las funciones principales de CSS , heighty width(o outerHeighty outerWidth, según corresponda).

var height = $("#myDiv").height();
var width = $("#myDiv").width();

var docHeight = $(document).height();
var docWidth = $(document).width();
tvanfosson
fuente
45

En caso de que sea útil para alguien, pongo un cuadro de texto, un botón y div todo con el mismo CSS:

width:200px;
height:20px;
border:solid 1px #000;
padding:2px;

<input id="t" type="text" />
<input id="b" type="button" />
<div   id="d"></div>

Lo probé en Chrome, Firefox y ie-edge, probé con jquery y sin él, y lo probé con y sin box-sizing:border-box. Siempre con<!DOCTYPE html>

Los resultados:

                                                               Firefox       Chrome        IE-Edge    
                                                              with   w/o    with   w/o    with   w/o     box-sizing

$("#t").width()                                               194    200    194    200    194    200
$("#b").width()                                               194    194    194    194    194    194
$("#d").width()                                               194    200    194    200    194    200

$("#t").outerWidth()                                          200    206    200    206    200    206
$("#b").outerWidth()                                          200    200    200    200    200    200
$("#d").outerWidth()                                          200    206    200    206    200    206

$("#t").innerWidth()                                          198    204    198    204    198    204
$("#b").innerWidth()                                          198    198    198    198    198    198
$("#d").innerWidth()                                          198    204    198    204    198    204

$("#t").css('width')                                          200px  200px  200px  200px  200px  200px
$("#b").css('width')                                          200px  200px  200px  200px  200px  200px
$("#d").css('width')                                          200px  200px  200px  200px  200px  200px

$("#t").css('border-left-width')                              1px    1px    1px    1px    1px    1px
$("#b").css('border-left-width')                              1px    1px    1px    1px    1px    1px
$("#d").css('border-left-width')                              1px    1px    1px    1px    1px    1px

$("#t").css('padding-left')                                   2px    2px    2px    2px    2px    2px
$("#b").css('padding-left')                                   2px    2px    2px    2px    2px    2px
$("#d").css('padding-left')                                   2px    2px    2px    2px    2px    2px

document.getElementById("t").getBoundingClientRect().width    200    206    200    206    200    206
document.getElementById("b").getBoundingClientRect().width    200    200    200    200    200    200
document.getElementById("d").getBoundingClientRect().width    200    206    200    206    200    206

document.getElementById("t").offsetWidth                      200    206    200    206    200    206
document.getElementById("b").offsetWidth                      200    200    200    200    200    200
document.getElementById("d").offsetWidth                      200    206    200    206    200    206
Graham
fuente
1
Para ser claros ... ¿alguno de esos navegadores hace algo diferente entre sí? No puedo encontrar ninguna diferencia ... Además, no estoy votando negativamente (todavía), pero esto realmente no responde directamente a la pregunta, aunque podría editarse fácilmente para hacerlo.
Zach Lysobey
1
No estaba destinado a responder la pregunta, ya ha sido respondida. Solo información útil y sí, todos los principales navegadores de la última versión están de acuerdo con estos valores, lo cual es algo bueno.
Graham
3
Bueno ... si tu intención no es responder la pregunta, entonces esto realmente no pertenece aquí (como una "respuesta"). Consideraría incluir esto en algún recurso externo (tal vez una esencia de GitHub o una publicación de blog) y vincularlo en un comentario sobre la Pregunta original o una de las respuestas.
Zach Lysobey
21
@ZachLysobey Hay excepciones para cada regla, y esto es algo genial y útil de ver.
Dan Nissenbaum
16

Según MDN: determinar las dimensiones de los elementos

offsetWidthy offsetHeightdevuelve la "cantidad total de espacio que ocupa un elemento, incluido el ancho del contenido visible, las barras de desplazamiento (si corresponde), el relleno y el borde"

clientWidthy clientHeightdevuelve "cuánto espacio ocupa el contenido visualizado real, incluido el relleno pero sin incluir el borde, los márgenes o las barras de desplazamiento"

scrollWidthy scrollHeightdevuelve el "tamaño real del contenido, independientemente de cuánto esté visible actualmente"

Por lo tanto, depende de si se espera que el contenido medido esté fuera del área visible actual.

Harlem Ardilla
fuente
5

Solo necesita calcularlo para IE7 y versiones anteriores (y solo si su contenido no tiene un tamaño fijo). Sugiero usar comentarios condicionales HTML para limitar el hackeo a viejos IE que no admiten CSS2. Para todos los demás navegadores, use esto:

<style type="text/css">
    html,body {display:table; height:100%;width:100%;margin:0;padding:0;}
    body {display:table-cell; vertical-align:middle;}
    div {display:table; margin:0 auto; background:red;}
</style>
<body><div>test<br>test</div></body>

Esta es la solución perfecta. Se centra <div>de cualquier tamaño y lo encoge al tamaño de su contenido.

Kornel
fuente
3

Es fácil modificar los estilos de los elementos, pero es un poco difícil leer el valor.

JavaScript no puede leer ninguna propiedad de estilo de elemento (elem.style) proveniente de css (interno / externo) a menos que use el método incorporado, llame a getComputedStyle en javascript.

getComputedStyle (elemento [, pseudo])

Elemento: El elemento para el que se lee el valor.
pseudo: un pseudo-elemento si es necesario, por ejemplo :: antes. Una cadena vacía o sin argumento significa el elemento en sí.

El resultado es un objeto con propiedades de estilo, como elem.style, pero ahora con respecto a todas las clases css.

Por ejemplo, aquí el estilo no ve el margen:

<head>
  <style> body { color: red; margin: 5px } </style>
</head>
<body>

  <script>
    let computedStyle = getComputedStyle(document.body);

    // now we can read the margin and the color from it

    alert( computedStyle.marginTop ); // 5px
    alert( computedStyle.color ); // rgb(255, 0, 0)
  </script>

</body>

Así que modificó su código javaScript para incluir el getComputedStyle del elemento que desea obtener es ancho / alto u otro atributo

window.onload = function() {

    var test = document.getElementById("test");
    test.addEventListener("click", select);


    function select(e) {                                  
        var elementID = e.target.id;
        var element = document.getElementById(elementID);
        let computedStyle = getComputedStyle(element);
        var width = computedStyle.width;
        console.log(element);
        console.log(width);
    }

}

Valores calculados y resueltos

Hay dos conceptos en CSS:

Un valor de estilo calculado es el valor después de aplicar todas las reglas CSS y la herencia CSS, como resultado de la cascada CSS. Puede parecer altura: 1em o tamaño de fuente: 125%.

Un valor de estilo resuelto es el que finalmente se aplica al elemento. Valores como 1em o 125% son relativos. El navegador toma el valor calculado y hace que todas las unidades sean fijas y absolutas, por ejemplo: altura: 20 píxeles o tamaño de fuente: 16 píxeles. Para las propiedades de geometría, los valores resueltos pueden tener un punto flotante, como el ancho: 50.5px.

Hace mucho tiempo, getComputedStyle se creó para obtener valores calculados, pero resultó que los valores resueltos son mucho más convenientes y el estándar cambió.
Así que hoy en día getComputedStyle realmente devuelve el valor resuelto de la propiedad.

Tenga en cuenta:

getComputedStyle requiere el nombre completo de la propiedad

Siempre debe solicitar la propiedad exacta que desea, como paddingLeft o height o width. De lo contrario, no se garantiza el resultado correcto.

Por ejemplo, si hay propiedades paddingLeft / paddingTop, ¿qué deberíamos obtener para getComputedStyle (elem) .padding? ¿Nada o tal vez un valor "generado" a partir de rellenos conocidos? No hay una regla estándar aquí.

Hay otras inconsistencias. Como ejemplo, algunos navegadores (Chrome) muestran 10px en el documento a continuación, y algunos de ellos (Firefox), no:

<style>
  body {
    margin: 30px;
    height: 900px;
  }
</style>
<script>
  let style = getComputedStyle(document.body);
  alert(style.margin); // empty string in Firefox
</script>

para más información https://javascript.info/styles-and-classes

Lekens
fuente
1

element.offsetWidth y element.offsetHeight deberían hacer, como se sugirió en la publicación anterior.

Sin embargo, si solo desea centrar el contenido, hay una mejor manera de hacerlo. Suponiendo que usa xhtml estricto DOCTYPE. establece el margen: 0, propiedad automática y ancho requerido en px para la etiqueta del cuerpo. El contenido se alinea al centro de la página.

questzen
fuente
1
Creo que también quiere centrarlo verticalmente, lo cual es un problema con CSS a menos que pueda cumplir con algunos criterios específicos (por ejemplo, contenido de tamaño conocido)
Greg
1

... parece que CSS ayuda a poner div en el centro ...

<style>
 .monitor {
 position:fixed;/* ... absolute possible if on :root */
 top:0;bottom:0;right:0;left:0;
 visibility:hidden;
 }
 .wrapper {
 width:200px;/* this is size range */
 height:100px;
 position:absolute;
 left:50%;top:50%;
 visibility:hidden;
 }

 .content {
 position:absolute;
 width: 100%;height:100%;
 left:-50%;top:-50%;
 visibility:visible;
 }

</style>

 <div class="monitor">
  <div class="wrapper">
   <div class="content">

 ... so you hav div 200px*100px on center ...

  </div>
 </div>
</div>
sanecina
fuente
0

También puedes usar este código:

var divID = document.getElementById("divid");

var h = divID.style.pixelHeight;
Sergio
fuente
1
Hmm, funciona en Chrome e IE9, no parece funcionar en Firefox. ¿Funciona solo para ciertos tipos de documentos?
BrainSlugs83
1
pixelHeight fue una invención de Internet Explorer que ya no debería usarse stackoverflow.com/q/17405066/2194590
HolgerJeromin
0

si necesita centrarlo en el puerto de visualización del navegador; puedes lograrlo solo con CSS

yourSelector {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
} 
tdjprog
fuente
-2

Aquí está el código para WKWebView que determina la altura de un elemento Dom específico (no funciona correctamente para toda la página)

let html = "<body><span id=\"spanEl\" style=\"font-family: '\(taskFont.fontName)'; font-size: \(taskFont.pointSize - 4.0)pt; color: rgb(\(red), \(blue), \(green))\">\(textValue)</span></body>"
webView.navigationDelegate = self
webView.loadHTMLString(taskHTML, baseURL: nil)

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    webView.evaluateJavaScript("document.getElementById(\"spanEl\").getBoundingClientRect().height;") { [weak self] (response, error) in
        if let nValue = response as? NSNumber {

        }
    }
}
Aleksey Mazurenko
fuente
para que quede claro, este es el swiftcódigo de iOS , ¿verdad? No es JavaScript Estoy reteniendo un voto negativo (b / c, esto en realidad puede ser bastante útil), pero tenga en cuenta que esto no responde a la pregunta, y probablemente sería más apropiado en otra pregunta específica de iOS. Si ya no existe ninguno, tal vez considere preguntar a uno y responder a sí mismo.
Zach Lysobey
-3

Si offsetWidth devuelve 0, puede obtener la propiedad de ancho de estilo del elemento y buscar un número. "100px" -> 100

/\d*/.exec(MyElement.style.width)

Arko
fuente