2009-09-24 12 views
19

Necesito medir el offsetHeight de un div que está dentro de un elemento oculto.Necesito encontrar la altura del div oculto en la página (configurado para mostrar: ninguno)

<div id="parent" style="display: none;"> 
    <div id="child">Lorem Ipsum dolor sit amet.</div> 
</div> 

El padre div debe ponerse en "display:none". No tengo control sobre eso. Me doy cuenta de que offsetHeight del div infantil va a ser 0. Necesito encontrar una solución.

Algo con lo que he jugado es cuando la página se carga, copio los nińos de los padres, los inserto en un div en la página que está configurada como "visiblity:hidden". Luego mido la altura de esos elementos y elimino los nodos cuando termine.

¿Alguna otra idea?

Actualización: Lo que terminé tener que hacer era esto:

Usando YUI 2, al cargar la página, me encontré con todos los elementos de ese nombre de clase dado que se ajusta bien a la pantalla: ninguno, o cuyos alto y ancho era 0 (esa es una manera de medir si un elemento existe, o uno de los padres está configurado para mostrar: ninguno). Luego configuro ese elemento para mostrar: bloquear. Luego verifiqué que era el padre de la misma cosa y se lo mostré a los padres hasta que encuentre un padre visible. Una vez que la pantalla es más alta: ningún antecesor está configurado para mostrar: bloquear, puedo medir mi elemento.

Una vez que se miden todos los elementos reinicio todos los elementos para mostrar: ninguno.

Respuesta

18

Necesita hacer visible el elemento para ese momento muy breve mientras obtiene las dimensiones del elemento. En una solución genérica, todos los antepasados ​​generalmente se atraviesan y se hacen visibles. Luego, sus valores display vuelven a los valores originales.

Existen problemas de rendimiento, por supuesto.

Hemos considerado este enfoque en la aplicación Prototype.js pero terminó con getWidth y getHeighthacer único elemento real visible, sin atravesar antepasados.

El problema con las soluciones alternativas, como quitar el elemento del elemento primario "oculto", es que ciertos estilos ya no se pueden aplicar a un elemento una vez que está fuera de su jerarquía "normal". Si usted tiene una estructura como esta:

<div class="foo" style="display:none;"> 
    <div class="bar">...</div> 
</div> 

y estas reglas:

.bar { width: 10em; } 
.foo .bar { width: 15em; } 

luego tomar elemento fuera de su padre en realidad resultar en dimensiones equivocadas.

+1

He considerado esto ... Esto parece que puede ser muy intensivo en recursos ... ¿Qué piensas? –

+0

Publicación editada para responder a sus inquietudes (y algunas ideas sobre un enfoque alternativo). – kangax

+1

No pude ver ningún parpadeo mientras mostraba minuciosamente el elemento. Tomé el enfoque de mostrarlo solo mientras obtenía la altura, luego la ocultaba. Eso es también lo que hace slideToggle() de jQuery. Funciona bien +1 –

13

Puede clonar el elemento, colóquelo completamente en -10000, -10000, mida el clon y destrúyalo.

+0

Si lo clono, tendría que inyectarlo, ¿verdad? –

+0

Sí, tendría que hacerlo, idealmente justo después del original, por lo que cualquier CSS aún está intacto. – James

+0

Brillante idea.Lo hizo en una función jQuery: http://stackoverflow.com/a/12463110/373345 – dsomnus

0

Utilice el índice Z para ocultar el elemento debajo del elemento no transparente, muéstrelo y obtenga la altura.

1

Hasta que se represente el elemento, no tiene altura. Incluso si clona el objeto principal y lo muestra en algún lugar que no puede ser visto por el usuario, no hay garantía de que el clon tendrá la misma altura que el tamaño final del objeto oculto.

Hay muchas cosas que pueden afectar la altura que no se representaría necesariamente en el clon: cualquier cosa en el DOM y su interacción con las reglas de CSS podría causar un cambio en la representación de cualquier otro elemento del DOM. Si no se clona todo el documento (e incluso eso no es infalible), no se puede determinar la altura del objeto oculto.

Si tiene que saber conocer la altura antes de que se muestre al usuario, tendrá que "piratearla" mostrándola por el menor tiempo posible y luego ocultándola nuevamente. Lo más probable es que el usuario vea este inconveniente y no esté satisfecho con el resultado.

+0

El "hipo" se puede evitar moviéndolo fuera de la página usando posicionamiento negativo y usando visibilidad: oculto posiblemente –

+2

