web-dev-qa-db-fra.com

Rendre absolu positionné div augmenter parent hauteur div

Comme vous pouvez le voir dans le CSS ci-dessous, je veux que l'enfant2 se positionne avant l'enfant1. En effet, le site que je suis en train de développer devrait également fonctionner sur les appareils mobiles, sur lesquels l’enfant2 devrait se trouver en bas, car il contient la navigation que je veux sous le contenu des appareils mobiles. - Pourquoi pas 2 pages maîtres? Ce sont les 2 seules divs qui sont repositionnées dans tout le code HTML, donc 2 pages maîtres pour cette modification mineure sont excessives.

HTML:

<div id="parent">
    <div class="child1"></div>
    <div class="child2"></div>
</div>

CSS:

parent { position: relative; width: 100%; }
child1 { width: auto; margin-left: 160px; }
child2 { width: 145px; position: absolute; top: 0px; bottom: 0px; }

child2 a une hauteur dynamique, car différents sous-sites pourraient avoir plus ou moins d'éléments de navigation.

Je sais que les éléments en position absolue sont supprimés du flux, donc ignorés par les autres éléments.
J'ai essayé de régler overflow:hidden; sur la div parente, mais cela n’a pas aidé, ni le correctif.

Mon dernier recours sera javascript pour repositionner les deux divs en conséquence, mais pour le moment je vais essayer de voir s'il existe un moyen de le faire sans javascript.

156
user557419

Vous avez répondu vous-même à la question: "Je sais que les éléments à positionnement absolu sont supprimés du flux, donc ignorés par les autres éléments." Vous ne pouvez donc pas définir la taille des parents en fonction d'un élément absolument positionné.

Soit vous utilisez des hauteurs fixes, soit vous devez impliquer JS.

125
feeela

Bien qu'il ne soit pas possible d'étirer des éléments avec position: absolute, il existe souvent des solutions permettant d'éviter le positionnement absolu tout en obtenant le même effet. Regardez ce violon qui résout le problème dans votre cas particulier HTTP://JSFIDDLE.NET/GS9Q7/ 

L'astuce consiste à inverser l'ordre des éléments en faisant flotter les deux éléments, le premier à droite, le second à gauche, de sorte que le second apparaisse en premier.

.child1 {
    width: calc(100% - 160px);
    float: right;
}
.child2 {
    width: 145px;
    float: left;
}

Enfin, ajoutez un clearfix au parent et vous avez terminé (voir le violon pour la solution complète).

En règle générale, tant que l'élément avec la position absolue est placé en haut de l'élément parent, il y a de bonnes chances que vous trouviez une solution de contournement en faisant flotter l'élément.

11
lex82

Feeela a raison mais vous pouvez obtenir un parent div en contractant/développant un élément enfant si vous inversez votre position div comme ceci: 

.parent{
    postion: absolute;
    /* position it in the browser using the `left`, `top` and `margin` 
       attributes */
}

.child{
    position: relative;
    height: 100%;
    width: 100%;

    overflow: hidden;
    /* to pad or move it around using `left` and `top` inside the parent */
}

Cela devrait fonctionner pour vous.

8
ChrisC

Il existe un moyen assez simple de résoudre ce problème.

Vous devez simplement dupliquer le contenu de enfant1 et enfant2 dans les div relatifs avec display: aucun dans div parent. Dites child1_1 et child2_2. Placez child2_2 en haut et child1_1 en bas.

Lorsque votre jquery (ou autre) appelle le div absolu, il suffit de définir le div relatif correspondant (child1_1 ou child2_2) avec display: block AND visibilité: hidden L'enfant relatif sera toujours invisible mais augmentera la div du parent.

7
MMB

Il y a un hack très simple qui résout ce problème

Voici un codesandbox qui illustre la solution: https://codesandbox.io/s/00w06z1n5l

HTML

<div id="parent">
  <div class="hack">
   <div class="child">
   </div>
  </div>
</div>

CSS

.parent { position: relative; width: 100%; }
.hack { position: absolute; left:0; right:0; top:0;}
.child { position: absolute; left: 0; right: 0; bottom:0; }

vous pouvez jouer avec le positionnement de la partition de hack pour modifier le positionnement de l'enfant.

Voici un extrait:

html {
  font-family: sans-serif;
  text-align: center;
}

.container {
  border: 2px solid gray;
  height: 400px;
  display: flex;
  flex-direction: column;
}

.stuff-the-middle {
  background: papayawhip
    url("https://camo.githubusercontent.com/6609e7239d46222bbcbd846155351a8ce06eb11f/687474703a2f2f692e696d6775722e636f6d2f4e577a764a6d6d2e706e67");
  flex: 1;
}

