2013-09-22 2 views
8

Je suis en train de créer un concepteur de thème html/javascript pour un CMS. Les éléments sont positionnés de manière absolue et peuvent être déplacés/redimensionnés à l'aide de la souris, et/ou contenir un texte éditable dont la hauteur peut être déterminée par le nombre de lignes. Cependant, je suis confronté au problème où la hauteur d'un élément parent ne s'étend pas pour inclure ses enfants absolument positionnés.Augmenter la hauteur pour inclure les enfants en position absolue

code minimal (aussi JSFiddle here):

<style> 
    div.layer { position: absolute } 
    div.layer1 { width: 400px; border: 1px solid #ccc } 
    div.layer2 { top: 15px; left: 100px; width: 100px; border: 1px solid blue } 
</style> 
<div class="layer layer1">container should expand to the bottom of the child. 
    <div class="layer layer2" contentEditable>Child with<br/>editable text.</div> 
</div> 

Une solution CSS seulement est idéal et je ne suis pas préoccupé par les anciens navigateurs. Mais je suis surtout à la recherche d'un moyen d'éviter le javascript sur chaque page en utilisant un thème créé pour définir leur hauteur (puisque les pages avec le même thème peuvent avoir différentes quantités de texte).

Il existe déjà quelques questions similaires, mais leurs réponses acceptées (par exemple, ne pas utiliser le positionnement absolu) ne fonctionneront pas dans mon cas. À moins qu'il y ait un moyen d'avoir plusieurs couches d'éléments draggable/redimensionnables sans qu'elles soient position: absolute.

+1

Je ne sais pas, mais ne pense pas qu'il peut être fait avec CSS pur. –

Répondre

17

J'ai trouvé une solution pure css! En résumé:

  1. Définissez les éléments enfants sur la position: relative au lieu de absolue.
  2. Définir leur marge-droite pour être leur largeur négative, pour leur donner zéro largeur effective, et les faire flotter: à gauche pour les garder tous sur la même ligne. Cela fait que tous ont une origine de 0, 0.
  3. Ensuite, nous pouvons définir leurs propriétés left et margin-top pour les positionner absolument dans leurs parents. Notez que margin-top est requis à la place de top parce que top n'appliquera pas le bas de l'élément parent.

JSFiddle here ou un code ci-dessous:

<style> 
    div.layer { position: relative; float: left; } 
    div.layer1 { width: 400px; border: 1px solid black } 
    div.layer2 { margin-top: 20px; left: 100px; width: 100px; margin-right: -100px; border: 1px solid blue } 
    div.layer3 { margin-top: 30px; left: 170px; width: 100px; margin-right: -100px; border: 1px solid red } 
    div.layer4 { margin-top: 30px; left: 20px; width: 60px; margin-right: -60px; border: 1px solid green } 
</style> 
<div class="layer layer1" style="position: relative; display: block; width: 400px; border: 1px solid black;"> 
    Container 
    <div class="layer layer2" contentEditable>Edit me</div> 
    <div class="layer layer3"> 
     <div class="layer layer4" contentEditable>Edit me</div> 
    </div> 
</div> 
+2

C'est vraiment génial. Gloire. +2 Bravo MySpace pour vous (ou +1 points SO). – indextwo

4

éléments positionnés absolus sont retirés du flux, ainsi ignoré par d'autres éléments

la seule façon que vous avez est de définir la position de l'enfant à position: relative, de cette manière, il est possible pour le déplacer à l'aide droite, à gauche, en haut et en bas et aussi changer l'affichage parent à display: inline-block

+1

Merci pour l'idée, mais malheureusement, cela échoue quand il y a plusieurs enfants. La position du second enfant est décalée par rapport à la première, qui est le comportement prévu de la position: relative. – Dwayne

1

Si vous voulez garder les enfants en position absolue, vous pouvez utilisez le script suivant pour redimensionner le conteneur: http://jsfiddle.net/6csrV/7/

var layer1 = document.getElementsByClassName('layer1'), 
    i = 0, len = layer1.length, childHeight; 
for(; i < len; i++) { 
    childHeight = layer1[i].getElementsByClassName('layer')[0].clientHeight; 
    layer1[i].style.height = childHeight + 'px'; 
} 
document.addEventListener('keyup', function(e) { 
    if(e.target.className.indexOf('layer2') !== false) { 
     e.target.parentNode.style.height = e.target.clientHeight + 'px'; 
    } 
}); 
+0

Je vais utiliser une solution similaire à ceci si je ne trouve rien de mieux. Mais cela devient plus complexe quand il y a des douzaines d'éléments imbriqués de diverses manières. Cela et je n'aime pas exécuter javascript sur le chargement de la page pour corriger la mise en page. – Dwayne