O modelo da caixa CSS é bastante complicado, principalmente quando se trata de rolagem de conteúdo. Enquanto o navegador usa os valores do CSS para desenhar caixas, determinar todas as dimensões usando JS não é simples se você tiver apenas o CSS.
É por isso que cada elemento tem seis propriedades DOM para sua conveniência: offsetWidth
, offsetHeight
, clientWidth
, clientHeight
, scrollWidth
e scrollHeight
. Esses são atributos somente leitura que representam o layout visual atual e todos são números inteiros (possivelmente sujeitos a erros de arredondamento).
Vamos examiná-los em detalhes:
offsetWidth
, offsetHeight
: O tamanho da caixa visual incluindo todas as bordas. Pode ser calculado adicionando width
/ height
e preenchimentos e bordas, se o elemento tiverdisplay: block
clientWidth
, clientHeight
: A parte visual do conteúdo da caixa, sem incluir bordas ou barras de rolagem, mas inclui preenchimento. Não pode ser calculado diretamente do CSS, depende do tamanho da barra de rolagem do sistema.
scrollWidth
, scrollHeight
: O tamanho de todo o conteúdo da caixa, incluindo as partes que estão ocultas atualmente fora da área de rolagem. Não pode ser calculado diretamente do CSS, depende do conteúdo.
Como offsetWidth
leva em conta a largura da barra de rolagem, podemos usá-la para calcular a largura da barra de rolagem por meio da fórmula
scrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth
Infelizmente, podemos obter erros de arredondamento, uma vez offsetWidth
e clientWidth
são sempre inteiros, enquanto os tamanhos reais podem ser fracionada com outros de 1 níveis de zoom.
Note que este
scrollbarWidth = getComputedStyle().width + getComputedStyle().paddingLeft + getComputedStyle().paddingRight - clientWidth
se não funcionar de forma confiável em Chrome, uma vez que os retornos do Chrome width
com barra de rolagem já subtraídos. (Além disso, o Chrome renderiza paddingBottom na parte inferior do conteúdo da rolagem, enquanto outros navegadores não)
element.getBoundingClientRect()
(veja a nota no developer.mozilla.org/en-US/docs/Web/API/Element.clientWidth )naturalWidth
enaturalHeight
scrollHeight
inclui,padding-bottom
masscrollWidth
não inclui?padding-right
clientWidth
paradocument.documentElement.clientWidth
é diferente, uma vez que parece incluir opadding
,borders
emargin
Criei uma versão mais abrangente e mais limpa que algumas pessoas podem achar útil para lembrar qual nome corresponde a qual valor. Usei o código de cores e os rótulos da Chrome Dev Tool são organizados simetricamente para captar analogias mais rapidamente:
Nota 1:
clientLeft
também inclui a largura da barra de rolagem vertical se a direção do texto estiver definida da direita para a esquerda (já que a barra é exibida à esquerda nesse caso)Nota 2: a linha mais externa representa o pai mais próximo posicionado (um elemento cuja
position
propriedade está configurada para um valor diferente destatic
ouinitial
). Portanto, se o contêiner direto não for um elemento posicionado , a linha não representa o primeiro contêiner na hierarquia, mas outro elemento mais alto na hierarquia. Se nenhum pai posicionado for encontrado, o navegador utilizará o elementohtml
oubody
como referênciaEspero que alguém ache útil, apenas meus 2 centavos;)
fonte
Se você deseja usar scrollWidth para obter a LARGURA / ALTURA "REAL" DE CONTEÚDO (como o conteúdo pode ser MAIOR do que a largura / altura-caixa definida por css), a largura / altura do scroll é muito INCRÍVEL, pois alguns navegadores parecem "MOVER" o preenchimento & paddingBOTTOM se o conteúdo for grande. Em seguida, colocam os revestimentos à DIREITA / INFERIOR do "conteúdo muito amplo / alto" (veja a figura abaixo).
==> Portanto, para obter a LARGURA DO CONTEÚDO REAL em alguns navegadores, é necessário subtrair AMBOS os preenchimentos da largura de rolagem e, em alguns navegadores, é necessário apenas subtrair o preenchimento ESQUERDO.
Encontrei uma solução para isso e queria adicionar isso como um comentário, mas não era permitido. Então tirei a foto e a deixei um pouco mais clara em relação aos "paddings movidos" e à "scrollWidth não confiável". Na ÁREA AZUL, você encontra minha solução sobre como obter a LARGURA "REAL" do CONTEÚDO!
Espero que isso ajude a tornar as coisas ainda mais claras!
fonte
Há um bom artigo sobre o MDN que explica a teoria por trás desses conceitos: https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements
Ele também explica as importantes diferenças conceituais entre a largura / altura do boundingClientRect e o offsetWidth / offsetHeight.
Então, para provar a teoria certa ou errada, você precisa de alguns testes. Foi o que fiz aqui: https://github.com/lingtalfi/dimensions-cheatsheet
Está testando para chrome53, ff49, safari9, edge13 e ie11.
Os resultados dos testes provam que a teoria geralmente está correta. Para os testes, criei 3 divs contendo 10 parágrafos de lorem ipsum cada. Algum css foi aplicado a eles:
E aqui estão os resultados:
div1
bcr.height: 330 (chrome53, ff49, safari9, edge13, ie11)
clientWidth: 505 (chrome53, ff49, safari9)
clientHeight: 320 (chrome53, ff49, safari9, edge13, ie11)
scrollWidth: 505 (chrome53, safari9, ff49)
div2
clientHeight: 290 (chrome53, ff49, safari9, edge13, ie11)
scrollWidth: 475 (chrome53, safari9, ff49)
div3
clientHeight: 320 (chrome53, ff49, safari9, edge13, ie11)
scrollWidth: 505 (chrome53, safari9, ff49)
Portanto, além do valor da altura do boundingClientRect (299.9999694824219 em vez do esperado 300) em edge13 e ie11, os resultados confirmam que a teoria por trás disso funciona.
A partir daí, aqui está minha definição desses conceitos:
Nota: a largura da barra de rolagem vertical padrão é 12px em edge13, 15px em chrome53, ff49 e safari9 e 17px em ie11 (feita por medidas no photoshop a partir de capturas de tela e comprovada pelos resultados dos testes).
No entanto, em alguns casos, talvez seu aplicativo não esteja usando a largura da barra de rolagem vertical padrão.
Portanto, dadas as definições desses conceitos, a largura da barra de rolagem vertical deve ser igual a (no pseudo-código):
dimensão do layout: offsetWidth - clientWidth - (borderLeftWidth + borderRightWidth)
dimensão de renderização: boundingClientRect.width - clientWidth - (borderLeftWidth + borderRightWidth)
Observe que, se você não entender o layout versus a renderização, leia o artigo mdn.
Além disso, se você tiver outro navegador (ou se quiser ver os resultados dos testes por conta própria), poderá ver minha página de teste aqui: http://codepen.io/lingtalfi/pen/BLdBdL
fonte