2009-12-03 8 views
27

Je suis actuellement en train d'étendre le lavalamp plugin pour travailler dans des menus déroulants mais j'ai rencontré un petit problème. J'ai besoin de connaître le offsetWidth d'un élément caché. Maintenant clairement cette question n'a aucun sens, plutôt ce que je cherche est le offsetWidth de l'élément s'il n'était pas caché.Trouver la largeur "potentielle" d'un élément caché

Est-ce la solution pour le montrer, saisir la largeur, puis se cacher à nouveau? Il doit y avoir un meilleur moyen ...

Répondre

34

La seule chose que je peux penser est de le montrer (ou un clone de celui-ci) pour permettre la récupération de l'offsetWidth.

Pour cette étape de mesure, il suffit de rendre sa position absolue et sa valeur x ou y un grand négatif, de sorte qu'il sera rendu mais pas visible pour l'utilisateur.

+0

Nice one, Peter. Merci. – Gausie

+0

Voici un article sur ce sujet. Un problème que cette méthode pourrait rencontrer est de réinitialiser la position à la valeur d'origine. L'utilisation de la méthode d'échange fonctionne bien dans cette situation. http://bit.ly/6KwGzm –

+1

Vous n'avez pas besoin de le réinitialiser à sa position d'origine si vous clonez l'élément. Supprimez simplement le clone après avoir récupéré sa position. – ajbeaven

27

La largeur d'un élément CSS visibility: hidden est mesurable. C'est seulement quand c'est display: none qu'il n'est pas rendu du tout. Donc, s'il est certain que les éléments seront positionnés de façon absolue (pour ne pas modifier la disposition), utilisez simplement css('visibility', 'hidden') pour masquer votre élément au lieu de hide() et vous devriez mesurer la largeur.

Sinon, oui, show-measure-hide fonctionne.

0

thats parce que son via via caché: aucun; Ce que j'ai fait dans le passé est de faire un div "récepteur" sur lequel j'utilise le positionnement absolu pour le sortir de la page. Ensuite, je charge le nouvel élément dans celui, saisissez les dimensions et retirez-le quand im fait - puis retirez le récepteur quand im fait.

Une autre chose que vous pouvez faire est de ne pas utiliser hide(); mais pour définir la visibilité: caché; afficher: ; Cependant, cela signifie que la zone vide sera rendue à chaque fois que le nœud est attaché.

2

Deux options:

  1. position de l'élément extérieur de la fenêtre (ex: left:-10000px)
  2. utilisation visibility: hidden ou opacity: 0 au lieu de hide().

L'une ou l'autre façon fonctionnera comme cacher l'élément tout en étant capable d'obtenir la largeur calculée. Soyez prudent avec Safari sur thi, il est terriblement rapide et parfois trop rapide ...

11

Vous pouvez utiliser la fonction suivante pour obtenir la largeur externe d'un élément dans un conteneur masqué.

$.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; 
}; 

Vous pouvez changer .outerWidth()-.offsetWidth() pour votre situation.

La fonction clone d'abord l'élément en le copiant à un endroit où il sera visible. Il récupère ensuite la largeur de décalage et supprime finalement le clone. L'extrait suivant illustre une situation où cette fonction serait parfait:

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

S'il vous plaît être conscient que s'il y a CSS appliqué à l'élément qui change la largeur de l'élément qui ne sera pas appliquée si elle est un descendant direct du corps, alors cette méthode ne fonctionnera pas.Donc, quelque chose comme cela signifie que la fonction ne fonctionne pas:

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

Vous devez soit:

  • changement la spécificité du-à-dire sélecteur CSS. .measure-me { width: 100px; }
  • changez le appendTo() pour ajouter le clone à un endroit où votre CSS sera également appliqué au clone. Assurez-vous que là où vous ne le mettez, que l'élément sera visible: .appendTo('.container-outer')

Encore une fois, cette fonction suppose que l'élément n'est caché parce qu'il est à l'intérieur d'un conteneur caché. Si l'élément lui-même est display:none, vous pouvez simplement ajouter du code pour rendre le clone visible avant de récupérer sa largeur de décalage. Quelque chose comme ceci:

$.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; 
} 

Cela fonctionnerait dans une situation comme celle-ci:

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

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

Intéressant, mais il ne fonctionnera pas avec n'importe quel type d'héritage de style ou de style dicté par le conteneur. –

+0

Oui, comme mentionné dans ma réponse. Il y a quelques suggestions pour contourner le problème, mais je suis d'accord, ce n'est pas parfait. – ajbeaven

0

J'essaie de trouver la fonction de travail pour l'élément caché, mais je me rends compte que CSS est complexe beaucoup plus que tout le monde pense. Il y a beaucoup de nouvelles techniques de mise en page dans CSS3 qui pourraient ne pas fonctionner pour toutes les réponses précédentes comme les boîtes flexibles, les grilles, les colonnes ou même les éléments à l'intérieur d'un élément parent complexe.

exemple Flexibox enter image description here

Je pense que la seule solution simple & durable est rendu en temps réel. À ce moment-là, le navigateur devrait vous donner que taille de l'élément correct.

Malheureusement, JavaScript ne fournit aucun événement direct à notifier lorsque l'élément est affiché ou masqué. Cependant, je crée une fonction basée sur l'API DOM Attribute Modified qui va exécuter la fonction callback lorsque la visibilité de l'élément est modifiée.

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

    // render or adjust something 
}); 

Pour plus d'informations, veuillez visiter mon projet GitHub.

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

Démo: http://jsbin.com/ETiGIre/7

0

Ce que je faisais était; Au moment de masquer cet élément, stocké sa largeur dans son ensemble de données. Cela ne fonctionnera que si vous pouvez vous cacher par programmation.

ie.

Lorsque vous vous cachez;

var elem = $("selectorOfElement"); 

elem.dataset.orgWidth = elem.clientWidth; 

plus tard lors de l'obtention;

var elem = $("selectorOfElement"); 

var originalWidthWas = elem.dataset.orgWidth; 
1

Actual jQuery plugin!

Utilisation:

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>

Questions connexes