Como recupero a largura e a altura reais de um elemento HTML?

894

Suponha que eu tenho um <div>que eu desejo centralizar na tela do navegador (janela de visualização). Para fazer isso, preciso calcular a largura e a altura do <div>elemento.

O que devo usar? Inclua informações sobre a compatibilidade do navegador.

snortasprocket
fonte
9
Lembre-se de que a obtenção da altura de um elemento por qualquer método sempre afeta o desempenho , pois faz com que o navegador recalcule a posição de todos os elementos na página (reflow). Portanto, evite fazer demais. Confira nesta lista quais tipos de coisas desencadeiam um reflow.
Marcelo Lazaroni

Respostas:

1287

Você deve usar as propriedades .offsetWidthe .offsetHeight. Observe que eles pertencem ao elemento, não .style.

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

A função.getBoundingClientRect() retorna as dimensões e a localização do elemento como números de ponto flutuante após a realização de transformações 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
fonte
174
Cuidado! offsetHeight / offsetWidth pode retornar 0 se você tiver feito determinadas modificações DOM no elemento recentemente. Talvez você precise chamar esse código em uma chamada setTimeout depois de modificar o elemento.
Dan Fabulich 19/01/10
37
Documentação sobre .offsetWidthe .offsetHeight: developer.mozilla.org/en/Determining_the_dimensions_of_elements
Denilson Sá Maia
31
Em que circunstâncias ele retorna 0?
Cheetah
46
@JDandChips: offsetWidthserá 0 se o elemento for display:none, enquanto o calculado widthainda pode ter um valor positivo nessa instância. visibility:hiddennão afeta o offsetWidth.
MrWhite
21
@Supuhstar ambos têm significados diferentes. offsetWidthretorna a caixa "inteira", incluindo conteúdo, preenchimento e bordas; while clientWidthretorna o tamanho da caixa de conteúdo sozinha (portanto, ele terá um valor menor sempre que o elemento tiver preenchimento e / ou borda diferente de zero). (mod editado para maior clareza)
Edurne Pascual
200

Dê uma olhada Element.getBoundingClientRect().

Este método irá devolver um objecto que contenha width, heighte alguns outros valores úteis:

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

Por exemplo:

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

Eu acredito que isso não tem os problemas que eles fazem .offsetWidthe .offsetHeightonde eles retornam às vezes 0(como discutido nos comentários aqui )

Outra diferença é que getBoundingClientRect()pode retornar pixels fracionários, onde .offsetWidthe .offsetHeightarredondará para o número inteiro mais próximo.

IE8 Nota : getBoundingClientRectnão retorna altura e largura no IE8 e abaixo. *

Se você deve oferecer suporte ao IE8, use .offsetWidthe .offsetHeight:

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

Vale a pena notar que o objeto retornado por esse método não é realmente um objeto normal . Suas propriedades não são enumeráveis (por exemplo, Object.keysnão funcionam imediatamente).

Mais informações aqui: Qual a melhor forma de converter um ClientRect / DomRect em um objeto simples

Referência:

Zach Lysobey
fonte
8
getboundingClientRect () irá voltar a largura real e a altura dos elementos de escala via CSS Considerando offsetHeighte offsetWidthnão será.
Luke
66

NOTA : esta resposta foi escrita em 2008. Na época, a melhor solução entre navegadores para a maioria das pessoas era realmente usar o jQuery. Estou deixando a resposta aqui para a posteridade e, se você estiver usando jQuery, esta é uma boa maneira de fazê-lo. Se você estiver usando alguma outra estrutura ou JavaScript puro, a resposta aceita provavelmente é o caminho a percorrer.

A partir do jQuery 1.2.6 você pode usar uma das principais funções do CSS , heighte width(ou outerHeighte outerWidth, conforme o caso).

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

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

Apenas para o caso de ser útil a alguém, coloquei uma caixa de texto, botão e div todos com o mesmo 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>

Eu tentei em chrome, firefox e ie-edge, tentei com jquery e sem e tentei com e sem box-sizing:border-box. Sempre com<!DOCTYPE html>

Os 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
fonte
1
Só para ficar claro ... algum desses navegadores faz algo diferente um do outro? Não consigo encontrar nenhuma diferença ... Além disso, ainda não recebi votos negativos, mas isso realmente não responde diretamente à pergunta, embora possa ser facilmente editada para isso.
Zach Lysobey
1
Não tinha como objetivo responder à pergunta - ela já foi respondida. Apenas algumas informações úteis e, sim, todos os principais navegadores da versão mais recente concordam com esses valores - o que é uma coisa boa.
Graham
3
Bem ... se sua intenção não é responder à pergunta, isso realmente não pertence aqui (como uma "resposta"). Eu consideraria colocar isso em algum recurso externo (talvez uma essência do GitHub ou uma postagem no blog) e vinculá-lo em um comentário na pergunta original ou em uma das respostas.
Zach Lysobey
21
@ZachLysobey Há exceções em todas as regras - e isso é algo interessante e útil de se ver.
Dan Nissenbaum 12/09
16

De acordo com o MDN: Determinando as Dimensões dos Elementos