Pero si lo mueve fuera de su posición verdadera en la página, no puede _guardar_ que la altura sea la correcta. La única forma en que puede estar 100% seguro de que es correcto es mostrarlo en el lugar. Moverlo a otra parte puede darte la respuesta correcta, pero luego debes aceptar la posibilidad de una diferencia de representación. –

+0

Es por eso que el elemento no debe moverse; más bien - oculto con "visibilidad: oculto". – kangax

1

Entonces, ¿no puede incluso cambiar el display:none; al height:0; overflow:hidden;? Tal vez usted podría anular que en su propia hoja de estilo, así:

div#parent { display: block !important; height:0; overflow:hidden; } 

Y entonces como que está utilizando YUI (suponiendo YUI 2) se puede usar esto:

var region = YAHOO.util.Dom.getRegion('child'); 

Para obtener las dimensiones y el desplazamiento de el niño.

0

Lo que terminé tener que hacer era esto:

Usando YUI 2, al cargar la página, me encontré con todos los elementos de ese nombre de clase dado que se ajusta bien a la pantalla: ninguno, o cuya altura y anchura de 0 (Esa es una manera de medir si un elemento existe, o uno de los padres está configurado para mostrar: ninguno). Luego configuro ese elemento para mostrar: bloquear. Luego verifiqué que era el padre de la misma cosa y se lo mostré a los padres hasta que encuentre un padre visible. Una vez que la pantalla es más alta: ningún antecesor está configurado para mostrar: bloquear, puedo medir mi elemento.

Una vez que se miden todos los elementos reinicio todos los elementos para mostrar: ninguno.

-5

¿Has probado esto?

setTimeout('alert($(".Var").height());',200); 
1

intenta utilizar:

#parent{ display:block !important; visibility:hidden; position:absolute} 
8

Si utiliza style.display = "none", el elemento tendrá 0 anchura y la altura,
pero utilizando el style.visibility = "hidden" lugar, el elemento tendrá la anchura y la altura calculada por el navegador (como normalmente).

+0

Creo que esta sería la mejor solución. Incluso podría establecer un índice z si el elemento oculto se interpone en el camino. –

4

Así que aquí está la solución de trabajo jQuery basado en la respuesta de lod3n y con la ayuda del comentario de 999:

 
var getHiddenElementHeight = function(element){ 
    var tempId = 'tmp-'+Math.floor(Math.random()*99999);//generating unique id just in case 
    $(element).clone() 
    .css('position','absolute') 
    .css('height','auto').css('width','1000px') 
    //inject right into parent element so all the css applies (yes, i know, except the :first-child and other pseudo stuff.. 
    .appendTo($(element).parent()) 
    .css('left','-10000em') 
    .addClass(tempId).show() 
    h = $('.'+tempId).height() 
    $('.'+tempId).remove() 
    return h; 
} 

disfrutar!

+2

¿Qué pasa si tu padre está oculto? – Rantiev

+0

@Rantiev buena captura, cuando el padre está oculto, todavía devuelve 0 .... –

6

preparó una solución JS puro sin jQuery y sin clonación (que supongo que es más rápido)

var getHeight = function(el) { 
    var el_style  = window.getComputedStyle(el), 
     el_display = el_style.display, 
     el_position = el_style.position, 
     el_visibility = el_style.visibility, 
     el_max_height = el_style.maxHeight.replace('px', '').replace('%', ''), 

     wanted_height = 0; 

    // if its not hidden we just return normal height 
    if(el_display !== 'none' && el_max_height !== '0') { 
     return el.offsetHeight; 
    } 

    // the element is hidden so: 
    // making the el block so we can meassure its height but still be hidden 
    el.style.position = 'absolute'; 
    el.style.visibility = 'hidden'; 
    el.style.display = 'block'; 

    wanted_height  = el.offsetHeight; 

    // reverting to the original values 
    el.style.display = el_display; 
    el.style.position = el_position; 
    el.style.visibility = el_visibility; 

    return wanted_height; 
} 

aquí es la demostración https://jsfiddle.net/xuumzf9k/1/

Por favor, hágamelo saber si usted puede encontrar cualquier mejora a esto (como lo uso en mis proyectos principales)

+3

Será mejor que pienses en que es ancestros https://jsfiddle.net/rantiev/xuumzf9k/2/ – Rantiev

+0

truco genial, gracias! –

+0

El posicionamiento absoluto parece innecesario y afecta la altura, al menos cuando se utilizan párrafos con estilos de navegador predeterminados en Chrome. – curtisblackwell

Cuestiones relacionadas