.parent {
  background: palevioletred;
  position: relative;
}

.hack {
  position: absolute;
  left: 0;
  top:0;
  right: 0;
}
.child {
  height: 40px;
  background: rgba(0, 0, 0, 0.5);
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
}
    <div class="container">
      <div class="stuff-the-middle">
        I have stuff annoyingly in th emiddle
      </div>
      <div class="parent">
        <div class="hack">
          <div class="child">
            I'm inside of my parent but absolutely on top
          </div>
        </div>
        I'm the parent
        <br /> You can modify my height
        <br /> and my child is always on top
        <br /> absolutely on top
        <br /> try removing this text
      </div>
    </div>

2
bernatfortet

J'ai eu un problème similaire . Pour résoudre ce problème (au lieu de calculer la hauteur de l'iframe à l'aide du corps, du document ou de la fenêtre), j'ai créé un div qui englobe tout le contenu de la page (un div avec un id = "page" par exemple). et puis j'ai utilisé sa hauteur.

2
Juliano

Je suis venu avec une autre solution, que je n'aime pas mais qui fait le travail.

Fondamentalement, dupliquez les éléments enfants de telle sorte que les doublons ne soient pas visibles.

<div id="parent">
    <div class="width-calc">
        <div class="child1"></div>
        <div class="child2"></div>
    </div>

    <div class="child1"></div>
    <div class="child2"></div>
</div>

CSS:

.width-calc {
    height: 0;
    overflow: hidden;
}

Si ces éléments enfants contiennent peu de balisage, l'impact sera faible.

1
btx9000

"Soit vous utilisez des hauteurs fixes, soit vous devez impliquer JS."

Voici l'exemple de JS:

---------- Exemple avec JQuery JS --------------------

    function findEnvelopSizeOfAbsolutelyPositionedChildren(containerSelector){
        var maxX = $(containerSelector).width(), maxY = $(containerSelector).height();

        $(containerSelector).children().each(function (i){
            if (maxX < parseInt($(this).css('left')) + $(this).width()){
                maxX = parseInt($(this).css('left')) + $(this).width();
            }
            if (maxY < parseInt($(this).css('top')) + $(this).height()){
                maxY = parseInt($(this).css('top')) + $(this).height();
            }
        });
        return {
            'width': maxX,
            'height': maxY
        }
    }

    var specBodySize = findEnvelopSizeOfAbsolutelyPositionedSubDivs("#SpecBody");
    $("#SpecBody").width(specBodySize.width);
    $("#SpecBody").height(specBodySize.height);
1
Nikolay

Ceci est très similaire à ce que @ChrisC a suggéré. Il n'utilise pas un élément absolu, mais un élément relatif. Peut-être pourrait travailler pour vous 

<div class="container">
  <div class="my-child"></div>
</div>

Et votre css comme ça:

.container{
    background-color: red;
    position: relative;
    border: 1px solid black;
    width: 100%;
}

.my-child{
    position: relative;
    top: 0;
    left: 100%;
    height: 100px;
    width: 100px;
    margin-left: -100px;
    background-color: blue;
}

https://jsfiddle.net/royriojas/dndjwa6t/

0
roy riojas

Il y a une meilleure façon de faire cela maintenant. Vous pouvez utiliser la propriété bottom.

    .my-element {
      position: absolute;
      bottom: 30px;
    }
0
rlasch

Pensez également à l'approche suivante:

CSS: 

.parent {
  height: 100%;
}
.parent:after {
  content: '';
  display: block;
}

Aussi, puisque vous essayez de repositionner les divs, considérez css grid

0
Iegor Benzyk

En JavaScript pur, il vous suffit de récupérer la hauteur de votre enfant static position.child1 à l'aide de la méthode getComputedStyle (), puis de définir cette valeur de récupération en tant que padding-top pour ce même enfant à l'aide de HTMLElement .style propriété.


Vérifiez et exécutez l'extrait de code suivant pour obtenir un exemple concret de ce que j'ai décrit ci-dessus:

/* JavaScript */

var child1 = document.querySelector(".child1");
var parent = document.getElementById("parent");

var childHeight = parseInt(window.getComputedStyle(child1).height) + "px";
child1.style.paddingTop = childHeight;
/* CSS */

#parent { position: relative; width: 100%; }
.child1 { width: auto; }
.child2 { width: 145px; position: absolute; top: 0px; bottom: 0px; }
html, body { width: 100%;height: 100%; margin: 0; padding: 0; }
<!-- HTML -->

<div id="parent">
    <div class="child1">STATIC</div>
    <div class="child2">ABSOLUTE</div>
</div>

0
AndrewL64