offsetWidthe offsetHeightretorne a "quantidade total de espaço que um elemento ocupa, incluindo a largura do conteúdo visível, barras de rolagem (se houver), preenchimento e borda"

clientWidthe clientHeightretornar "quanto espaço o conteúdo real exibido ocupa, incluindo preenchimento, mas sem incluir a borda, as margens ou as barras de rolagem"

scrollWidthe scrollHeightretorne o "tamanho real do conteúdo, independentemente da quantidade visível no momento"

Portanto, depende se o conteúdo medido deve estar fora da área visível atual.

HarlemSquirrel
fonte
5

Você só precisa calculá-lo para o IE7 e versões anteriores (e apenas se o conteúdo não tiver tamanho fixo). Sugiro o uso de comentários condicionais em HTML para limitar o hack a IEs antigos que não suportam CSS2. Para todos os outros navegadores, use este:

<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 é a solução perfeita. Centra-se <div>em qualquer tamanho e encolhe-o de acordo com o tamanho de seu conteúdo.

Kornel
fonte
3

É fácil modificar os estilos dos elementos, mas meio complicado de ler o valor.

O JavaScript não pode ler nenhuma propriedade de estilo de elemento (elem.style) proveniente de css (interno / externo), a menos que você use a chamada de método incorporada getComputedStyle em javascript.

getComputedStyle (elemento [, pseudo])

Elemento: o elemento para o qual ler o valor.
pseudo: um pseudoelemento, se necessário, por exemplo: :: before. Uma cadeia vazia ou nenhum argumento significa o próprio elemento.

O resultado é um objeto com propriedades de estilo, como elem.style, mas agora com relação a todas as classes css.

Por exemplo, aqui o estilo não vê a margem:

<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>

Então, modifique seu código javaScript para incluir o getComputedStyle do elemento que você deseja obter, largura / altura ou outro 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 computados e resolvidos

Existem dois conceitos no CSS:

Um valor de estilo calculado é o valor após todas as regras de CSS e a herança de CSS serem aplicadas, como resultado da cascata de CSS. Pode parecer com altura: 1em ou tamanho da fonte: 125%.

Um valor de estilo resolvido é aquele finalmente aplicado ao elemento. Valores como 1em ou 125% são relativos. O navegador pega o valor calculado e torna todas as unidades fixas e absolutas, por exemplo: height: 20px ou tamanho da fonte: 16px. Para propriedades de geometria, os valores resolvidos podem ter um ponto flutuante, como largura: 50,5px.

Há muito tempo, o getComputedStyle foi criado para obter valores computados, mas os valores resolvidos são muito mais convenientes e o padrão foi alterado.
Hoje em dia, getComputedStyle realmente retorna o valor resolvido da propriedade.

Observe:

getComputedStyle requer o nome completo da propriedade

Você sempre deve solicitar a propriedade exata que deseja, como paddingLeft ou height ou width. Caso contrário, o resultado correto não é garantido.

Por exemplo, se houver propriedades paddingLeft / paddingTop, o que devemos obter para getComputedStyle (elem) .padding? Nada, ou talvez um valor "gerado" a partir de campos conhecidos? Não há regra padrão aqui.

Existem outras inconsistências. Como exemplo, alguns navegadores (Chrome) mostram 10px no documento abaixo, e alguns deles (Firefox) - não:

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

para mais informações https://javascript.info/styles-and-classes

Lekens
fonte
1

element.offsetWidth e element.offsetHeight devem funcionar, conforme sugerido na postagem anterior.

No entanto, se você quiser apenas centralizar o conteúdo, existe uma maneira melhor de fazê-lo. Supondo que você use xhtml strict DOCTYPE. defina a margem: 0, propriedade automática e largura necessária em px para a tag body. O conteúdo fica alinhado ao centro com a página.

questzen
fonte
1
Acho que ele quer para centralizá-la na vertical também, o que é uma dor direita com CSS menos que você pode encontrar alguns critérios específicos (por exemplo, o conteúdo de tamanho conhecido)
Greg
1

... parece CSS ajudar a colocar div no 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>
sanecin
fonte
0

Também você pode usar este código:

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

var h = divID.style.pixelHeight;
Sergio
fonte
1
Hmm, funciona no Chrome e IE9, não parece funcionar no Firefox. Funciona apenas para certos tipos de documentos?
precisa saber é o seguinte
1
pixelHeight era uma invenção Internet Explorer que não deve ser mais utilizado stackoverflow.com/q/17405066/2194590
HolgerJeromin
0

se você precisar centralizá-lo na porta de exibição do navegador; você pode conseguir isso apenas com CSS

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

Aqui está o código para o WKWebView que determina a altura do elemento Dom específico (não funciona corretamente para toda a 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
fonte
só para ficar claro, esse é o swiftcódigo do iOS , certo? Não é JavaScript. Estou retendo um voto negativo (b / c isso pode realmente ser bastante útil), mas observe que isso não responde à pergunta e provavelmente seria mais apropriado em outra pergunta específica do iOS. Se já não existe, considere pedir uma e responder automaticamente.
Zach Lysobey 30/10
-3

Se offsetWidth retornar 0, você poderá obter a propriedade width do estilo do elemento e procurar um número. "100 px" -> 100

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

Arko
fonte