2009-12-03 9 views
27

Actualmente extiendo el lavalamp plugin para trabajar en los menús desplegables, pero me he encontrado con un pequeño problema. Necesito saber el offsetWidth de un elemento que está oculto. Ahora claramente esta pregunta no tiene sentido, más bien lo que estoy buscando es el offsetWidth del elemento si no estuviera oculto.Encuentra el ancho "potencial" de un elemento oculto

¿Es la solución para mostrarlo, tomar el ancho y luego ocultarlo de nuevo? Debe haber una mejor manera ...

Respuesta

34

Lo único que se me ocurre es mostrarlo (o un clon de él) para permitir la recuperación del offsetWidth.

Para este paso de medición, simplemente haga que su posición sea absoluta y su valor xoy sea un gran negativo, por lo que se renderizará pero no será visible para el usuario.

+0

uno de los buenos, Peter. Gracias. – Gausie

+0

Aquí hay una publicación de blog sobre este tema. Un problema que este método podría enfrentar es restablecer la posición al valor original. Usar el método de intercambio funciona bien en esta situación. http://bit.ly/6KwGzm –

+1

No necesita restablecerlo a su posición original si está clonando el elemento. Simplemente elimine el clon después de haber recuperado su posición. – ajbeaven

27

El ancho de un elemento que tiene CSS visibility: hidden es mensurable. Solo cuando es display: none no se procesa. Por lo tanto, si es seguro que los elementos estarán absolutamente posicionados (para que no causen un cambio en el diseño cuando se muestren), simplemente use css('visibility', 'hidden') para ocultar su elemento en lugar de hide() y debe medir el ancho.

De lo contrario, sí, show-measure-hide funciona.

0

eso es porque está oculto a través de la pantalla: ninguno; Lo que he hecho en el pasado es crear un div "reciever" en el que use posicionamiento absoluto para sacarlo de la página. Luego, cargué el nuevo elemento en eso, tomé las dimensiones y luego lo eliminé cuando terminé; luego, quité el receptor cuando terminé.

Otra cosa que puede hacer es no usar hide(); pero para establecer la visibilidad: oculto; monitor: ; Sin embargo, esto significa que el área en blanco se representará siempre que el nodo esté conectado.

2

dos opciones:

  1. posicionar el elemento de fuera de la ventana gráfica (ex: left:-10000px)
  2. uso visibility: hidden o opacity: 0 en lugar de hide().

De cualquier forma funcionará como ocultar el elemento pero aún así poder obtener el ancho calculado. Tenga cuidado con Safari en este caso, es terriblemente rápido y a veces demasiado rápido ...

11

Puede usar la siguiente función para obtener el ancho exterior de un elemento que es dentro de un contenedor oculto.

$.fn.getHiddenOffsetWidth = function() { 
    // save a reference to a cloned element that can be measured 
    var $hiddenElement = $(this).clone().appendTo('body'); 

    // calculate the width of the clone 
    var width = $hiddenElement.outerWidth(); 

    // remove the clone from the DOM 
    $hiddenElement.remove(); 

    return width; 
}; 

Puede cambiar .outerWidth()-.offsetWidth() para su situación.

La función primero clona el elemento, copiándolo en un lugar donde será visible. Luego recupera el ancho de desplazamiento y finalmente elimina el clon. El siguiente fragmento ilustra una situación en la que esta función sería perfecto:

<style> 
    .container-inner { 
     display: none; 
    } 

    .measure-me { 
     width: 120px; 
    } 
</style> 

<div class="container-outer"> 
    <div class="container-inner"> 
     <div class="measure-me"></div> 
    </div> 
</div> 

Por favor, tenga en cuenta que si hay CSS aplicada al elemento que cambia la anchura del elemento que no se aplicará si es un descendiente directo del cuerpo, entonces este método no funcionará.Así que algo como esto significará que la función no funciona:

.container-outer .measure-me { 
    width: 100px; 
} 

ya sea que usted necesita:

  • cambiar la especificidad del selector CSS es decir. .measure-me { width: 100px; }
  • cambie el appendTo() para agregar el clon a un lugar donde su CSS también se aplicará al clon. Asegúrese de que donde quiera que haces la idea, de que el elemento será visible: .appendTo('.container-outer')

Una vez más, esta función supone que el elemento sólo se oculta porque es dentro de un contenedor oculto. Si el elemento en sí es display:none, simplemente puede agregar un código para hacer que el clon sea visible antes de recuperar su ancho de desplazamiento. Algo como esto:

$.fn.getHiddenOffsetWidth = function() { 
    var hiddenElement $(this) 
     width = 0; 

    // make the element measurable 
    hiddenElement.show(); 

    // calculate the width of the element 
    width = hiddenElement.outerWidth(); 

    // hide the element again 
    hiddenElement.hide(); 

    return width; 
} 

Esto funcionaría en una situación como esta:

<style> 
    .measure-me { 
     display: none; 
     width: 120px; 
    } 
</style> 

<div class="container"> 
    <div class="measure-me"></div> 
</div> 
+1

Interesante, pero no funcionará con ningún tipo de herencia de estilo, ni con el estilo dictado por un contenedor. –

+0

Sí, como se menciona en mi respuesta. Hay un par de sugerencias para evitar esto, pero estoy de acuerdo, no es perfecto. – ajbeaven

0

trato de encontrar la función de trabajo para el elemento oculto pero se dan cuenta de que el CSS es mucho más compleja de lo que todos piensan. Hay muchas técnicas de diseño nuevas en CSS3 que podrían no funcionar para todas las respuestas anteriores, como cuadro flexible, cuadrícula, columna o incluso elemento dentro del elemento padre complejo.

ejemplo Flexibox enter image description here

Creo que la única solución sostenible es sencilla & renderizado en tiempo real. En ese momento, el navegador debe darle ese tamaño de elemento correcto.

Lamentablemente, JavaScript no proporciona ningún evento directo para notificar cuando el elemento se muestra u oculta. Sin embargo, creo alguna función basada en la API modificada del atributo DOM que ejecutará la función de devolución de llamada cuando se cambie la visibilidad del elemento.

$('[selector]').onVisibleChanged(function(e, isVisible) 
{ 
    var realWidth = $('[selector]').width(); 
    var realHeight = $('[selector]').height(); 

    // render or adjust something 
}); 

Para obtener más información, visite mi proyecto GitHub.

https://github.com/Soul-Master/visible.event.js

demo: http://jsbin.com/ETiGIre/7

0

Lo que hice fue; en el momento de ocultar ese elemento, almacenó su ancho en su conjunto de datos. Solo le servirá si puede ocultarse mediante programación.

ie.

Al ocultar;

var elem = $("selectorOfElement"); 

elem.dataset.orgWidth = elem.clientWidth; 

Más tarde al llegar;

var elem = $("selectorOfElement"); 

var originalWidthWas = elem.dataset.orgWidth; 
1

Actual jQuery plugin!

Uso:

console.log('width without actual: ' + $('#hidden').width()); 
 

 
console.log('width with actual: ' + $('#hidden').actual('width'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.actual/1.0.19/jquery.actual.min.js"></script> 
 

 
<div style="width: 100px; display: none;"> 
 
    <div id="hidden"></div> 
 
</div>

Cuestiones relacionadas